Je suis moi-même un partisan de ListView depuis environ un an depuis que j'ai commencé à développer Android. J'ai pensé: "Parce que ** RecyclerView n'a pas de fonction **, ** C'est une version dégradée de ListView? ** Cela semble difficile et difficile à utiliser, ** Physiologiquement impossible **". ListView a Divider, FastScroll et ChoiceMode. Et pourtant, le successeur ** RecyclerView n'a rien **! Je pense qu'il fut un temps où tout le monde le pensait.
Cependant, en réalité, RecyclerView est plus facile à manipuler. C'est pourquoi il est florissant. Même si ListView est plus facile à implémenter, je vais l'implémenter avec RecyclerView. Cela peut être le résultat de s'entraîner à créer ** RecyclerAdapter désespérément toute la nuit, mais compte tenu de l'extensibilité plus tard, il est préférable de l'implémenter avec RecyclerView. Il a trahi ListView et est maintenant un partisan de RecyclerView.
Disons que l'attrait pratique de RecyclerView est ici, et nous entrerons dans le sujet principal. Il y a beaucoup de bons articles écrits par des adeptes de RecyclerView, alors veuillez les lire également (désolé de les avoir rendus abonnés).
・ Notions de base de RecyclerView ・ Je viens de résumer les bases de RecyclerView
Cela signifie que vous souhaitez créer des éléments sélectionnables. C'est un RecyclerView qui n'a aucune fonctionnalité, mais ** modifions-le en un SelectableRecyclerView que je peux sélectionner directement **. Tel est le contenu de cet article. Cette fonctionnalité est presque certainement implémentée dans les applications récentes, mais étonnamment, il y a peu d'articles qui l'expliquent, j'ai donc écrit cet article.
Comme il est implémenté dans diverses applications, vous savez probablement de quel type de fonction il s'agit, mais je vais faire une liste de fonctions pour le moment.
・ Se comporte généralement comme une vue de recyclage normale ・ Appuyez et maintenez un élément pour entrer en mode de sélection ・ En mode de sélection, vous pouvez également sélectionner avec NormalClick (vous pouvez également sélectionner avec un appui long) -Cliquez sur l'élément sélectionné pour le désélectionner ・ Lorsque tous les éléments sont désélectionnés, le mode de sélection est automatiquement désactivé. ・ Vous pouvez obtenir l'élément sélectionné ・ Dans certains cas, vous pouvez toujours accéder au mode de sélection.
Est-ce à propos de ça? Je pense que ces fonctions sont communes même s'il existe des différences de fonctions selon l'application. Si vous avez besoin d'autre chose, veuillez l'implémenter vous-même. Cette extensibilité est également un bon point de RecyclerView.
Il s'appelle SelectableRecyclerView, j'ai donc pensé en faire une vue, mais compte tenu de l'extensibilité, ce n'est pas le cas. Les fonctions requises diffèrent d'une personne à l'autre. Donc cette fois je vais l'implémenter avec Adapter. Avant cela, j'écrirai sur cet environnement. J'écrirai sur la base du Kotlin de base, mais comme il semble y avoir une demande en Java, j'écrirai également l'implémentation en Java de l'adaptateur lui-même. (Parce que je suis un débutant en Java, merci de me dire si vous faites une erreur)
· Java 8 ・ Kotlin 1.4 ・ Android Studio 4.0.1 ・ SDK cible 30 ・ SDK minimum 24 ・ Construire des outils 30.0.1
<détails> <détails> Activity
L'activité est écrite en Kotlin. Je n'écris pas grand-chose en premier lieu, donc je pense qu'il peut être facilement porté. Lorsque vous appuyez sur le bouton, la position de l'élément sélectionné est reçue de l'adaptateur (getSelectedItemPositions), et la valeur est obtenue et affichée en la comparant à la liste détenue par l'activité. C'est un peu compliqué d'indiquer qu'il est sélectionné. Cette fois, l'état de la sélection est affiché en affichant / masquant la vue, mais vous pouvez également mettre Vérifier dans la case à cocher. Gradle
Pour utiliser RecyclerView, vous devez ajouter à Gradle. Cette fois, j'utilise aussi CardView, etc. donc je dois aussi les écrire. Je l'ai essayé sur Pixel 3 (Android 11). La version Kotlin et la version Java fonctionnent de la même manière.
Cette fois, j'ai créé un RecyclerView sélectionnable. Dans le GIF ci-dessus, isAlwaysSelectable est false, mais si vous le définissez sur true, il sera toujours sélectionnable. Il peut y avoir des erreurs dans Java, donc si vous en trouvez une, veuillez commenter. Veuillez faire LGTM même si cela est utile ou non (c'est un mensonge. Veuillez commenter si cela ne vous aide pas. Je vous aiderai autant que possible)
Recommended Posts
SelectableAdapterWithKotlin.kt
class SelectableAdapterWithKotlin(private val context: Context, private val itemDataList: List<String>, private val isAlwaysSelectable: Boolean): RecyclerView.Adapter<SelectableHolder>(){
//Lorsque isAlwaysSelectable est activé, sélectionnez le mode depuis le début
private var isSelectableMode = isAlwaysSelectable
private val selectedItemPositions = mutableSetOf<Int>()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SelectableHolder {
return SelectableHolder(LayoutInflater.from(parent.context).inflate(R.layout.view_multi_url_card, parent, false))
}
@SuppressLint("SetTextI18n")
override fun onBindViewHolder(holder: SelectableHolder, position: Int) {
with(holder) {
mainTextView.text = itemDataList[position]
subTextView.text = "position $position"
//Si cet élément est sélectionné, cochez-le (Afficher l'image de ✓)
checkLayout.visibility = if (isSelectedItem(position)) View.VISIBLE else View.GONE
cardView.setOnClickListener {
//Traitez comme un clic normal lorsque vous n'êtes pas en mode sélection
if (!isSelectableMode && !isAlwaysSelectable) Toast.makeText(context, "Normal click", Toast.LENGTH_SHORT).show()
else {
if (isSelectedItem(position)) removeSelectedItem(position)
else addSelectedItem(position)
onBindViewHolder(holder, position)
}
}
cardView.setOnLongClickListener {
//Cliquez longuement pour entrer en mode de sélection
if (isSelectedItem(position)) removeSelectedItem(position)
else addSelectedItem(position)
onBindViewHolder(holder, position)
return@setOnLongClickListener true
}
}
}
override fun getItemCount(): Int = itemDataList.size
//Passer le jeu qui enregistre la position de l'élément sélectionné vers l'extérieur
fun getSelectedItemPositions() = selectedItemPositions.toSet()
//Vérifiez si l'élément de la position spécifiée est sélectionné
private fun isSelectedItem(position: Int): Boolean = (selectedItemPositions.contains(position))
//Entrer en mode de sélection lorsque vous n'êtes pas en mode de sélection
private fun addSelectedItem(position: Int){
if(selectedItemPositions.isEmpty() && !isAlwaysSelectable){
isSelectableMode = true
Toast.makeText(context, "Selectable Mode ON", Toast.LENGTH_SHORT).show()
}
selectedItemPositions.add(position)
}
//Si le dernier est désélectionné en mode sélection, désactiver le mode sélection
private fun removeSelectedItem(position: Int){
selectedItemPositions.remove(position)
if(selectedItemPositions.isEmpty() && !isAlwaysSelectable){
isSelectableMode = false
Toast.makeText(context, "Selectable Mode OFF", Toast.LENGTH_SHORT).show()
}
}
}
SelectableHolder.java
public class SelectableHolder extends RecyclerView.ViewHolder {
public TextView mainTextView;
public TextView subTextView;
public CardView cardView;
public ConstraintLayout checkLayout;
public SelectableHolder(View itemView) {
super(itemView);
mainTextView = itemView.findViewById(R.id.VMU_MainText);
subTextView = itemView.findViewById(R.id.VMU_SubText);
cardView = itemView.findViewById(R.id.VMU_CardView);
checkLayout = itemView.findViewById(R.id.VMU_CheckLayout);
}
}
SelectableAdapter.java
public class SelectableAdapter extends RecyclerView.Adapter<SelectableHolder> {
private Context context;
private List<String> itemDataList;
private Boolean isSelectableMode;
private Boolean isAlwaysSelectable;
private Set<Integer> selectedItemPositionsSet = new ArraySet<>();
public SelectableAdapter(Context context, List<String> itemDataList, Boolean isAlwaysSelectable){
this.context = context;
this.itemDataList = itemDataList;
this.isAlwaysSelectable = isAlwaysSelectable;
//Lorsque isAlwaysSelectable est activé, sélectionnez le mode depuis le début
isSelectableMode = isAlwaysSelectable;
}
@NonNull
@Override
public SelectableHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new SelectableHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.view_multi_url_card, parent, false));
}
@SuppressLint("SetTextI18n")
@Override
public void onBindViewHolder(@NonNull final SelectableHolder holder, final int position) {
holder.mainTextView.setText(itemDataList.get(position));
holder.subTextView.setText("position " + position);
//Si cet élément est sélectionné, cochez-le (Afficher l'image de ✓)
if(isSelectedItem(position)){
holder.checkLayout.setVisibility(View.VISIBLE);
}
else {
holder.checkLayout.setVisibility(View.GONE);
}
holder.cardView.setOnClickListener(view -> {
//Traitez comme un clic normal lorsque vous n'êtes pas en mode sélection
if(!isSelectableMode && !isAlwaysSelectable) Toast.makeText(context, "Normal click", Toast.LENGTH_SHORT).show();
else {
if(isSelectedItem(position)) removeSelectedItem(position);
else addSelectedItem(position);
onBindViewHolder(holder, position);
}
});
holder.cardView.setOnLongClickListener(view -> {
//Cliquez longuement pour entrer en mode de sélection
if (isSelectedItem(position)) removeSelectedItem(position);
else addSelectedItem(position);
onBindViewHolder(holder, position);
return true;
});
}
@Override
public int getItemCount() {
return itemDataList.size();
}
//Passer le jeu qui enregistre la position de l'élément sélectionné vers l'extérieur
Set<Integer> getSelectedItemPositions(){
return selectedItemPositionsSet;
}
//Vérifiez si l'élément de la position spécifiée est sélectionné
private Boolean isSelectedItem(int position){
return selectedItemPositionsSet.contains(position);
}
//Entrer en mode de sélection lorsque vous n'êtes pas en mode de sélection
private void addSelectedItem(int position){
if(selectedItemPositionsSet.isEmpty() && !isAlwaysSelectable) {
isSelectableMode = true;
Toast.makeText(context, "Selectable Mode ON", Toast.LENGTH_SHORT).show();
}
selectedItemPositionsSet.add(position);
}
//Si le dernier est désélectionné en mode sélection, désactiver le mode sélection
private void removeSelectedItem(int position){
selectedItemPositionsSet.remove(position);
if(selectedItemPositionsSet.isEmpty() && !isAlwaysSelectable){
isSelectableMode = false;
Toast.makeText(context, "Selectable Mode OFF", Toast.LENGTH_SHORT).show();
}
}
}
Code ci-dessous (cliquez pour développer) summary>
MainActivity.kt
class MainActivity : AppCompatActivity(){
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val itemDataList = listOf("poméranien", "caniche jouet", "Chien shiba", "Bouledogue", "Daxfund", "Dobelman", "beagle", "Labrador retriever", "Golden retriever", "Husky sibérien")
val selectableAdapter = SelectableAdapterWithKotlin(this, itemDataList, false)
AM_RecyclerView.apply {
setHasFixedSize(false)
adapter = selectableAdapter
layoutManager = LinearLayoutManager(this@MainActivity)
}
AM_Button.setOnClickListener {
MaterialAlertDialogBuilder(this)
.setTitle("Élément sélectionné")
.setMessage(selectableAdapter.getSelectedItemPositions().joinToString(separator = "\n") { itemDataList[it] })
.setPositiveButton("OK", null)
.show()
}
}
}
Disposition
Code ci-dessous (cliquez pour développer) summary>
view_multi_url_card.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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">
<androidx.cardview.widget.CardView
android:id="@+id/VMU_CardView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="8dp"
android:foreground="?android:attr/selectableItemBackground"
app:cardCornerRadius="8dp"
app:cardBackgroundColor="@color/colorBackgroundZ4"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.cardview.widget.CardView
android:id="@+id/cardView"
android:layout_width="0dp"
android:layout_height="0dp"
app:cardBackgroundColor="@android:color/transparent"
app:cardElevation="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center">
<ImageView
android:id="@+id/VMU_Image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:scaleType="centerCrop"
android:src="@drawable/im_dog"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/VMU_CheckLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:alpha="0.9"
android:background="@color/colorAccent"
android:visibility="gone">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
android:scaleType="fitCenter"
android:src="@drawable/ic_check"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
<LinearLayout
android:id="@+id/linearLayout"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/cardView"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/VMU_MainText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:singleLine="true"
android:text="Texte principal"
android:textColor="@color/colorChar"
android:textSize="14sp" />
<TextView
android:id="@+id/VMU_SubText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:ellipsize="end"
android:gravity="end"
android:singleLine="true"
android:text="Sous-texte"
android:textColor="@color/colorCharSec"
android:textSize="12sp" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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="match_parent"
android:background="@color/colorBackgroundZ3"
android:orientation="vertical"
tools:context=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/AM_RecyclerView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
<com.google.android.material.button.MaterialButton
android:id="@+id/AM_Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="8dp"
android:text="Afficher les éléments sélectionnés" />
</LinearLayout>
Code ci-dessous (cliquez pour développer) summary>
build.gradle(app)
dependencies {
implementation 'androidx.recyclerview:recyclerview:1.1.0'
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'com.google.android.material:material:1.2.0'
}
J'ai essayé de bouger
finalement