rewrite RecyclerAdapter to the shared recyclerview adapter

This commit is contained in:
tibbi
2017-11-30 23:26:02 +01:00
parent a60c1f6fc1
commit c8c277d7d5
7 changed files with 118 additions and 284 deletions

View File

@ -39,7 +39,7 @@ android {
}
dependencies {
implementation 'com.simplemobiletools:commons:3.0.3'
implementation 'com.simplemobiletools:commons:3.0.13'
implementation 'com.facebook.stetho:stetho:1.5.0'
implementation 'com.android.support:multidex:1.0.2'
}

View File

@ -2,19 +2,12 @@ package com.simplemobiletools.applauncher
import android.support.multidex.MultiDexApplication
import com.facebook.stetho.Stetho
import com.simplemobiletools.applauncher.extensions.config
import java.util.*
import com.simplemobiletools.commons.extensions.checkUseEnglish
class App : MultiDexApplication() {
override fun onCreate() {
super.onCreate()
if (config.useEnglish) {
val conf = resources.configuration
conf.locale = Locale.ENGLISH
resources.updateConfiguration(conf, resources.displayMetrics)
}
checkUseEnglish()
Stetho.initializeWithDefaults(this)
}
}

View File

@ -7,23 +7,25 @@ import android.view.Menu
import android.view.MenuItem
import com.simplemobiletools.applauncher.BuildConfig
import com.simplemobiletools.applauncher.R
import com.simplemobiletools.applauncher.adapters.RecyclerAdapter
import com.simplemobiletools.applauncher.adapters.LaunchersAdapter
import com.simplemobiletools.applauncher.dialogs.AddAppLauncherDialog
import com.simplemobiletools.applauncher.extensions.config
import com.simplemobiletools.applauncher.extensions.dbHelper
import com.simplemobiletools.applauncher.extensions.isAPredefinedApp
import com.simplemobiletools.applauncher.models.AppLauncher
import com.simplemobiletools.commons.extensions.appLaunched
import com.simplemobiletools.commons.extensions.checkWhatsNew
import com.simplemobiletools.commons.extensions.restartActivity
import com.simplemobiletools.commons.extensions.updateTextColors
import com.simplemobiletools.commons.helpers.LICENSE_KOTLIN
import com.simplemobiletools.commons.helpers.LICENSE_MULTISELECT
import com.simplemobiletools.commons.helpers.LICENSE_STETHO
import com.simplemobiletools.commons.interfaces.RefreshRecyclerViewListener
import com.simplemobiletools.commons.models.Release
import kotlinx.android.synthetic.main.activity_main.*
import java.util.*
class MainActivity : SimpleActivity(), RecyclerAdapter.AppLaunchersListener {
class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
private var launchers = ArrayList<AppLauncher>()
private var mStoredPrimaryColor = 0
private var mStoredTextColor = 0
@ -32,14 +34,14 @@ class MainActivity : SimpleActivity(), RecyclerAdapter.AppLaunchersListener {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
appLaunched()
setupLaunchers()
checkWhatsNewDialog()
setupGridLayoutManager()
storeStateVariables()
fab.setOnClickListener {
AddAppLauncherDialog(this, launchers) {
refreshLaunchers()
setupLaunchers()
}
}
}
@ -89,30 +91,13 @@ class MainActivity : SimpleActivity(), RecyclerAdapter.AppLaunchersListener {
startAboutActivity(R.string.app_name, LICENSE_KOTLIN or LICENSE_MULTISELECT or LICENSE_STETHO, BuildConfig.VERSION_NAME)
}
private fun getGridAdapter() = launchers_grid.adapter as? RecyclerAdapter
private fun setupGridLayoutManager() {
/*launchers_grid.isDragSelectionEnabled = true
launchers_grid.listener = object : MyScalableRecyclerView.MyScalableRecyclerViewListener {
override fun zoomIn() {}
override fun zoomOut() {}
override fun selectItem(position: Int) {
getGridAdapter()?.selectItem(position)
}
override fun selectRange(initialSelection: Int, lastDraggedIndex: Int, minReached: Int, maxReached: Int) {
getGridAdapter()?.selectRange(initialSelection, lastDraggedIndex, minReached, maxReached)
}
}*/
}
private fun getGridAdapter() = launchers_grid.adapter as? LaunchersAdapter
private fun setupLaunchers() {
launchers = dbHelper.getLaunchers()
checkInvalidApps()
launchers_grid.adapter = RecyclerAdapter(this, launchers, this) {
val launchIntent = packageManager.getLaunchIntentForPackage(it.packageName)
val adapter = LaunchersAdapter(this, launchers, this, launchers_grid) {
val launchIntent = packageManager.getLaunchIntentForPackage((it as AppLauncher).packageName)
if (launchIntent != null) {
startActivity(launchIntent)
finish()
@ -122,6 +107,8 @@ class MainActivity : SimpleActivity(), RecyclerAdapter.AppLaunchersListener {
startActivity(intent)
}
}
adapter.setupDragListener(true)
launchers_grid.adapter = adapter
}
private fun checkInvalidApps() {
@ -144,14 +131,10 @@ class MainActivity : SimpleActivity(), RecyclerAdapter.AppLaunchersListener {
}
}
override fun refreshLaunchers() {
override fun refreshItems() {
setupLaunchers()
}
override fun itemLongClicked(position: Int) {
//launchers_grid.setDragSelectActive(position)
}
private fun checkWhatsNewDialog() {
arrayListOf<Release>().apply {
add(Release(7, R.string.release_7))

View File

@ -0,0 +1,99 @@
package com.simplemobiletools.applauncher.adapters
import android.view.Menu
import android.view.View
import android.view.ViewGroup
import com.simplemobiletools.applauncher.R
import com.simplemobiletools.applauncher.activities.SimpleActivity
import com.simplemobiletools.applauncher.dialogs.EditDialog
import com.simplemobiletools.applauncher.extensions.dbHelper
import com.simplemobiletools.applauncher.models.AppLauncher
import com.simplemobiletools.commons.adapters.MyRecyclerViewAdapter
import com.simplemobiletools.commons.dialogs.ConfirmationDialog
import com.simplemobiletools.commons.extensions.applyColorFilter
import com.simplemobiletools.commons.extensions.beVisibleIf
import com.simplemobiletools.commons.interfaces.RefreshRecyclerViewListener
import com.simplemobiletools.commons.views.MyRecyclerView
import kotlinx.android.synthetic.main.app_launcher_item.view.*
import java.util.*
class LaunchersAdapter(activity: SimpleActivity, val launchers: MutableList<AppLauncher>, val listener: RefreshRecyclerViewListener?,
recyclerView: MyRecyclerView, itemClick: (Any) -> Unit) : MyRecyclerViewAdapter(activity, recyclerView, itemClick) {
override fun getActionMenuId() = R.menu.cab
override fun prepareItemSelection(view: View) {
view.launcher_check?.background?.applyColorFilter(primaryColor)
}
override fun markItemSelection(select: Boolean, view: View?) {
view?.launcher_check?.beVisibleIf(select)
}
override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int) = createViewHolder(R.layout.app_launcher_item, parent)
override fun onBindViewHolder(holder: MyRecyclerViewAdapter.ViewHolder, position: Int) {
val launcher = launchers[position]
val view = holder.bindView(launcher) { itemView, layoutPosition ->
setupView(itemView, launcher)
}
bindViewHolder(holder, position, view)
}
override fun getItemCount() = launchers.size
override fun prepareActionMode(menu: Menu) {
menu.apply {
findItem(R.id.cab_edit).isVisible = selectedPositions.size == 1
}
}
override fun actionItemPressed(id: Int) {
when (id) {
R.id.cab_edit -> showEditDialog()
R.id.cab_delete -> askConfirmDelete()
}
}
override fun getSelectableItemCount() = launchers.size
private fun showEditDialog() {
EditDialog(activity, launchers[selectedPositions.first()]) {
finishActMode()
listener?.refreshItems()
}
}
private fun askConfirmDelete() {
ConfirmationDialog(activity, "", R.string.delete_explanation, R.string.ok, R.string.cancel) {
deleteItems()
}
}
private fun deleteItems() {
val deleteIds = ArrayList<String>(selectedPositions.size)
val removeLaunchers = ArrayList<AppLauncher>(selectedPositions.size)
selectedPositions.sortedDescending().forEach {
val launcher = launchers[it]
deleteIds.add(launcher.id.toString())
removeLaunchers.add(launcher)
}
launchers.removeAll(removeLaunchers)
activity.dbHelper.deleteLaunchers(deleteIds)
removeSelectedItems()
}
fun updatePrimaryColor(primaryColor: Int) {
this.primaryColor = primaryColor
notifyDataSetChanged()
}
private fun setupView(view: View, launcher: AppLauncher) {
view.apply {
launcher_label.text = launcher.name
launcher_label.setTextColor(textColor)
launcher_icon.setImageDrawable(launcher.drawable!!)
}
}
}

View File

@ -1,242 +0,0 @@
package com.simplemobiletools.applauncher.adapters
import android.support.v7.view.ActionMode
import android.support.v7.widget.RecyclerView
import android.util.SparseArray
import android.view.*
import com.bignerdranch.android.multiselector.ModalMultiSelectorCallback
import com.bignerdranch.android.multiselector.MultiSelector
import com.bignerdranch.android.multiselector.SwappingHolder
import com.simplemobiletools.applauncher.R
import com.simplemobiletools.applauncher.activities.SimpleActivity
import com.simplemobiletools.applauncher.dialogs.EditDialog
import com.simplemobiletools.applauncher.extensions.config
import com.simplemobiletools.applauncher.extensions.dbHelper
import com.simplemobiletools.applauncher.models.AppLauncher
import com.simplemobiletools.commons.dialogs.ConfirmationDialog
import com.simplemobiletools.commons.extensions.applyColorFilter
import com.simplemobiletools.commons.extensions.beGone
import com.simplemobiletools.commons.extensions.beVisibleIf
import com.simplemobiletools.commons.interfaces.MyAdapterListener
import kotlinx.android.synthetic.main.app_launcher_item.view.*
import java.util.*
class RecyclerAdapter(val activity: SimpleActivity, val launchers: MutableList<AppLauncher>, val listener: AppLaunchersListener?, val itemClick: (AppLauncher) -> Unit) :
RecyclerView.Adapter<RecyclerAdapter.ViewHolder>() {
private val config = activity.config
private var actMode: ActionMode? = null
private var primaryColor = config.primaryColor
private val multiSelector = MultiSelector()
private var itemViews = SparseArray<View>()
private val selectedPositions = HashSet<Int>()
private var textColor = config.textColor
fun toggleItemSelection(select: Boolean, pos: Int) {
if (select) {
if (itemViews[pos] != null) {
itemViews[pos].launcher_check?.background?.applyColorFilter(primaryColor)
selectedPositions.add(pos)
}
} else {
selectedPositions.remove(pos)
}
itemViews[pos]?.launcher_check?.beVisibleIf(select)
if (selectedPositions.isEmpty()) {
actMode?.finish()
return
}
updateTitle(selectedPositions.size)
}
private fun updateTitle(cnt: Int) {
actMode?.title = "$cnt / ${launchers.size}"
actMode?.invalidate()
}
private val adapterListener = object : MyAdapterListener {
override fun itemLongClicked(position: Int) {
}
override fun toggleItemSelectionAdapter(select: Boolean, position: Int) {
toggleItemSelection(select, position)
}
override fun getSelectedPositions(): HashSet<Int> = selectedPositions
}
private val multiSelectorMode = object : ModalMultiSelectorCallback(multiSelector) {
override fun onActionItemClicked(mode: ActionMode?, item: MenuItem): Boolean {
when (item.itemId) {
R.id.cab_edit -> showEditDialog()
R.id.cab_delete -> askConfirmDelete()
else -> return false
}
return true
}
override fun onCreateActionMode(actionMode: ActionMode?, menu: Menu?): Boolean {
super.onCreateActionMode(actionMode, menu)
actMode = actionMode
activity.menuInflater.inflate(R.menu.cab, menu)
return true
}
override fun onPrepareActionMode(actionMode: ActionMode?, menu: Menu): Boolean {
menu.findItem(R.id.cab_edit).isVisible = selectedPositions.size == 1
return true
}
override fun onDestroyActionMode(actionMode: ActionMode?) {
super.onDestroyActionMode(actionMode)
selectedPositions.forEach {
itemViews[it]?.launcher_check?.beGone()
}
selectedPositions.clear()
actMode = null
}
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
itemViews.put(position, holder.bindView(launchers[position], textColor))
toggleItemSelection(selectedPositions.contains(position), position)
holder.itemView.tag = holder
}
override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent?.context).inflate(R.layout.app_launcher_item, parent, false)
return ViewHolder(view, adapterListener, activity, multiSelectorMode, multiSelector, listener, itemClick)
}
override fun getItemCount() = launchers.count()
private fun showEditDialog() {
EditDialog(activity, launchers[selectedPositions.first()]) {
actMode?.finish()
listener?.refreshLaunchers()
}
}
private fun askConfirmDelete() {
ConfirmationDialog(activity, "", R.string.delete_explanation, R.string.ok, R.string.cancel) {
deleteItems()
}
}
private fun deleteItems() {
val deleteIds = ArrayList<String>(selectedPositions.size)
val removeLaunchers = ArrayList<AppLauncher>(selectedPositions.size)
selectedPositions.sortedDescending().forEach {
val launcher = launchers[it]
deleteIds.add(launcher.id.toString())
removeLaunchers.add(launcher)
notifyItemRemoved(it)
itemViews.put(it, null)
}
launchers.removeAll(removeLaunchers)
activity.dbHelper.deleteLaunchers(deleteIds)
val newItems = SparseArray<View>()
(0 until itemViews.size())
.filter { itemViews[it] != null }
.forEachIndexed { curIndex, i -> newItems.put(curIndex, itemViews[i]) }
itemViews = newItems
actMode?.finish()
}
fun updateTextColor(textColor: Int) {
this.textColor = textColor
notifyDataSetChanged()
}
fun updatePrimaryColor(primaryColor: Int) {
this.primaryColor = primaryColor
notifyDataSetChanged()
}
fun selectItem(pos: Int) {
toggleItemSelection(true, pos)
}
fun selectRange(from: Int, to: Int, min: Int, max: Int) {
if (from == to) {
(min..max).filter { it != from }
.forEach { toggleItemSelection(false, it) }
return
}
if (to < from) {
for (i in to..from)
toggleItemSelection(true, i)
if (min > -1 && min < to) {
(min until to).filter { it != from }
.forEach { toggleItemSelection(false, it) }
}
if (max > -1) {
for (i in from + 1..max)
toggleItemSelection(false, i)
}
} else {
for (i in from..to)
toggleItemSelection(true, i)
if (max > -1 && max > to) {
(to + 1..max).filter { it != from }
.forEach { toggleItemSelection(false, it) }
}
if (min > -1) {
for (i in min until from)
toggleItemSelection(false, i)
}
}
}
class ViewHolder(view: View, val adapterListener: MyAdapterListener, val activity: SimpleActivity, val multiSelectorCallback: ModalMultiSelectorCallback,
val multiSelector: MultiSelector, val listener: AppLaunchersListener?, val itemClick: (AppLauncher) -> (Unit)) : SwappingHolder(view, MultiSelector()) {
fun bindView(launcher: AppLauncher, textColor: Int): View {
itemView.apply {
launcher_label.text = launcher.name
launcher_label.setTextColor(textColor)
launcher_icon.setImageDrawable(launcher.drawable!!)
setOnClickListener { viewClicked(launcher) }
setOnLongClickListener { viewLongClicked(); true }
}
return itemView
}
private fun viewClicked(appLauncher: AppLauncher) {
if (multiSelector.isSelectable) {
val isSelected = adapterListener.getSelectedPositions().contains(adapterPosition)
adapterListener.toggleItemSelectionAdapter(!isSelected, adapterPosition)
} else {
itemClick(appLauncher)
}
}
private fun viewLongClicked() {
if (listener != null) {
if (!multiSelector.isSelectable) {
activity.startSupportActionMode(multiSelectorCallback)
adapterListener.toggleItemSelectionAdapter(true, adapterPosition)
}
listener.itemLongClicked(adapterPosition)
}
}
}
interface AppLaunchersListener {
fun refreshLaunchers()
fun itemLongClicked(position: Int)
}
}

View File

@ -3,7 +3,5 @@ package com.simplemobiletools.applauncher.models
import android.graphics.drawable.Drawable
data class AppLauncher(val id: Int, var name: String, val packageName: String, val drawable: Drawable? = null) {
override fun equals(other: Any?): Boolean {
return packageName.equals((other as AppLauncher).packageName, true)
}
override fun equals(other: Any?) = packageName.equals((other as AppLauncher).packageName, true)
}

View File

@ -5,6 +5,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:paddingBottom="@dimen/small_margin"
android:paddingLeft="@dimen/small_margin"
android:paddingRight="@dimen/small_margin"
@ -32,6 +34,7 @@
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_margin="@dimen/small_margin"
android:background="@drawable/circle_background"
android:padding="@dimen/tiny_margin"
android:src="@drawable/ic_check"