mirror of
https://github.com/karasevm/PrivateDNSAndroid.git
synced 2025-06-28 20:29:56 +00:00
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:
parent
01650977c3
commit
c24f8e0b38
5 changed files with 110 additions and 4 deletions
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
10
app/src/main/res/drawable/ic_drag_handle_24.xml
Normal file
10
app/src/main/res/drawable/ic_drag_handle_24.xml
Normal 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>
|
|
@ -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>
|
Loading…
Add table
Add a link
Reference in a new issue