Feature: Reordring (#23)

* Reordering of Servers

* Fix drag handle being drawn outside of the screen

---------

Co-authored-by: Maksim Karasev <karasevm98@gmail.com>
This commit is contained in:
Praveen Kumar 2024-06-27 17:15:05 +05:30 committed by GitHub
parent 01650977c3
commit c24f8e0b38
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 110 additions and 4 deletions

View file

@ -44,7 +44,7 @@ class DNSServerDialogFragment : DialogFragment() {
items.add(0, resources.getString(R.string.dns_auto)) items.add(0, resources.getString(R.string.dns_auto))
items.add(0, resources.getString(R.string.dns_off)) items.add(0, resources.getString(R.string.dns_off))
adapter = RecyclerAdapter(items) adapter = RecyclerAdapter(items, false)
binding.recyclerView.adapter = adapter binding.recyclerView.adapter = adapter

View file

@ -6,15 +6,26 @@ import android.content.Intent
import android.content.SharedPreferences import android.content.SharedPreferences
import android.content.pm.IPackageManager import android.content.pm.IPackageManager
import android.content.pm.PackageManager 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.net.Uri
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.permission.IPermissionManager import android.permission.IPermissionManager
import android.util.Log import android.util.Log
import android.util.TypedValue
import android.view.Menu import android.view.Menu
import android.widget.Toast import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity 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.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import org.lsposed.hiddenapibypass.HiddenApiBypass import org.lsposed.hiddenapibypass.HiddenApiBypass
import rikka.shizuku.Shizuku import rikka.shizuku.Shizuku
import rikka.shizuku.ShizukuBinderWrapper import rikka.shizuku.ShizukuBinderWrapper
@ -34,6 +45,47 @@ class MainActivity : AppCompatActivity(), AddServerDialogFragment.NoticeDialogLi
private lateinit var sharedPrefs: SharedPreferences private lateinit var sharedPrefs: SharedPreferences
private lateinit var adapter: RecyclerAdapter 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?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -52,16 +104,24 @@ class MainActivity : AppCompatActivity(), AddServerDialogFragment.NoticeDialogLi
if (items[0] == "") { if (items[0] == "") {
items.removeAt(0) items.removeAt(0)
} }
adapter = RecyclerAdapter(items) adapter = RecyclerAdapter(items, true)
adapter.onItemClick = { position -> adapter.onItemClick = { position ->
val newFragment = DeleteServerDialogFragment(position) val newFragment = DeleteServerDialogFragment(position)
newFragment.show(supportFragmentManager, "delete_server") newFragment.show(supportFragmentManager, "delete_server")
} }
adapter.onItemsChanged = { swapedItems ->
items = swapedItems
sharedPrefs.dns_servers = swapedItems
}
adapter.onDragStart = { viewHolder ->
itemTouchHelper.startDrag(viewHolder);
}
binding.floatingActionButton.setOnClickListener { binding.floatingActionButton.setOnClickListener {
val newFragment = AddServerDialogFragment() val newFragment = AddServerDialogFragment()
newFragment.show(supportFragmentManager, "add_server") newFragment.show(supportFragmentManager, "add_server")
} }
binding.recyclerView.adapter = adapter binding.recyclerView.adapter = adapter
itemTouchHelper.attachToRecyclerView(binding.recyclerView);
binding.topAppBar.setOnMenuItemClickListener { item -> binding.topAppBar.setOnMenuItemClickListener { item ->
when (item.itemId) { when (item.itemId) {

View file

@ -1,15 +1,21 @@
package ru.karasevm.privatednstoggle package ru.karasevm.privatednstoggle
import android.annotation.SuppressLint
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import java.util.Collections
class RecyclerAdapter(private val items: MutableList<String>) : class RecyclerAdapter(private val items: MutableList<String>, private val showDragHandle: Boolean) :
RecyclerView.Adapter<RecyclerAdapter.ViewHolder>() { RecyclerView.Adapter<RecyclerAdapter.ViewHolder>() {
var onItemClick: ((Int) -> Unit)? = null var onItemClick: ((Int) -> Unit)? = null
var onItemsChanged: ((MutableList<String>) -> Unit)? = null
var onDragStart: ((RecyclerAdapter.ViewHolder) -> Unit)? = null
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerAdapter.ViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerAdapter.ViewHolder {
val view = val view =
@ -18,20 +24,39 @@ class RecyclerAdapter(private val items: MutableList<String>) :
return vh return vh
} }
@SuppressLint("ClickableViewAccessibility")
override fun onBindViewHolder(holder: RecyclerAdapter.ViewHolder, position: Int) { override fun onBindViewHolder(holder: RecyclerAdapter.ViewHolder, position: Int) {
val item = items[position] val item = items[position]
// sets the text to the textview from our itemHolder class // sets the text to the textview from our itemHolder class
holder.textView.text = item 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 { override fun getItemCount(): Int {
return items.size 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) { inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val textView: TextView = itemView.findViewById(R.id.textView) val textView: TextView = itemView.findViewById(R.id.textView)
val dragHandle: ImageView = itemView.findViewById(R.id.dragHandle)
init { init {
itemView.setOnClickListener { itemView.setOnClickListener {

View file

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M20,9H4v2h16V9zM4,15h16v-2H4v2z"/>
</vector>

View file

@ -13,7 +13,18 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="32dp" android:layout_marginStart="32dp"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toStartOf="@+id/dragHandle"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/dragHandle"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_marginEnd="32dp"
android:src="@drawable/ic_drag_handle_24"
android:visibility="gone"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>