mirror of
https://github.com/TeamNewPipe/NewPipe
synced 2024-12-23 16:40:32 +00:00
UI design and behavior
This commit is contained in:
parent
ba8370bcfd
commit
bfb56b4144
@ -2,7 +2,6 @@ package org.schabi.newpipe.database.playlist.model;
|
|||||||
|
|
||||||
import androidx.room.ColumnInfo;
|
import androidx.room.ColumnInfo;
|
||||||
import androidx.room.Entity;
|
import androidx.room.Entity;
|
||||||
import androidx.room.Ignore;
|
|
||||||
import androidx.room.Index;
|
import androidx.room.Index;
|
||||||
import androidx.room.PrimaryKey;
|
import androidx.room.PrimaryKey;
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package org.schabi.newpipe.local.bookmark;
|
package org.schabi.newpipe.local.bookmark;
|
||||||
|
|
||||||
|
import static org.schabi.newpipe.util.ThemeHelper.shouldUseGridLayout;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
import android.text.InputType;
|
import android.text.InputType;
|
||||||
@ -12,6 +14,8 @@ import androidx.annotation.NonNull;
|
|||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.appcompat.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import androidx.fragment.app.FragmentManager;
|
import androidx.fragment.app.FragmentManager;
|
||||||
|
import androidx.recyclerview.widget.ItemTouchHelper;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
import org.reactivestreams.Subscriber;
|
import org.reactivestreams.Subscriber;
|
||||||
import org.reactivestreams.Subscription;
|
import org.reactivestreams.Subscription;
|
||||||
@ -41,6 +45,7 @@ import io.reactivex.rxjava3.disposables.CompositeDisposable;
|
|||||||
import io.reactivex.rxjava3.disposables.Disposable;
|
import io.reactivex.rxjava3.disposables.Disposable;
|
||||||
|
|
||||||
public final class BookmarkFragment extends BaseLocalListFragment<List<PlaylistLocalItem>, Void> {
|
public final class BookmarkFragment extends BaseLocalListFragment<List<PlaylistLocalItem>, Void> {
|
||||||
|
private static final int MINIMUM_INITIAL_DRAG_VELOCITY = 12;
|
||||||
@State
|
@State
|
||||||
protected Parcelable itemsListState;
|
protected Parcelable itemsListState;
|
||||||
|
|
||||||
@ -48,6 +53,7 @@ public final class BookmarkFragment extends BaseLocalListFragment<List<PlaylistL
|
|||||||
private CompositeDisposable disposables = new CompositeDisposable();
|
private CompositeDisposable disposables = new CompositeDisposable();
|
||||||
private LocalPlaylistManager localPlaylistManager;
|
private LocalPlaylistManager localPlaylistManager;
|
||||||
private RemotePlaylistManager remotePlaylistManager;
|
private RemotePlaylistManager remotePlaylistManager;
|
||||||
|
private ItemTouchHelper itemTouchHelper;
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// Fragment LifeCycle - Creation
|
// Fragment LifeCycle - Creation
|
||||||
@ -98,6 +104,9 @@ public final class BookmarkFragment extends BaseLocalListFragment<List<PlaylistL
|
|||||||
protected void initListeners() {
|
protected void initListeners() {
|
||||||
super.initListeners();
|
super.initListeners();
|
||||||
|
|
||||||
|
itemTouchHelper = new ItemTouchHelper(getItemTouchCallback());
|
||||||
|
itemTouchHelper.attachToRecyclerView(itemsList);
|
||||||
|
|
||||||
itemListAdapter.setSelectedListener(new OnClickGesture<LocalItem>() {
|
itemListAdapter.setSelectedListener(new OnClickGesture<LocalItem>() {
|
||||||
@Override
|
@Override
|
||||||
public void selected(final LocalItem selectedItem) {
|
public void selected(final LocalItem selectedItem) {
|
||||||
@ -126,6 +135,14 @@ public final class BookmarkFragment extends BaseLocalListFragment<List<PlaylistL
|
|||||||
showRemoteDeleteDialog((PlaylistRemoteEntity) selectedItem);
|
showRemoteDeleteDialog((PlaylistRemoteEntity) selectedItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void drag(final LocalItem selectedItem,
|
||||||
|
final RecyclerView.ViewHolder viewHolder) {
|
||||||
|
if (itemTouchHelper != null) {
|
||||||
|
itemTouchHelper.startDrag(viewHolder);
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,6 +183,7 @@ public final class BookmarkFragment extends BaseLocalListFragment<List<PlaylistL
|
|||||||
}
|
}
|
||||||
|
|
||||||
databaseSubscription = null;
|
databaseSubscription = null;
|
||||||
|
itemTouchHelper = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -255,56 +273,9 @@ public final class BookmarkFragment extends BaseLocalListFragment<List<PlaylistL
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
// Utils
|
// Playlist Metadata Manipulation
|
||||||
///////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////*/
|
||||||
|
|
||||||
private void showRemoteDeleteDialog(final PlaylistRemoteEntity item) {
|
|
||||||
showDeleteDialog(item.getName(), remotePlaylistManager.deletePlaylist(item.getUid()));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showLocalDialog(final PlaylistMetadataEntry selectedItem) {
|
|
||||||
final DialogEditTextBinding dialogBinding
|
|
||||||
= DialogEditTextBinding.inflate(getLayoutInflater());
|
|
||||||
dialogBinding.dialogEditText.setHint(R.string.name);
|
|
||||||
dialogBinding.dialogEditText.setInputType(InputType.TYPE_CLASS_TEXT);
|
|
||||||
dialogBinding.dialogEditText.setText(selectedItem.name);
|
|
||||||
|
|
||||||
final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
|
||||||
builder.setView(dialogBinding.getRoot())
|
|
||||||
.setPositiveButton(R.string.rename_playlist, (dialog, which) ->
|
|
||||||
changeLocalPlaylistName(
|
|
||||||
selectedItem.uid,
|
|
||||||
dialogBinding.dialogEditText.getText().toString()))
|
|
||||||
.setNegativeButton(R.string.cancel, null)
|
|
||||||
.setNeutralButton(R.string.delete, (dialog, which) -> {
|
|
||||||
showDeleteDialog(selectedItem.name,
|
|
||||||
localPlaylistManager.deletePlaylist(selectedItem.uid));
|
|
||||||
dialog.dismiss();
|
|
||||||
})
|
|
||||||
.create()
|
|
||||||
.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showDeleteDialog(final String name, final Single<Integer> deleteReactor) {
|
|
||||||
if (activity == null || disposables == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
new AlertDialog.Builder(activity)
|
|
||||||
.setTitle(name)
|
|
||||||
.setMessage(R.string.delete_playlist_prompt)
|
|
||||||
.setCancelable(true)
|
|
||||||
.setPositiveButton(R.string.delete, (dialog, i) ->
|
|
||||||
disposables.add(deleteReactor
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.subscribe(ignored -> { /*Do nothing on success*/ }, throwable ->
|
|
||||||
showError(new ErrorInfo(throwable,
|
|
||||||
UserAction.REQUESTED_BOOKMARK,
|
|
||||||
"Deleting playlist")))))
|
|
||||||
.setNegativeButton(R.string.cancel, null)
|
|
||||||
.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void changeLocalPlaylistName(final long id, final String name) {
|
private void changeLocalPlaylistName(final long id, final String name) {
|
||||||
if (localPlaylistManager == null) {
|
if (localPlaylistManager == null) {
|
||||||
@ -379,5 +350,141 @@ public final class BookmarkFragment extends BaseLocalListFragment<List<PlaylistL
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void saveImmediate() {
|
||||||
|
if (localPlaylistManager == null || remotePlaylistManager == null
|
||||||
|
|| itemListAdapter == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// todo: debounce
|
||||||
|
/*
|
||||||
|
// List must be loaded and modified in order to save
|
||||||
|
if (isLoadingComplete == null || isModified == null
|
||||||
|
|| !isLoadingComplete.get() || !isModified.get()) {
|
||||||
|
Log.w(TAG, "Attempting to save playlist when local playlist "
|
||||||
|
+ "is not loaded or not modified: playlist id=[" + playlistId + "]");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
// todo: is it correct?
|
||||||
|
final List<LocalItem> items = itemListAdapter.getItemsList();
|
||||||
|
for (int i = 0; i < items.size(); i++) {
|
||||||
|
final LocalItem item = items.get(i);
|
||||||
|
if (item instanceof PlaylistMetadataEntry) {
|
||||||
|
changeLocalPlaylistDisplayIndex(((PlaylistMetadataEntry) item).uid, i);
|
||||||
|
} else if (item instanceof PlaylistRemoteEntity) {
|
||||||
|
changeLocalPlaylistDisplayIndex(((PlaylistRemoteEntity) item).getUid(), i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ItemTouchHelper.SimpleCallback getItemTouchCallback() {
|
||||||
|
int directions = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
|
||||||
|
if (shouldUseGridLayout(requireContext())) {
|
||||||
|
directions |= ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
|
||||||
|
}
|
||||||
|
return new ItemTouchHelper.SimpleCallback(directions,
|
||||||
|
ItemTouchHelper.ACTION_STATE_IDLE) {
|
||||||
|
@Override
|
||||||
|
public int interpolateOutOfBoundsScroll(@NonNull final RecyclerView recyclerView,
|
||||||
|
final int viewSize,
|
||||||
|
final int viewSizeOutOfBounds,
|
||||||
|
final int totalSize,
|
||||||
|
final long msSinceStartScroll) {
|
||||||
|
final int standardSpeed = super.interpolateOutOfBoundsScroll(recyclerView,
|
||||||
|
viewSize, viewSizeOutOfBounds, totalSize, msSinceStartScroll);
|
||||||
|
final int minimumAbsVelocity = Math.max(MINIMUM_INITIAL_DRAG_VELOCITY,
|
||||||
|
Math.abs(standardSpeed));
|
||||||
|
return minimumAbsVelocity * (int) Math.signum(viewSizeOutOfBounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onMove(@NonNull final RecyclerView recyclerView,
|
||||||
|
@NonNull final RecyclerView.ViewHolder source,
|
||||||
|
@NonNull final RecyclerView.ViewHolder target) {
|
||||||
|
if (source.getItemViewType() != target.getItemViewType()
|
||||||
|
|| itemListAdapter == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo: is it correct
|
||||||
|
final int sourceIndex = source.getBindingAdapterPosition();
|
||||||
|
final int targetIndex = target.getBindingAdapterPosition();
|
||||||
|
final boolean isSwapped = itemListAdapter.swapItems(sourceIndex, targetIndex);
|
||||||
|
if (isSwapped) {
|
||||||
|
// todo
|
||||||
|
//saveChanges();
|
||||||
|
saveImmediate();
|
||||||
|
}
|
||||||
|
return isSwapped;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isLongPressDragEnabled() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isItemViewSwipeEnabled() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSwiped(@NonNull final RecyclerView.ViewHolder viewHolder,
|
||||||
|
final int swipeDir) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// Utils
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
private void showRemoteDeleteDialog(final PlaylistRemoteEntity item) {
|
||||||
|
showDeleteDialog(item.getName(), remotePlaylistManager.deletePlaylist(item.getUid()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showLocalDialog(final PlaylistMetadataEntry selectedItem) {
|
||||||
|
final DialogEditTextBinding dialogBinding
|
||||||
|
= DialogEditTextBinding.inflate(getLayoutInflater());
|
||||||
|
dialogBinding.dialogEditText.setHint(R.string.name);
|
||||||
|
dialogBinding.dialogEditText.setInputType(InputType.TYPE_CLASS_TEXT);
|
||||||
|
dialogBinding.dialogEditText.setText(selectedItem.name);
|
||||||
|
|
||||||
|
final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||||
|
builder.setView(dialogBinding.getRoot())
|
||||||
|
.setPositiveButton(R.string.rename_playlist, (dialog, which) ->
|
||||||
|
changeLocalPlaylistName(
|
||||||
|
selectedItem.uid,
|
||||||
|
dialogBinding.dialogEditText.getText().toString()))
|
||||||
|
.setNegativeButton(R.string.cancel, null)
|
||||||
|
.setNeutralButton(R.string.delete, (dialog, which) -> {
|
||||||
|
showDeleteDialog(selectedItem.name,
|
||||||
|
localPlaylistManager.deletePlaylist(selectedItem.uid));
|
||||||
|
dialog.dismiss();
|
||||||
|
})
|
||||||
|
.create()
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showDeleteDialog(final String name, final Single<Integer> deleteReactor) {
|
||||||
|
if (activity == null || disposables == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
new AlertDialog.Builder(activity)
|
||||||
|
.setTitle(name)
|
||||||
|
.setMessage(R.string.delete_playlist_prompt)
|
||||||
|
.setCancelable(true)
|
||||||
|
.setPositiveButton(R.string.delete, (dialog, i) ->
|
||||||
|
disposables.add(deleteReactor
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(ignored -> { /*Do nothing on success*/ }, throwable ->
|
||||||
|
showError(new ErrorInfo(throwable,
|
||||||
|
UserAction.REQUESTED_BOOKMARK,
|
||||||
|
"Deleting playlist")))))
|
||||||
|
.setNegativeButton(R.string.cancel, null)
|
||||||
|
.show();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
package org.schabi.newpipe.local.holder;
|
package org.schabi.newpipe.local.holder;
|
||||||
|
|
||||||
|
import android.view.MotionEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import org.schabi.newpipe.R;
|
||||||
import org.schabi.newpipe.database.LocalItem;
|
import org.schabi.newpipe.database.LocalItem;
|
||||||
import org.schabi.newpipe.database.playlist.PlaylistMetadataEntry;
|
import org.schabi.newpipe.database.playlist.PlaylistMetadataEntry;
|
||||||
import org.schabi.newpipe.local.LocalItemBuilder;
|
import org.schabi.newpipe.local.LocalItemBuilder;
|
||||||
@ -13,13 +15,16 @@ import org.schabi.newpipe.util.Localization;
|
|||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
|
|
||||||
public class LocalPlaylistItemHolder extends PlaylistItemHolder {
|
public class LocalPlaylistItemHolder extends PlaylistItemHolder {
|
||||||
|
private final View itemHandleView;
|
||||||
|
|
||||||
public LocalPlaylistItemHolder(final LocalItemBuilder infoItemBuilder, final ViewGroup parent) {
|
public LocalPlaylistItemHolder(final LocalItemBuilder infoItemBuilder, final ViewGroup parent) {
|
||||||
super(infoItemBuilder, parent);
|
this(infoItemBuilder, R.layout.list_playlist_bookmark_item, parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalPlaylistItemHolder(final LocalItemBuilder infoItemBuilder, final int layoutId,
|
LocalPlaylistItemHolder(final LocalItemBuilder infoItemBuilder, final int layoutId,
|
||||||
final ViewGroup parent) {
|
final ViewGroup parent) {
|
||||||
super(infoItemBuilder, layoutId, parent);
|
super(infoItemBuilder, layoutId, parent);
|
||||||
|
itemHandleView = itemView.findViewById(R.id.itemHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -38,6 +43,20 @@ public class LocalPlaylistItemHolder extends PlaylistItemHolder {
|
|||||||
|
|
||||||
PicassoHelper.loadPlaylistThumbnail(item.thumbnailUrl).into(itemThumbnailView);
|
PicassoHelper.loadPlaylistThumbnail(item.thumbnailUrl).into(itemThumbnailView);
|
||||||
|
|
||||||
|
itemHandleView.setOnTouchListener(getOnTouchListener(item));
|
||||||
|
|
||||||
super.updateFromItem(localItem, historyRecordManager, dateTimeFormatter);
|
super.updateFromItem(localItem, historyRecordManager, dateTimeFormatter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private View.OnTouchListener getOnTouchListener(final PlaylistMetadataEntry item) {
|
||||||
|
return (view, motionEvent) -> {
|
||||||
|
view.performClick();
|
||||||
|
if (itemBuilder != null && itemBuilder.getOnItemSelectedListener() != null
|
||||||
|
&& motionEvent.getActionMasked() == MotionEvent.ACTION_DOWN) {
|
||||||
|
itemBuilder.getOnItemSelectedListener().drag(item,
|
||||||
|
LocalPlaylistItemHolder.this);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
package org.schabi.newpipe.local.holder;
|
package org.schabi.newpipe.local.holder;
|
||||||
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import org.schabi.newpipe.R;
|
||||||
import org.schabi.newpipe.database.LocalItem;
|
import org.schabi.newpipe.database.LocalItem;
|
||||||
import org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity;
|
import org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity;
|
||||||
import org.schabi.newpipe.extractor.NewPipe;
|
import org.schabi.newpipe.extractor.NewPipe;
|
||||||
@ -14,14 +17,17 @@ import org.schabi.newpipe.util.Localization;
|
|||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
|
|
||||||
public class RemotePlaylistItemHolder extends PlaylistItemHolder {
|
public class RemotePlaylistItemHolder extends PlaylistItemHolder {
|
||||||
|
private final View itemHandleView;
|
||||||
|
|
||||||
public RemotePlaylistItemHolder(final LocalItemBuilder infoItemBuilder,
|
public RemotePlaylistItemHolder(final LocalItemBuilder infoItemBuilder,
|
||||||
final ViewGroup parent) {
|
final ViewGroup parent) {
|
||||||
super(infoItemBuilder, parent);
|
this(infoItemBuilder, R.layout.list_playlist_bookmark_item, parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
RemotePlaylistItemHolder(final LocalItemBuilder infoItemBuilder, final int layoutId,
|
RemotePlaylistItemHolder(final LocalItemBuilder infoItemBuilder, final int layoutId,
|
||||||
final ViewGroup parent) {
|
final ViewGroup parent) {
|
||||||
super(infoItemBuilder, layoutId, parent);
|
super(infoItemBuilder, layoutId, parent);
|
||||||
|
itemHandleView = itemView.findViewById(R.id.itemHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -46,6 +52,20 @@ public class RemotePlaylistItemHolder extends PlaylistItemHolder {
|
|||||||
|
|
||||||
PicassoHelper.loadPlaylistThumbnail(item.getThumbnailUrl()).into(itemThumbnailView);
|
PicassoHelper.loadPlaylistThumbnail(item.getThumbnailUrl()).into(itemThumbnailView);
|
||||||
|
|
||||||
|
itemHandleView.setOnTouchListener(getOnTouchListener(item));
|
||||||
|
|
||||||
super.updateFromItem(localItem, historyRecordManager, dateTimeFormatter);
|
super.updateFromItem(localItem, historyRecordManager, dateTimeFormatter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private View.OnTouchListener getOnTouchListener(final PlaylistRemoteEntity item) {
|
||||||
|
return (view, motionEvent) -> {
|
||||||
|
view.performClick();
|
||||||
|
if (itemBuilder != null && itemBuilder.getOnItemSelectedListener() != null
|
||||||
|
&& motionEvent.getActionMasked() == MotionEvent.ACTION_DOWN) {
|
||||||
|
itemBuilder.getOnItemSelectedListener().drag(item,
|
||||||
|
RemotePlaylistItemHolder.this);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
84
app/src/main/res/layout/list_playlist_bookmark_item.xml
Normal file
84
app/src/main/res/layout/list_playlist_bookmark_item.xml
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/itemRoot"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?attr/selectableItemBackground"
|
||||||
|
android:clickable="true"
|
||||||
|
android:focusable="true"
|
||||||
|
android:padding="@dimen/video_item_search_padding">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/itemThumbnailView"
|
||||||
|
android:layout_width="90dp"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:layout_alignParentStart="true"
|
||||||
|
android:layout_alignParentLeft="true"
|
||||||
|
android:layout_alignParentTop="true"
|
||||||
|
android:layout_marginRight="@dimen/video_item_search_image_right_margin"
|
||||||
|
android:scaleType="centerCrop"
|
||||||
|
android:src="@drawable/dummy_thumbnail_playlist"
|
||||||
|
tools:ignore="RtlHardcoded" />
|
||||||
|
|
||||||
|
<org.schabi.newpipe.views.NewPipeTextView
|
||||||
|
android:id="@+id/itemStreamCountView"
|
||||||
|
android:layout_width="45dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_alignTop="@id/itemThumbnailView"
|
||||||
|
android:layout_alignRight="@id/itemThumbnailView"
|
||||||
|
android:layout_alignBottom="@id/itemThumbnailView"
|
||||||
|
android:background="@color/playlist_stream_count_background_color"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingTop="4dp"
|
||||||
|
android:paddingBottom="6dp"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||||
|
android:textColor="@color/duration_text_color"
|
||||||
|
android:textSize="@dimen/video_item_search_duration_text_size"
|
||||||
|
android:textStyle="bold"
|
||||||
|
app:drawableTint="@color/duration_text_color"
|
||||||
|
app:drawableTopCompat="@drawable/ic_playlist_play"
|
||||||
|
tools:ignore="RtlHardcoded"
|
||||||
|
tools:text="3141" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/itemHandle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="55dp"
|
||||||
|
android:layout_alignParentRight="true"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:contentDescription="@string/detail_drag_description"
|
||||||
|
android:paddingLeft="@dimen/video_item_search_image_right_margin"
|
||||||
|
android:scaleType="center"
|
||||||
|
app:srcCompat="@drawable/ic_drag_handle"
|
||||||
|
tools:ignore="RtlHardcoded,RtlSymmetry" />
|
||||||
|
|
||||||
|
<org.schabi.newpipe.views.NewPipeTextView
|
||||||
|
android:id="@+id/itemTitleView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentTop="true"
|
||||||
|
android:layout_toStartOf="@id/itemHandle"
|
||||||
|
android:layout_toLeftOf="@id/itemHandle"
|
||||||
|
android:layout_toRightOf="@+id/itemThumbnailView"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:maxLines="2"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||||
|
android:textSize="@dimen/video_item_search_title_text_size"
|
||||||
|
tools:ignore="RtlHardcoded"
|
||||||
|
tools:text="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc tristique vitae sem vitae blanditLorem ipsumLorem ipsumLorem ipsumLorem ipsumLorem ipsumLorem ipsumLorem ipsum" />
|
||||||
|
|
||||||
|
<org.schabi.newpipe.views.NewPipeTextView
|
||||||
|
android:id="@+id/itemUploaderView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@+id/itemTitleView"
|
||||||
|
android:layout_toRightOf="@+id/itemThumbnailView"
|
||||||
|
android:lines="1"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||||
|
android:textSize="@dimen/video_item_search_uploader_text_size"
|
||||||
|
tools:ignore="RtlHardcoded"
|
||||||
|
tools:text="Uploader" />
|
||||||
|
|
||||||
|
</RelativeLayout>
|
Loading…
Reference in New Issue
Block a user