Arayüze sahip yazılımsal projelerde, projenin en az backend yazılımının iyi olması kadar kullanıcısını doğru tanıyan, onların yapacağı eylemlerin kolay, hızlıca ve eğlenceli bir şekilde yapabilmesini sağlayan ekranların tasarlanması da çok önemlidir.
Bu makalemde, Gmail mail silme işleminde olduğu gibi, listelenen içeriklerin animasyonlu bir şekilde kaydırarak (swipe) silme işlemini ve silinen kaydın geri alınabilmesini sağlayan yapıyı örnekleyerek anlatacağım.
Örneğimizi uyguladığımızda aşağıdaki gibi bir ekran görüntüsünü elde edeceğiz.
Android Uygulamalarda Kaydırarak Silme (Swipe To Delete)
Uygulama tasarımınızda, listelenen kayıtları kaydırma animasyonu ile silmek istiyorsanız, ilk öncelikle arayüz kodlama da RecyclerView elementini eklemelisiniz.
RecyclerView arayüz elementini işlevsel hale getirmek için de ItemTouchHelper yardımcı sınıfını kullanmanız gerekir.
Not: Proje kodlarında ItemTouchHelper sınıfıyla alakalı gerekli açıklamaları bulabilirsiniz.
Birkaç adımda RecyclerView widget ile Swipe To Delete özelliğini uygulamamızda nasıl kullanacağımızı görelim.
1-Gerekli Kütüphanelerin Eklenmesi
Android Studio Ide ile oluşturduğum projemin app dizinin altındaki build.gradle dosyasını açıyoruz. Dependencies kod bloklarının arasına aşağıdaki kodları yerleştirerek kütüphanelerimizi yükleyelim.
1 2 |
implementation 'com.android.support:appcompat-v7:28.0.0-rc02' implementation 'com.android.support:design:28.0.0-rc01' |
2-Arayüz Kodlaması
Custom Listview kullanımında olduğu gibi, burada da 2 tane xml dosyasında kodlarımız bulunmalıdır.
İlk olarak, listelenecek item’larda gösterilecek arayüz elemanlarının yerleştirileceği xml dosyasını oluşturmalıyız.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:card_view="http://schemas.android.com/apk/res-auto" android:id="@+id/cardView" android:layout_width="match_parent" android:layout_height="64dp" android:layout_margin="8dp" card_view:cardCornerRadius="0dp" card_view:cardElevation="2dp"> <RelativeLayout android:id="@+id/relativeLayout" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="8dp" android:paddingLeft="8dp" android:paddingRight="8dp"> <TextView android:id="@+id/txtTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:text="Item 1" android:textAppearance="@style/TextAppearance.Compat.Notification.Title" /> </RelativeLayout> </android.support.v7.widget.CardView> |
Diğer xml dosyamıza da RecyclerView widget’ını yerleştirmemiz gerekmektedir.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout 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:id="@+id/coordinatorLayout" android:layout_height="match_parent" tools:context=".MainActivity"> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v7.widget.RecyclerView android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" app:layoutManager="android.support.v7.widget.LinearLayoutManager" /> </RelativeLayout> </android.support.design.widget.CoordinatorLayout> |
3-Java kodlama ile işlevsellik oluşturma
Aşağıdaki SwipeToDeleteCallback.java sınıfıdır. ItemTouchHelper.Callback sınıfından kalıtım alınmıştır. Bu sınıf, kaydırma animasyonunu ve kaydırma sonucunda oluşan görüntüyü sağlar.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.support.annotation.NonNull; import android.support.v4.content.ContextCompat; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.helper.ItemTouchHelper; import android.view.View; abstract public class SwipeToDeleteCallback extends ItemTouchHelper.Callback { Context mContext; private Paint mClearPaint; private ColorDrawable mBackground; private int backgroundColor; private Drawable deleteDrawable; private int intrinsicWidth; private int intrinsicHeight; SwipeToDeleteCallback(Context context) { mContext = context; mBackground = new ColorDrawable(); backgroundColor = Color.parseColor("#b80f0a"); mClearPaint = new Paint(); mClearPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); deleteDrawable = ContextCompat.getDrawable(mContext, R.drawable.ic_delete); intrinsicWidth = deleteDrawable.getIntrinsicWidth(); intrinsicHeight = deleteDrawable.getIntrinsicHeight(); } //Burada kaydırma yönünü belirledik. Yön işaretini makeMovementFlags statik yönteminde döndürdük. @Override public int getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) { return makeMovementFlags(0, ItemTouchHelper.LEFT); } //Bu metod sürükle ve bırak için kullanılır. Kullanmıcagımız için, false döndürdüm. @Override public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder viewHolder1) { return false; } //Bu metodda kaydırmanın gerçekleştiğini gösteren özel görünümümüzü oluşturuyoruz. @Override public void onChildDraw(@NonNull Canvas c, @NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) { super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive); View itemView = viewHolder.itemView; int itemHeight = itemView.getHeight(); boolean isCancelled = dX == 0 && !isCurrentlyActive; if (isCancelled) { clearCanvas(c, itemView.getRight() + dX, (float) itemView.getTop(), (float) itemView.getRight(), (float) itemView.getBottom()); super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive); return; } mBackground.setColor(backgroundColor); mBackground.setBounds(itemView.getRight() + (int) dX, itemView.getTop(), itemView.getRight(), itemView.getBottom()); mBackground.draw(c); int deleteIconTop = itemView.getTop() + (itemHeight - intrinsicHeight) / 2; int deleteIconMargin = (itemHeight - intrinsicHeight) / 2; int deleteIconLeft = itemView.getRight() - deleteIconMargin - intrinsicWidth; int deleteIconRight = itemView.getRight() - deleteIconMargin; int deleteIconBottom = deleteIconTop + intrinsicHeight; deleteDrawable.setBounds(deleteIconLeft, deleteIconTop, deleteIconRight, deleteIconBottom); deleteDrawable.draw(c); super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive); } private void clearCanvas(Canvas c, Float left, Float top, Float right, Float bottom) { c.drawRect(left, top, right, bottom, mClearPaint); } //Burada float değerini döndürüyoruz. örnek 0.7f, RecyclerView satırındaki yüzde 70 kaydırma işleminin kaydırma olarak sayılacağı anlamına gelir. @Override public float getSwipeThreshold(@NonNull RecyclerView.ViewHolder viewHolder) { return 0.7f; } } |
Aşağıdaki RecyclerViewAdapter sınıfıdır. Item’ları tasarım anlamında özelleştirebilmek için oluşturulmuş bir sınıftır. Ek olarak, restoreItem metodu sayesinde sildiğimiz kaydı geri alabilir, removeItem metodu sayesinde de item’i silebilirsiniz.
Hvis man har pollenallergi eg 3×20 potens piller, de tre opprinnelige kjente merkenavn strømprodukter eller som kan føre til helseskader eller apotekno.com/kjop-generisk-levitra-uten-resept/ begrens dosen med en pille. Det er årsaken til at du når du bruker pillene eg for det samme virkestoffet pellets med Sildenafil er 30 minutter til en time.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.RelativeLayout; import android.widget.TextView; import java.util.ArrayList; import java.util.List; public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.MyViewHolder> { private ArrayList<String> data; public class MyViewHolder extends RecyclerView.ViewHolder { private TextView mTitle; RelativeLayout relativeLayout; public MyViewHolder(View itemView) { super(itemView); mTitle = itemView.findViewById(R.id.txtTitle); } } public RecyclerViewAdapter(ArrayList<String> data) { this.data = data; } @Override public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.cardview_row, parent, false); return new MyViewHolder(itemView); } @Override public void onBindViewHolder(MyViewHolder holder, int position) { holder.mTitle.setText(data.get(position)); } @Override public int getItemCount() { return data.size(); } //Item'i silme işlemi public void removeItem(int position) { data.remove(position); notifyItemRemoved(position); } // Snackbar işlemi tıklandığında, restoreItem metodunu kullanarak öğeyi RecyclerView'da geri yükleriz. public void restoreItem(String item, int position) { data.add(position, item); notifyItemInserted(position); } public ArrayList<String> getData() { return data; } } |
Aşağıdaki MainActivity sınıfıdır. Bu sınıfta listelenecek değerleri bir diziye aktarıp, RecyclerViewAdapter sınıfına gönderdim. Diğer bir yandan item’ı kaydırarak (swipe) sildiğinizde, Snackbar çıkmasını, silme ve silinen item’ın geri almasını sağlayan metodu kullandık.
1 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
import android.graphics.Color; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.design.widget.CoordinatorLayout; import android.support.design.widget.Snackbar; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.helper.ItemTouchHelper; import android.util.Log; import android.view.View; import java.util.ArrayList; public class MainActivity extends AppCompatActivity { RecyclerView recyclerView; RecyclerViewAdapter mAdapter; ArrayList<String> stringArrayList = new ArrayList<>(); CoordinatorLayout coordinatorLayout; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); recyclerView = findViewById(R.id.recyclerView); coordinatorLayout = findViewById(R.id.coordinatorLayout); populateRecyclerView(); enableSwipeToDeleteAndUndo(); } private void populateRecyclerView() { stringArrayList.add("Item 1"); stringArrayList.add("Item 2"); stringArrayList.add("Item 3"); stringArrayList.add("Item 4"); stringArrayList.add("Item 5"); stringArrayList.add("Item 6"); stringArrayList.add("Item 7"); stringArrayList.add("Item 8"); stringArrayList.add("Item 9"); stringArrayList.add("Item 10"); mAdapter = new RecyclerViewAdapter(stringArrayList); recyclerView.setAdapter(mAdapter); } private void enableSwipeToDeleteAndUndo() { SwipeToDeleteCallback swipeToDeleteCallback = new SwipeToDeleteCallback(this) { @Override public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int i) { final int position = viewHolder.getAdapterPosition(); final String item = mAdapter.getData().get(position); //silinecek item ın position bilgisiyle, removeItem kullanarak silme işlemi yapıldı mAdapter.removeItem(position); //Snackbar oluşturulması Snackbar snackbar = Snackbar .make(coordinatorLayout, "Item was removed from the list.", Snackbar.LENGTH_LONG); snackbar.setAction("UNDO", new View.OnClickListener() { @Override public void onClick(View view) { //item ın position bilgisiyle, restoreItem kullanarak geri alma işlemi yapıldı mAdapter.restoreItem(item, position); recyclerView.scrollToPosition(position); } }); snackbar.setActionTextColor(Color.YELLOW); snackbar.show(); } }; ItemTouchHelper itemTouchhelper = new ItemTouchHelper(swipeToDeleteCallback); itemTouchhelper.attachToRecyclerView(recyclerView); } } |
Böylelikle projemizi oluşturmuş olduk.
Son olarak ufak bir not: Bu yukarıda anlattığım projemin kodlarını indirmek isterseniz; yapmanız gereken tek şey aşağıya koyduğum KODLARI İNDİR resmine tıklamak.