Я пытаюсь воссоздать поведение редактирования списка iOS в Android с помощью RecyclerView. Вот результат, который я хочу получить (без кнопки удаления):
![iOS edit mode](https://i.stack.imgur.com/ZAj8t.png)
Мне не нужна кнопка редактирования в этом контексте, и я предполагаю, что маленький красный кружок слева всегда есть. Когда вы нажимаете красную круглую кнопку, кнопка удаления прямоугольника должна сдвинуться вправо, сдвинув строку влево.
Я пытался сделать горизонтальный LinearLayout
с двумя детьми. Одним из них является ConstraintLayout
, который имеет основной макет каждой строки, а его ширина установлена на match_parent
, так что он занимает всю ширину экрана. Другой дочерний элемент - кнопка удаления шириной 130dp
, которая по умолчанию будет вне экрана.
Вот код для файла макета:
<FrameLayout 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:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipChildren="false">
<LinearLayout
android:id="@+id/root_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:clipChildren="false">
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="9dp"
android:layout_marginTop="9dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageButton
android:id="@+id/remove_circle_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_remove_circle"
android:background="@null"/>
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@+id/remove_circle_button"
app:layout_constraintTop_toTopOf="parent"
tools:text="some text" />
</android.support.constraint.ConstraintLayout>
<Button
android:id="@+id/remove_main_button"
style="?android:borderlessButtonStyle"
android:layout_width="130dp"
android:layout_height="match_parent"
android:background="@color/red"
android:stateListAnimator="@null"
android:text="Delete"
android:textColor="@color/white" />
</LinearLayout>
</FrameLayout>
Моя логика заключается в том, что когда пользователь нажимает круглую красную кнопку, линейный макет будет анимирован 130dp
влево, делая красную кнопку видимой, в то время как остальная часть строки будет сдвинута влево. Визуально это выглядит достаточно хорошо для наших требований.
Вот код для адаптера RecyclerView, который я написал:
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {
private Context mContext;
private List<String> mStrings;
private SparseBooleanArray mHasDeleteButtonPressed;
public RecyclerViewAdapter(Context context, List<String> strings) {
this.mContext = context;
this.mStrings = strings;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View row = LayoutInflater.from(mContext).inflate(R.layout.rv_item, parent, false);
return new ViewHolder(row);
}
@Override
public void onBindViewHolder(@NonNull final ViewHolder holder, int position) {
String value = mStrings.get(position);
holder.textView.setText(value);
holder.smallDeleteButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
holder.rootLayout.animate().translationX(
-1 * holder.mainDeleteButton.getWidth())
.setDuration(300)
.start();
mHasDeleteButtonPressed.put(holder.getAdapterPosition(), false);
}
});
holder.mainDeleteButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(mContext, "clicked", Toast.LENGTH_LONG).show();
}
});
}
@Override
public int getItemCount() {
return mStrings.size();
}
static class ViewHolder extends RecyclerView.ViewHolder {
LinearLayout rootLayout;
TextView textView;
ImageButton smallDeleteButton;
Button mainDeleteButton;
ViewHolder(View itemView) {
super(itemView);
rootLayout = (LinearLayout) itemView.findViewById(R.id.root_layout);
textView = (TextView) itemView.findViewById(R.id.time_textView);
smallDeleteButton = (ImageButton) itemView.findViewById(R.id.remove_circle_button);
mainDeleteButton = (Button) itemView.findViewById(R.id.remove_main_button);
}
}
}
Логический массив должен знать, какая кнопка каждой строки была нажата, чтобы мы могли анимировать кнопку удаления, если пользователь решил, что не хочет удалять эту строку.
Теоретически, с этим кодом следует нажать кнопку удаления и показать тост, указывающий, что кнопка была нажата. Однако, похоже, что OnClickListener
не устанавливается вообще и не вызывается код внутри метода onClick
. Я подозреваю, что, поскольку кнопка поначалу находится за пределами экрана, и мы заставляем представление не обрезать ее (используя android:clipChildren="false"
в файле XML), метод setOnClickListener
не работает. Потому что, когда я переставляю макет так, чтобы кнопка «Удалить» находилась внутри экрана, приведенный выше код адаптера будет работать без каких-либо изменений.
Так как я могу исправить мою проблему? Я не хочу использовать какие-либо внешние библиотеки, и я хочу сделать это в RecyclerView.
Заранее спасибо