diff --git a/app/src/main/java/ru/karasevm/privatednstoggle/DNSServerDialogFragment.kt b/app/src/main/java/ru/karasevm/privatednstoggle/DNSServerDialogFragment.kt index 144a728..550d493 100644 --- a/app/src/main/java/ru/karasevm/privatednstoggle/DNSServerDialogFragment.kt +++ b/app/src/main/java/ru/karasevm/privatednstoggle/DNSServerDialogFragment.kt @@ -44,7 +44,7 @@ class DNSServerDialogFragment : DialogFragment() { items.add(0, resources.getString(R.string.dns_auto)) items.add(0, resources.getString(R.string.dns_off)) - adapter = RecyclerAdapter(items) + adapter = RecyclerAdapter(items, false) binding.recyclerView.adapter = adapter diff --git a/app/src/main/java/ru/karasevm/privatednstoggle/MainActivity.kt b/app/src/main/java/ru/karasevm/privatednstoggle/MainActivity.kt index 84c3b63..5d5513e 100644 --- a/app/src/main/java/ru/karasevm/privatednstoggle/MainActivity.kt +++ b/app/src/main/java/ru/karasevm/privatednstoggle/MainActivity.kt @@ -6,15 +6,26 @@ import android.content.Intent import android.content.SharedPreferences import android.content.pm.IPackageManager import android.content.pm.PackageManager +import android.content.res.Resources +import android.graphics.Color +import android.graphics.drawable.Drawable import android.net.Uri import android.os.Build import android.os.Bundle import android.permission.IPermissionManager import android.util.Log +import android.util.TypedValue import android.view.Menu import android.widget.Toast import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import androidx.recyclerview.widget.ItemTouchHelper +import androidx.recyclerview.widget.ItemTouchHelper.DOWN +import androidx.recyclerview.widget.ItemTouchHelper.END +import androidx.recyclerview.widget.ItemTouchHelper.START +import androidx.recyclerview.widget.ItemTouchHelper.UP import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView import org.lsposed.hiddenapibypass.HiddenApiBypass import rikka.shizuku.Shizuku import rikka.shizuku.ShizukuBinderWrapper @@ -34,6 +45,47 @@ class MainActivity : AppCompatActivity(), AddServerDialogFragment.NoticeDialogLi private lateinit var sharedPrefs: SharedPreferences private lateinit var adapter: RecyclerAdapter + private val itemTouchHelper by lazy { + val simpleItemTouchCallback = + object : ItemTouchHelper.SimpleCallback(UP or + DOWN, 0) { + + override fun onMove( + recyclerView: RecyclerView, + viewHolder: RecyclerView.ViewHolder, + target: RecyclerView.ViewHolder + ): Boolean { + adapter.onItemMove(viewHolder.adapterPosition, target.adapterPosition) + return true + } + + override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {} + + override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) { + super.onSelectedChanged(viewHolder, actionState) + if (actionState == ItemTouchHelper.ACTION_STATE_DRAG) { + viewHolder?.itemView?.apply { + // Example: Elevate the view + elevation = 8f + alpha = 0.5f + setBackgroundColor(Color.GRAY) + } + } + } + + override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) { + super.clearView(recyclerView, viewHolder) + viewHolder.itemView.apply { + // Reset the appearance + elevation = 0f + alpha = 1.0f + setBackgroundColor(Color.TRANSPARENT) + } + } + } + ItemTouchHelper(simpleItemTouchCallback) + } + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -52,16 +104,24 @@ class MainActivity : AppCompatActivity(), AddServerDialogFragment.NoticeDialogLi if (items[0] == "") { items.removeAt(0) } - adapter = RecyclerAdapter(items) + adapter = RecyclerAdapter(items, true) adapter.onItemClick = { position -> val newFragment = DeleteServerDialogFragment(position) newFragment.show(supportFragmentManager, "delete_server") } + adapter.onItemsChanged = { swapedItems -> + items = swapedItems + sharedPrefs.dns_servers = swapedItems + } + adapter.onDragStart = { viewHolder -> + itemTouchHelper.startDrag(viewHolder); + } binding.floatingActionButton.setOnClickListener { val newFragment = AddServerDialogFragment() newFragment.show(supportFragmentManager, "add_server") } binding.recyclerView.adapter = adapter + itemTouchHelper.attachToRecyclerView(binding.recyclerView); binding.topAppBar.setOnMenuItemClickListener { item -> when (item.itemId) { diff --git a/app/src/main/java/ru/karasevm/privatednstoggle/RecyclerAdapter.kt b/app/src/main/java/ru/karasevm/privatednstoggle/RecyclerAdapter.kt index 03bdda4..0cbc011 100644 --- a/app/src/main/java/ru/karasevm/privatednstoggle/RecyclerAdapter.kt +++ b/app/src/main/java/ru/karasevm/privatednstoggle/RecyclerAdapter.kt @@ -1,15 +1,21 @@ package ru.karasevm.privatednstoggle +import android.annotation.SuppressLint import android.view.LayoutInflater +import android.view.MotionEvent import android.view.View import android.view.ViewGroup +import android.widget.ImageView import android.widget.TextView import androidx.recyclerview.widget.RecyclerView +import java.util.Collections -class RecyclerAdapter(private val items: MutableList) : +class RecyclerAdapter(private val items: MutableList, private val showDragHandle: Boolean) : RecyclerView.Adapter() { var onItemClick: ((Int) -> Unit)? = null + var onItemsChanged: ((MutableList) -> Unit)? = null + var onDragStart: ((RecyclerAdapter.ViewHolder) -> Unit)? = null override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerAdapter.ViewHolder { val view = @@ -18,20 +24,39 @@ class RecyclerAdapter(private val items: MutableList) : return vh } + @SuppressLint("ClickableViewAccessibility") override fun onBindViewHolder(holder: RecyclerAdapter.ViewHolder, position: Int) { val item = items[position] // sets the text to the textview from our itemHolder class holder.textView.text = item + if(showDragHandle) { + holder.dragHandle.visibility = View.VISIBLE + holder.dragHandle.setOnTouchListener { + _, event -> + if (event.actionMasked == MotionEvent.ACTION_DOWN) { + onDragStart?.invoke(holder) + } + return@setOnTouchListener true + } + } } override fun getItemCount(): Int { return items.size } + fun onItemMove(fromPosition: Int, toPosition: Int) { + // Swap items in your data list + Collections.swap(items, fromPosition, toPosition) + notifyItemMoved(fromPosition, toPosition) + onItemsChanged?.invoke(items) + } + inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { val textView: TextView = itemView.findViewById(R.id.textView) + val dragHandle: ImageView = itemView.findViewById(R.id.dragHandle) init { itemView.setOnClickListener { diff --git a/app/src/main/res/drawable/ic_drag_handle_24.xml b/app/src/main/res/drawable/ic_drag_handle_24.xml new file mode 100644 index 0000000..892b734 --- /dev/null +++ b/app/src/main/res/drawable/ic_drag_handle_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/layout/recyclerview_row.xml b/app/src/main/res/layout/recyclerview_row.xml index dd9e0cc..c796261 100644 --- a/app/src/main/res/layout/recyclerview_row.xml +++ b/app/src/main/res/layout/recyclerview_row.xml @@ -13,7 +13,18 @@ android:layout_height="wrap_content" android:layout_marginStart="32dp" app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintEnd_toStartOf="@+id/dragHandle" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> + + \ No newline at end of file