Implement ActionMode for CustomRulesFragment
This commit is contained in:
@@ -20,21 +20,21 @@
|
||||
|
||||
package com.github.shadowsocks.acl
|
||||
|
||||
import android.annotation.TargetApi
|
||||
import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.support.design.widget.Snackbar
|
||||
import android.support.v4.content.ContextCompat
|
||||
import android.support.v7.app.AlertDialog
|
||||
import android.support.v7.widget.DefaultItemAnimator
|
||||
import android.support.v7.widget.LinearLayoutManager
|
||||
import android.support.v7.widget.RecyclerView
|
||||
import android.support.v7.widget.Toolbar
|
||||
import android.support.v7.widget.helper.ItemTouchHelper
|
||||
import android.view.LayoutInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.*
|
||||
import android.widget.EditText
|
||||
import android.widget.Spinner
|
||||
import android.widget.TextView
|
||||
@@ -48,12 +48,13 @@ import com.github.shadowsocks.ToolbarFragment
|
||||
import com.github.shadowsocks.bg.BaseService
|
||||
import com.github.shadowsocks.utils.Subnet
|
||||
import com.github.shadowsocks.utils.asIterable
|
||||
import com.github.shadowsocks.utils.resolveResourceId
|
||||
import com.github.shadowsocks.widget.UndoSnackbarManager
|
||||
import java.net.IDN
|
||||
import java.net.URL
|
||||
import java.util.*
|
||||
|
||||
class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
|
||||
class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener, ActionMode.Callback {
|
||||
companion object {
|
||||
private const val TEMPLATE_REGEX_DOMAIN = "(^|\\.)%s$"
|
||||
|
||||
@@ -288,13 +289,12 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
|
||||
private val selectedItems = HashSet<Any>()
|
||||
private val adapter by lazy { AclRulesAdapter() }
|
||||
private lateinit var list: RecyclerView
|
||||
private var selectionItem: MenuItem? = null
|
||||
private var mode: ActionMode? = null
|
||||
private lateinit var undoManager: UndoSnackbarManager<Any>
|
||||
private val clipboard by lazy { activity!!.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager }
|
||||
|
||||
private fun onSelectedItemsUpdated() {
|
||||
val selectionItem = selectionItem
|
||||
if (selectionItem != null) selectionItem.isVisible = selectedItems.isNotEmpty()
|
||||
if (selectedItems.isEmpty()) mode?.finish() else if (mode == null) mode = toolbar.startActionMode(this)
|
||||
}
|
||||
|
||||
private fun createAclRuleDialog(item: Any = ""): Triple<Spinner, EditText, AlertDialog.Builder> {
|
||||
@@ -345,9 +345,6 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
|
||||
toolbar.setTitle(R.string.custom_rules)
|
||||
toolbar.inflateMenu(R.menu.custom_rules_menu)
|
||||
toolbar.setOnMenuItemClickListener(this)
|
||||
val selectionItem = toolbar.menu.findItem(R.id.selection)
|
||||
selectionItem.isVisible = selectedItems.isNotEmpty()
|
||||
this.selectionItem = selectionItem
|
||||
list = view.findViewById(R.id.list)
|
||||
list.layoutManager = LinearLayoutManager(activity, LinearLayoutManager.VERTICAL, false)
|
||||
list.itemAnimator = DefaultItemAnimator()
|
||||
@@ -365,10 +362,9 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
|
||||
}
|
||||
|
||||
override fun onBackPressed(): Boolean {
|
||||
return if (selectedItems.isNotEmpty()) {
|
||||
selectedItems.clear()
|
||||
onSelectedItemsUpdated()
|
||||
adapter.notifyDataSetChanged()
|
||||
val mode = mode
|
||||
return if (mode != null) {
|
||||
mode.finish()
|
||||
true
|
||||
} else super.onBackPressed()
|
||||
}
|
||||
@@ -395,24 +391,6 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
|
||||
}
|
||||
|
||||
override fun onMenuItemClick(item: MenuItem): Boolean = when (item.itemId) {
|
||||
R.id.action_select_all -> {
|
||||
adapter.selectAll()
|
||||
true
|
||||
}
|
||||
R.id.action_cut -> {
|
||||
copySelected()
|
||||
adapter.removeSelected()
|
||||
true
|
||||
}
|
||||
R.id.action_copy -> {
|
||||
copySelected()
|
||||
true
|
||||
}
|
||||
R.id.action_delete -> {
|
||||
adapter.removeSelected()
|
||||
true
|
||||
}
|
||||
|
||||
R.id.action_manual_settings -> {
|
||||
val (templateSelector, editText, dialog) = createAclRuleDialog()
|
||||
dialog.setPositiveButton(android.R.string.ok, { _, _ ->
|
||||
@@ -444,4 +422,50 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
|
||||
undoManager.flush()
|
||||
super.onDetach()
|
||||
}
|
||||
|
||||
override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean {
|
||||
val activity = activity!!
|
||||
val window = activity.window
|
||||
// In the end material_grey_100 is used for background, see AppCompatDrawableManager (very complicated)
|
||||
if (Build.VERSION.SDK_INT >= 23) {
|
||||
window.statusBarColor = ContextCompat.getColor(activity, R.color.material_grey_300)
|
||||
window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
|
||||
} else window.statusBarColor = ContextCompat.getColor(activity, R.color.material_grey_600)
|
||||
activity.menuInflater.inflate(R.menu.custom_rules_selection, menu)
|
||||
toolbar.touchscreenBlocksFocus = true
|
||||
return true
|
||||
}
|
||||
override fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean = false
|
||||
override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean = when (item.itemId) {
|
||||
R.id.action_select_all -> {
|
||||
adapter.selectAll()
|
||||
true
|
||||
}
|
||||
R.id.action_cut -> {
|
||||
copySelected()
|
||||
adapter.removeSelected()
|
||||
true
|
||||
}
|
||||
R.id.action_copy -> {
|
||||
copySelected()
|
||||
true
|
||||
}
|
||||
R.id.action_delete -> {
|
||||
adapter.removeSelected()
|
||||
true
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
override fun onDestroyActionMode(mode: ActionMode) {
|
||||
val activity = activity!!
|
||||
val window = activity.window
|
||||
window.statusBarColor = ContextCompat.getColor(activity,
|
||||
activity.theme.resolveResourceId(android.R.attr.statusBarColor))
|
||||
window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE
|
||||
toolbar.touchscreenBlocksFocus = false
|
||||
selectedItems.clear()
|
||||
onSelectedItemsUpdated()
|
||||
adapter.notifyDataSetChanged()
|
||||
this.mode = null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
android:viewportHeight="24.0"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="#FFFFFFFF"
|
||||
android:pathData="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2V7H6v12zM19,4h-3.5l-1,-1h-5l-1,1H5v2h14V4z"/>
|
||||
|
||||
@@ -2,9 +2,7 @@
|
||||
<animated-vector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:drawable="@drawable/ic_service_busy"
|
||||
tools:ignore="NewApi">
|
||||
android:drawable="@drawable/ic_service_busy">
|
||||
<target android:name="path">
|
||||
<aapt:attr name="android:animation">
|
||||
<objectAnimator
|
||||
|
||||
@@ -2,9 +2,7 @@
|
||||
<animated-vector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:drawable="@drawable/ic_service_idle"
|
||||
tools:ignore="NewApi">
|
||||
android:drawable="@drawable/ic_service_idle">
|
||||
<target android:name="strike_thru_path">
|
||||
<aapt:attr name="android:animation">
|
||||
<objectAnimator
|
||||
|
||||
@@ -2,9 +2,7 @@
|
||||
<animated-vector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:drawable="@drawable/ic_service_idle"
|
||||
tools:ignore="NewApi">
|
||||
android:drawable="@drawable/ic_service_idle">
|
||||
<target android:name="strike_thru_path">
|
||||
<aapt:attr name="android:animation">
|
||||
<objectAnimator
|
||||
|
||||
@@ -2,9 +2,7 @@
|
||||
<animated-vector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:drawable="@drawable/ic_service_busy"
|
||||
tools:ignore="NewApi">
|
||||
android:drawable="@drawable/ic_service_busy">
|
||||
<target android:name="path">
|
||||
<aapt:attr name="android:animation">
|
||||
<objectAnimator
|
||||
|
||||
@@ -1,41 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<item
|
||||
android:id="@+id/selection"
|
||||
android:alphabeticShortcut="s"
|
||||
android:icon="?attr/actionModeSelectAllDrawable"
|
||||
android:numericShortcut="0"
|
||||
android:title="@string/action_selection"
|
||||
android:visible="false"
|
||||
app:showAsAction="always">
|
||||
<menu>
|
||||
<item
|
||||
android:id="@+id/action_select_all"
|
||||
android:alphabeticShortcut="a"
|
||||
android:numericShortcut="1"
|
||||
android:title="@android:string/selectAll"
|
||||
app:showAsAction="always"/>
|
||||
<item
|
||||
android:id="@+id/action_cut"
|
||||
android:alphabeticShortcut="t"
|
||||
android:numericShortcut="2"
|
||||
android:title="@android:string/cut"
|
||||
app:showAsAction="always"/>
|
||||
<item
|
||||
android:id="@+id/action_copy"
|
||||
android:alphabeticShortcut="c"
|
||||
android:numericShortcut="3"
|
||||
android:title="@android:string/copy"
|
||||
app:showAsAction="always"/>
|
||||
<item
|
||||
android:id="@+id/action_delete"
|
||||
android:alphabeticShortcut="d"
|
||||
android:numericShortcut="4"
|
||||
android:title="@string/delete"
|
||||
app:showAsAction="always"/>
|
||||
</menu>
|
||||
</item>
|
||||
<item android:title="@string/action_add_rule"
|
||||
android:icon="@drawable/ic_av_playlist_add"
|
||||
android:alphabeticShortcut="a"
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:ignore="AppCompatResource">
|
||||
<item
|
||||
android:id="@+id/action_select_all"
|
||||
android:alphabeticShortcut="a"
|
||||
android:icon="?attr/actionModeSelectAllDrawable"
|
||||
android:numericShortcut="1"
|
||||
android:title="@android:string/selectAll"
|
||||
android:showAsAction="always"/>
|
||||
<item
|
||||
android:id="@+id/action_cut"
|
||||
android:alphabeticShortcut="t"
|
||||
android:icon="?attr/actionModeCutDrawable"
|
||||
android:numericShortcut="2"
|
||||
android:title="@android:string/cut"
|
||||
android:showAsAction="always"/>
|
||||
<item
|
||||
android:id="@+id/action_copy"
|
||||
android:alphabeticShortcut="c"
|
||||
android:icon="?attr/actionModeCopyDrawable"
|
||||
android:numericShortcut="3"
|
||||
android:title="@android:string/copy"
|
||||
android:showAsAction="always"/>
|
||||
<item
|
||||
android:id="@+id/action_delete"
|
||||
android:alphabeticShortcut="d"
|
||||
android:icon="@drawable/ic_action_delete"
|
||||
android:numericShortcut="4"
|
||||
android:title="@string/delete"
|
||||
android:showAsAction="always"/>
|
||||
</menu>
|
||||
+2
-1
@@ -2,7 +2,8 @@
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
android:viewportHeight="24.0"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="#FFFFFFFF"
|
||||
android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z"/>
|
||||
@@ -1,13 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<style name="Theme.Shadowsocks" parent="PreferenceFixTheme.Light.NoActionBar">
|
||||
<!--suppress NewApi -->
|
||||
<item name="android:navigationBarColor">@color/material_primary_700</item>
|
||||
<item name="actionModeCloseDrawable">@drawable/ic_navigation_close</item>
|
||||
<item name="colorAccent">@color/material_accent_200</item>
|
||||
<item name="colorButtonNormal">@color/material_accent_200</item>
|
||||
<item name="colorPrimary">@color/material_primary_500</item>
|
||||
<item name="colorPrimaryDark">@color/material_primary_700</item>
|
||||
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material.Fix</item>
|
||||
<item name="preferenceCategory_marginBottom">8dp</item>
|
||||
<item name="windowActionModeOverlay">true</item>
|
||||
</style>
|
||||
</resources>
|
||||
|
||||
Reference in New Issue
Block a user