mirror of
https://github.com/SimpleMobileTools/Simple-Calendar.git
synced 2025-02-17 04:10:45 +01:00
create an abstract MyAdapter that can be reused at multiple recycler adapters
This commit is contained in:
parent
c3a770ab43
commit
30b1cb40c6
@ -566,7 +566,7 @@ class MainActivity : SimpleActivity(), NavigationListener {
|
||||
}
|
||||
|
||||
private fun launchAbout() {
|
||||
startAboutActivity(R.string.app_name, LICENSE_KOTLIN or LICENSE_JODA or LICENSE_STETHO, BuildConfig.VERSION_NAME)
|
||||
startAboutActivity(R.string.app_name, LICENSE_KOTLIN or LICENSE_JODA or LICENSE_STETHO or LICENSE_MULTISELECT, BuildConfig.VERSION_NAME)
|
||||
}
|
||||
|
||||
private fun resetTitle() {
|
||||
|
@ -1,107 +1,42 @@
|
||||
package com.simplemobiletools.calendar.adapters
|
||||
|
||||
import android.graphics.PorterDuff
|
||||
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 android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.simplemobiletools.calendar.R
|
||||
import com.simplemobiletools.calendar.activities.SimpleActivity
|
||||
import com.simplemobiletools.calendar.dialogs.DeleteEventDialog
|
||||
import com.simplemobiletools.calendar.extensions.config
|
||||
import com.simplemobiletools.calendar.extensions.shareEvents
|
||||
import com.simplemobiletools.calendar.helpers.Formatter
|
||||
import com.simplemobiletools.calendar.interfaces.DeleteEventsListener
|
||||
import com.simplemobiletools.calendar.models.Event
|
||||
import com.simplemobiletools.commons.extensions.beInvisible
|
||||
import com.simplemobiletools.commons.extensions.beInvisibleIf
|
||||
import com.simplemobiletools.commons.interfaces.MyAdapterListener
|
||||
import kotlinx.android.synthetic.main.event_item_day_view.view.*
|
||||
import java.util.*
|
||||
|
||||
class DayEventsAdapter(val activity: SimpleActivity, val events: List<Event>, val listener: DeleteEventsListener?, val itemClick: (Event) -> Unit) :
|
||||
RecyclerView.Adapter<DayEventsAdapter.ViewHolder>() {
|
||||
private val config = activity.config
|
||||
private var actMode: ActionMode? = null
|
||||
private var textColor = config.textColor
|
||||
private val multiSelector = MultiSelector()
|
||||
private var itemViews = SparseArray<View>()
|
||||
private val selectedPositions = HashSet<Int>()
|
||||
class DayEventsAdapter(activity: SimpleActivity, val events: List<Event>, val listener: DeleteEventsListener?, itemClick: (Any) -> Unit) :
|
||||
MyAdapter(activity, itemClick) {
|
||||
|
||||
private var allDayString = activity.resources.getString(R.string.all_day)
|
||||
private var replaceDescriptionWithLocation = config.replaceDescription
|
||||
|
||||
fun toggleItemSelection(select: Boolean, pos: Int) {
|
||||
if (select) {
|
||||
if (itemViews[pos] != null) {
|
||||
selectedPositions.add(pos)
|
||||
}
|
||||
} else {
|
||||
selectedPositions.remove(pos)
|
||||
}
|
||||
override fun getActionMenuId() = R.menu.cab_day
|
||||
|
||||
override fun markItemSelection(select: Boolean, pos: Int) {
|
||||
itemViews[pos].event_item_frame.isSelected = select
|
||||
|
||||
if (selectedPositions.isEmpty()) {
|
||||
finishActMode()
|
||||
return
|
||||
}
|
||||
|
||||
updateTitle(selectedPositions.size)
|
||||
}
|
||||
|
||||
private fun updateTitle(cnt: Int) {
|
||||
actMode?.title = "$cnt / ${events.size}"
|
||||
actMode?.invalidate()
|
||||
}
|
||||
|
||||
private val adapterListener = object : MyAdapterListener {
|
||||
override fun toggleItemSelectionAdapter(select: Boolean, position: Int) {
|
||||
toggleItemSelection(select, position)
|
||||
override fun actionItemPressed(id: Int) {
|
||||
when (id) {
|
||||
R.id.cab_share -> shareEvents()
|
||||
R.id.cab_delete -> askConfirmDelete()
|
||||
}
|
||||
|
||||
override fun getSelectedPositions() = selectedPositions
|
||||
}
|
||||
|
||||
private val multiSelectorMode = object : ModalMultiSelectorCallback(multiSelector) {
|
||||
override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean {
|
||||
when (item.itemId) {
|
||||
R.id.cab_share -> shareEvents()
|
||||
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_day, menu)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onPrepareActionMode(actionMode: ActionMode?, menu: Menu) = true
|
||||
|
||||
override fun onDestroyActionMode(actionMode: ActionMode?) {
|
||||
super.onDestroyActionMode(actionMode)
|
||||
selectedPositions.forEach {
|
||||
itemViews[it].event_item_frame.isSelected = false
|
||||
}
|
||||
selectedPositions.clear()
|
||||
actMode = null
|
||||
}
|
||||
}
|
||||
|
||||
fun finishActMode() {
|
||||
actMode?.finish()
|
||||
}
|
||||
|
||||
private fun shareEvents() {
|
||||
val selections = multiSelector.selectedPositions
|
||||
val eventIds = ArrayList<Int>(selections.size)
|
||||
selections.forEach {
|
||||
val eventIds = ArrayList<Int>(selectedPositions.size)
|
||||
selectedPositions.forEach {
|
||||
eventIds.add(events[it].id)
|
||||
}
|
||||
activity.shareEvents(eventIds.distinct())
|
||||
@ -109,10 +44,9 @@ class DayEventsAdapter(val activity: SimpleActivity, val events: List<Event>, va
|
||||
}
|
||||
|
||||
private fun askConfirmDelete() {
|
||||
val selections = multiSelector.selectedPositions
|
||||
val eventIds = ArrayList<Int>(selections.size)
|
||||
val timestamps = ArrayList<Int>(selections.size)
|
||||
selections.forEach {
|
||||
val eventIds = ArrayList<Int>(selectedPositions.size)
|
||||
val timestamps = ArrayList<Int>(selectedPositions.size)
|
||||
selectedPositions.forEach {
|
||||
eventIds.add(events[it].id)
|
||||
timestamps.add(events[it].startTS)
|
||||
}
|
||||
@ -129,71 +63,50 @@ class DayEventsAdapter(val activity: SimpleActivity, val events: List<Event>, va
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): ViewHolder {
|
||||
val view = LayoutInflater.from(parent?.context).inflate(R.layout.event_item_day_view, parent, false)
|
||||
return ViewHolder(view, adapterListener, activity, multiSelectorMode, multiSelector, itemClick)
|
||||
return createViewHolder(view)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
override fun onBindViewHolder(holder: MyAdapter.ViewHolder, position: Int) {
|
||||
val event = events[position]
|
||||
itemViews.put(position, holder.bindView(event, textColor, replaceDescriptionWithLocation, allDayString))
|
||||
val view = holder.bindView(event) {
|
||||
setupView(it, event)
|
||||
}
|
||||
itemViews.put(position, view)
|
||||
toggleItemSelection(selectedPositions.contains(position), position)
|
||||
}
|
||||
|
||||
override fun getItemCount() = events.size
|
||||
|
||||
class ViewHolder(view: View, val adapterListener: MyAdapterListener, val activity: SimpleActivity, val multiSelectorCallback: ModalMultiSelectorCallback,
|
||||
val multiSelector: MultiSelector, val itemClick: (Event) -> (Unit)) : SwappingHolder(view, MultiSelector()) {
|
||||
fun bindView(event: Event, textColor: Int, replaceDescriptionWithLocation: Boolean, allDayString: String): View {
|
||||
itemView.apply {
|
||||
event_item_title.text = event.title
|
||||
event_item_description.text = if (replaceDescriptionWithLocation) event.location else event.description
|
||||
event_item_start.text = if (event.getIsAllDay()) allDayString else Formatter.getTimeFromTS(context, event.startTS)
|
||||
event_item_end.beInvisibleIf(event.startTS == event.endTS)
|
||||
event_item_color.setColorFilter(event.color, PorterDuff.Mode.SRC_IN)
|
||||
private fun setupView(view: View, event: Event) {
|
||||
view.apply {
|
||||
event_item_title.text = event.title
|
||||
event_item_description.text = if (replaceDescriptionWithLocation) event.location else event.description
|
||||
event_item_start.text = if (event.getIsAllDay()) allDayString else Formatter.getTimeFromTS(context, event.startTS)
|
||||
event_item_end.beInvisibleIf(event.startTS == event.endTS)
|
||||
event_item_color.setColorFilter(event.color, PorterDuff.Mode.SRC_IN)
|
||||
|
||||
if (event.startTS != event.endTS) {
|
||||
val startCode = Formatter.getDayCodeFromTS(event.startTS)
|
||||
val endCode = Formatter.getDayCodeFromTS(event.endTS)
|
||||
if (event.startTS != event.endTS) {
|
||||
val startCode = Formatter.getDayCodeFromTS(event.startTS)
|
||||
val endCode = Formatter.getDayCodeFromTS(event.endTS)
|
||||
|
||||
event_item_end.apply {
|
||||
text = Formatter.getTimeFromTS(context, event.endTS)
|
||||
if (startCode != endCode) {
|
||||
if (event.getIsAllDay()) {
|
||||
text = Formatter.getDateFromCode(context, endCode, true)
|
||||
} else {
|
||||
append(" (${Formatter.getDateFromCode(context, endCode, true)})")
|
||||
}
|
||||
} else if (event.getIsAllDay()) {
|
||||
beInvisible()
|
||||
event_item_end.apply {
|
||||
text = Formatter.getTimeFromTS(context, event.endTS)
|
||||
if (startCode != endCode) {
|
||||
if (event.getIsAllDay()) {
|
||||
text = Formatter.getDateFromCode(context, endCode, true)
|
||||
} else {
|
||||
append(" (${Formatter.getDateFromCode(context, endCode, true)})")
|
||||
}
|
||||
} else if (event.getIsAllDay()) {
|
||||
beInvisible()
|
||||
}
|
||||
}
|
||||
|
||||
event_item_start.setTextColor(textColor)
|
||||
event_item_end.setTextColor(textColor)
|
||||
event_item_title.setTextColor(textColor)
|
||||
event_item_description.setTextColor(textColor)
|
||||
|
||||
setOnClickListener { viewClicked(event) }
|
||||
setOnLongClickListener { viewLongClicked(); true }
|
||||
}
|
||||
|
||||
return itemView
|
||||
}
|
||||
|
||||
private fun viewClicked(event: Event) {
|
||||
if (multiSelector.isSelectable) {
|
||||
val isSelected = adapterListener.getSelectedPositions().contains(adapterPosition)
|
||||
adapterListener.toggleItemSelectionAdapter(!isSelected, adapterPosition)
|
||||
} else {
|
||||
itemClick(event)
|
||||
}
|
||||
}
|
||||
|
||||
private fun viewLongClicked() {
|
||||
if (!multiSelector.isSelectable) {
|
||||
activity.startSupportActionMode(multiSelectorCallback)
|
||||
adapterListener.toggleItemSelectionAdapter(true, adapterPosition)
|
||||
}
|
||||
event_item_start.setTextColor(textColor)
|
||||
event_item_end.setTextColor(textColor)
|
||||
event_item_title.setTextColor(textColor)
|
||||
event_item_description.setTextColor(textColor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ class EventListAdapter(val activity: SimpleActivity, val mItems: List<ListItem>,
|
||||
val markedItems = HashSet<Int>()
|
||||
|
||||
var topDivider: Drawable? = null
|
||||
var mNow = (System.currentTimeMillis() / 1000).toInt()
|
||||
var now = (System.currentTimeMillis() / 1000).toInt()
|
||||
var primaryColor = 0
|
||||
var textColor = 0
|
||||
var redTextColor = 0
|
||||
@ -65,7 +65,7 @@ class EventListAdapter(val activity: SimpleActivity, val mItems: List<ListItem>,
|
||||
|
||||
textColor = activity.config.textColor
|
||||
primaryColor = activity.config.primaryColor
|
||||
val mTodayCode = Formatter.getDayCodeFromTS(mNow)
|
||||
val mTodayCode = Formatter.getDayCodeFromTS(now)
|
||||
todayDate = Formatter.getDayTitle(activity, mTodayCode)
|
||||
replaceDescriptionWithLocation = activity.config.replaceDescription
|
||||
}
|
||||
@ -181,15 +181,15 @@ class EventListAdapter(val activity: SimpleActivity, val mItems: List<ListItem>,
|
||||
|
||||
var startTextColor = textColor
|
||||
var endTextColor = textColor
|
||||
if (item.startTS <= mNow && item.endTS <= mNow) {
|
||||
if (item.startTS <= now && item.endTS <= now) {
|
||||
if (item.isAllDay) {
|
||||
if (Formatter.getDayCodeFromTS(item.startTS) == Formatter.getDayCodeFromTS(mNow))
|
||||
if (Formatter.getDayCodeFromTS(item.startTS) == Formatter.getDayCodeFromTS(now))
|
||||
startTextColor = primaryColor
|
||||
} else {
|
||||
startTextColor = redTextColor
|
||||
}
|
||||
endTextColor = redTextColor
|
||||
} else if (item.startTS <= mNow && item.endTS >= mNow) {
|
||||
} else if (item.startTS <= now && item.endTS >= now) {
|
||||
startTextColor = primaryColor
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,121 @@
|
||||
package com.simplemobiletools.calendar.adapters
|
||||
|
||||
import android.support.v7.view.ActionMode
|
||||
import android.support.v7.widget.RecyclerView
|
||||
import android.util.SparseArray
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import com.bignerdranch.android.multiselector.ModalMultiSelectorCallback
|
||||
import com.bignerdranch.android.multiselector.MultiSelector
|
||||
import com.bignerdranch.android.multiselector.SwappingHolder
|
||||
import com.simplemobiletools.calendar.activities.SimpleActivity
|
||||
import com.simplemobiletools.calendar.extensions.config
|
||||
import com.simplemobiletools.commons.interfaces.MyAdapterListener
|
||||
import java.util.*
|
||||
|
||||
abstract class MyAdapter(val activity: SimpleActivity, val itemClick: (Any) -> Unit) : RecyclerView.Adapter<MyAdapter.ViewHolder>() {
|
||||
protected val config = activity.config
|
||||
protected var actMode: ActionMode? = null
|
||||
protected var primaryColor = config.primaryColor
|
||||
protected var textColor = config.textColor
|
||||
protected var itemViews = SparseArray<View>()
|
||||
protected val selectedPositions = HashSet<Int>()
|
||||
protected val multiSelector = MultiSelector()
|
||||
|
||||
abstract fun getActionMenuId(): Int
|
||||
|
||||
abstract fun markItemSelection(select: Boolean, pos: Int)
|
||||
|
||||
abstract fun actionItemPressed(id: Int)
|
||||
|
||||
protected fun toggleItemSelection(select: Boolean, pos: Int) {
|
||||
if (select) {
|
||||
if (itemViews[pos] != null) {
|
||||
selectedPositions.add(pos)
|
||||
}
|
||||
} else {
|
||||
selectedPositions.remove(pos)
|
||||
}
|
||||
|
||||
markItemSelection(select, pos)
|
||||
|
||||
if (selectedPositions.isEmpty()) {
|
||||
finishActMode()
|
||||
return
|
||||
}
|
||||
|
||||
updateTitle(selectedPositions.size)
|
||||
}
|
||||
|
||||
private fun updateTitle(cnt: Int) {
|
||||
actMode?.title = "$cnt / $itemCount"
|
||||
actMode?.invalidate()
|
||||
}
|
||||
|
||||
private val adapterListener = object : MyAdapterListener {
|
||||
override fun toggleItemSelectionAdapter(select: Boolean, position: Int) {
|
||||
toggleItemSelection(select, position)
|
||||
}
|
||||
|
||||
override fun getSelectedPositions() = selectedPositions
|
||||
}
|
||||
|
||||
private val multiSelectorMode = object : ModalMultiSelectorCallback(multiSelector) {
|
||||
override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean {
|
||||
actionItemPressed(item.itemId)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onCreateActionMode(actionMode: ActionMode?, menu: Menu?): Boolean {
|
||||
super.onCreateActionMode(actionMode, menu)
|
||||
actMode = actionMode
|
||||
activity.menuInflater.inflate(getActionMenuId(), menu)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onPrepareActionMode(actionMode: ActionMode?, menu: Menu) = true
|
||||
|
||||
override fun onDestroyActionMode(actionMode: ActionMode?) {
|
||||
super.onDestroyActionMode(actionMode)
|
||||
selectedPositions.forEach {
|
||||
markItemSelection(false, it)
|
||||
}
|
||||
selectedPositions.clear()
|
||||
actMode = null
|
||||
}
|
||||
}
|
||||
|
||||
fun finishActMode() {
|
||||
actMode?.finish()
|
||||
}
|
||||
|
||||
protected fun createViewHolder(view: View) = ViewHolder(view, adapterListener, activity, multiSelectorMode, multiSelector, itemClick)
|
||||
|
||||
class ViewHolder(view: View, val adapterListener: MyAdapterListener, val activity: SimpleActivity, val multiSelectorCallback: ModalMultiSelectorCallback,
|
||||
val multiSelector: MultiSelector, val itemClick: (Any) -> (Unit)) : SwappingHolder(view, multiSelector) {
|
||||
fun bindView(any: Any, callback: (itemView: View) -> Unit): View {
|
||||
return itemView.apply {
|
||||
callback(this)
|
||||
itemView.setOnClickListener { viewClicked(any) }
|
||||
itemView.setOnLongClickListener { viewLongClicked(); true }
|
||||
}
|
||||
}
|
||||
|
||||
private fun viewClicked(any: Any) {
|
||||
if (multiSelector.isSelectable) {
|
||||
val isSelected = adapterListener.getSelectedPositions().contains(adapterPosition)
|
||||
adapterListener.toggleItemSelectionAdapter(!isSelected, adapterPosition)
|
||||
} else {
|
||||
itemClick(any)
|
||||
}
|
||||
}
|
||||
|
||||
private fun viewLongClicked() {
|
||||
if (!multiSelector.isSelectable) {
|
||||
activity.startSupportActionMode(multiSelectorCallback)
|
||||
adapterListener.toggleItemSelectionAdapter(true, adapterPosition)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -140,7 +140,7 @@ class DayFragment : Fragment(), DBHelper.EventUpdateListener, DeleteEventsListen
|
||||
return
|
||||
|
||||
val eventsAdapter = DayEventsAdapter(activity as SimpleActivity, events, this) {
|
||||
editEvent(it)
|
||||
editEvent(it as Event)
|
||||
}
|
||||
|
||||
mHolder.day_events.adapter = eventsAdapter
|
||||
|
Loading…
x
Reference in New Issue
Block a user