allow drag selecting multiple events at the daily view

This commit is contained in:
tibbi 2017-11-13 21:54:46 +01:00
parent c2fe4d6bb0
commit befacff4e4
15 changed files with 125 additions and 42 deletions

View File

@ -47,7 +47,7 @@ ext {
}
dependencies {
compile 'com.simplemobiletools:commons:2.39.0'
compile 'com.simplemobiletools:commons:2.39.3'
compile 'joda-time:joda-time:2.9.9'
compile 'com.facebook.stetho:stetho:1.5.0'
compile 'com.bignerdranch.android:recyclerview-multiselect:0.2'

View File

@ -12,14 +12,19 @@ import com.simplemobiletools.calendar.models.Event
import com.simplemobiletools.commons.extensions.applyColorFilter
import com.simplemobiletools.commons.extensions.beInvisible
import com.simplemobiletools.commons.extensions.beInvisibleIf
import com.simplemobiletools.commons.views.MyRecyclerView
import kotlinx.android.synthetic.main.event_item_day_view.view.*
class DayEventsAdapter(activity: SimpleActivity, val events: List<Event>, val listener: DeleteEventsListener?, itemClick: (Any) -> Unit) :
MyAdapter(activity, itemClick) {
class DayEventsAdapter(activity: SimpleActivity, val events: List<Event>, val listener: DeleteEventsListener?, recyclerView: MyRecyclerView,
itemClick: (Any) -> Unit) : MyAdapter(activity, itemClick) {
private var allDayString = resources.getString(R.string.all_day)
private var replaceDescriptionWithLocation = config.replaceDescription
init {
setDragListenerRecyclerView(recyclerView)
}
override fun getActionMenuId() = R.menu.cab_day
override fun getSelectableItemCount() = events.size
@ -47,13 +52,14 @@ class DayEventsAdapter(activity: SimpleActivity, val events: List<Event>, val li
}
itemViews.put(position, view)
toggleItemSelection(selectedPositions.contains(position), position)
holder.itemView.tag = holder
}
override fun getItemCount() = events.size
private fun setupView(view: View, event: Event) {
view.apply {
event_item_title.text = event.title
event_section_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)
@ -79,7 +85,7 @@ class DayEventsAdapter(activity: SimpleActivity, val events: List<Event>, val li
event_item_start.setTextColor(textColor)
event_item_end.setTextColor(textColor)
event_item_title.setTextColor(textColor)
event_section_title.setTextColor(textColor)
event_item_description.setTextColor(textColor)
}
}
@ -90,7 +96,6 @@ class DayEventsAdapter(activity: SimpleActivity, val events: List<Event>, val li
eventIds.add(events[it].id)
}
activity.shareEvents(eventIds.distinct())
finishActMode()
}
private fun askConfirmDelete() {

View File

@ -70,7 +70,7 @@ class EventListAdapter(activity: SimpleActivity, val listItems: List<ListItem>,
private fun setupListEvent(view: View, listEvent: ListEvent) {
view.apply {
event_item_title.text = listEvent.title
event_section_title.text = listEvent.title
event_item_description.text = if (replaceDescriptionWithLocation) listEvent.location else listEvent.description
event_item_start.text = if (listEvent.isAllDay) allDayString else Formatter.getTimeFromTS(context, listEvent.startTS)
event_item_end.beInvisibleIf(listEvent.startTS == listEvent.endTS)
@ -110,13 +110,13 @@ class EventListAdapter(activity: SimpleActivity, val listItems: List<ListItem>,
event_item_start.setTextColor(startTextColor)
event_item_end.setTextColor(endTextColor)
event_item_title.setTextColor(startTextColor)
event_section_title.setTextColor(startTextColor)
event_item_description.setTextColor(startTextColor)
}
}
private fun setupListSection(view: View, listSection: ListSection, position: Int) {
view.event_item_title.apply {
view.event_section_title.apply {
text = listSection.title
setCompoundDrawablesWithIntrinsicBounds(null, if (position == 0) null else topDivider, null, null)
setTextColor(if (listSection.title == todayDate) primaryColor else textColor)

View File

@ -40,7 +40,7 @@ class EventListWidgetAdapter(val context: Context) : RemoteViewsService.RemoteVi
if (type == ITEM_EVENT) {
val item = events[position] as ListEvent
remoteView = RemoteViews(context.packageName, R.layout.event_list_item_widget).apply {
setText(R.id.event_item_title, item.title)
setText(R.id.event_section_title, item.title)
setText(R.id.event_item_description, if (replaceDescription) item.location else item.description)
setText(R.id.event_item_start, if (item.isAllDay) allDayString else Formatter.getTimeFromTS(context, item.startTS))
setImageViewBitmap(R.id.event_item_color, context.resources.getColoredBitmap(R.drawable.monthly_event_dot, item.color))
@ -65,12 +65,12 @@ class EventListWidgetAdapter(val context: Context) : RemoteViewsService.RemoteVi
setText(R.id.event_item_end, endString)
}
setTextColor(R.id.event_item_title, textColor)
setTextColor(R.id.event_section_title, textColor)
setTextColor(R.id.event_item_description, textColor)
setTextColor(R.id.event_item_start, textColor)
setTextColor(R.id.event_item_end, textColor)
setTextSize(R.id.event_item_title, mediumFontSize)
setTextSize(R.id.event_section_title, mediumFontSize)
setTextSize(R.id.event_item_description, mediumFontSize)
setTextSize(R.id.event_item_start, mediumFontSize)
setTextSize(R.id.event_item_end, mediumFontSize)
@ -84,9 +84,9 @@ class EventListWidgetAdapter(val context: Context) : RemoteViewsService.RemoteVi
} else {
val item = events[position] as ListSection
remoteView = RemoteViews(context.packageName, R.layout.event_list_section_widget).apply {
setTextColor(R.id.event_item_title, textColor)
setTextSize(R.id.event_item_title, mediumFontSize)
setText(R.id.event_item_title, item.title)
setTextColor(R.id.event_section_title, textColor)
setTextSize(R.id.event_section_title, mediumFontSize)
setText(R.id.event_section_title, item.title)
}
}

View File

@ -99,7 +99,7 @@ class EventListWidgetAdapterOld(val context: Context, val mEvents: List<ListItem
override fun getItemId(position: Int) = 0L
internal class ViewHolder(view: View) {
val title = view.event_item_title
val title = view.event_section_title
val description: TextView? = view.event_item_description
val start: TextView? = view.event_item_start
val end: TextView? = view.event_item_end

View File

@ -44,6 +44,8 @@ class FilterEventTypeAdapter(val activity: SimpleActivity, val eventTypes: List<
}
override fun getSelectedPositions() = selectedPositions
override fun itemLongClicked(position: Int) {}
}
fun getSelectedItemsSet(): HashSet<String> {

View File

@ -12,17 +12,20 @@ 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 com.simplemobiletools.commons.views.MyRecyclerView
import java.util.*
abstract class MyAdapter(val activity: SimpleActivity, val itemClick: (Any) -> Unit) : RecyclerView.Adapter<MyAdapter.ViewHolder>() {
protected val config = activity.config
protected val resources = activity.resources
protected var actMode: ActionMode? = null
protected val resources = activity.resources!!
protected var primaryColor = config.primaryColor
protected var textColor = config.textColor
protected val itemViews = SparseArray<View>()
protected val selectedPositions = HashSet<Int>()
protected val multiSelector = MultiSelector()
private val multiSelector = MultiSelector()
private var actMode: ActionMode? = null
private var myRecyclerView: MyRecyclerView? = null
abstract fun getActionMenuId(): Int
@ -56,12 +59,74 @@ abstract class MyAdapter(val activity: SimpleActivity, val itemClick: (Any) -> U
actMode?.invalidate()
}
protected fun setDragListenerRecyclerView(recyclerView: MyRecyclerView) {
myRecyclerView = recyclerView
myRecyclerView!!.setupDragListener(object : MyRecyclerView.MyDragListener {
override fun selectItem(position: Int) {
selectItemPosition(position)
}
override fun selectRange(initialSelection: Int, lastDraggedIndex: Int, minReached: Int, maxReached: Int) {
selectItemRange(initialSelection, lastDraggedIndex, minReached, maxReached)
}
})
}
fun selectItemPosition(pos: Int) {
toggleItemSelection(true, pos)
}
fun selectItemRange(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)
}
}
}
}
fun finishActMode() {
actMode?.finish()
}
private val adapterListener = object : MyAdapterListener {
override fun toggleItemSelectionAdapter(select: Boolean, position: Int) {
toggleItemSelection(select, position)
}
override fun getSelectedPositions() = selectedPositions
override fun itemLongClicked(position: Int) {
myRecyclerView?.setDragSelectActive(position)
}
}
private val multiSelectorMode = object : ModalMultiSelectorCallback(multiSelector) {
@ -89,10 +154,6 @@ abstract class MyAdapter(val activity: SimpleActivity, val itemClick: (Any) -> U
}
}
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,
@ -100,8 +161,14 @@ abstract class MyAdapter(val activity: SimpleActivity, val itemClick: (Any) -> U
fun bindView(any: Any, callback: (itemView: View) -> Unit): View {
return itemView.apply {
callback(this)
itemView.setOnClickListener { viewClicked(any) }
itemView.setOnLongClickListener { viewLongClicked(); true }
if (isClickable) {
setOnClickListener { viewClicked(any) }
setOnLongClickListener { viewLongClicked(); true }
} else {
setOnClickListener(null)
setOnLongClickListener(null)
}
}
}
@ -119,6 +186,8 @@ abstract class MyAdapter(val activity: SimpleActivity, val itemClick: (Any) -> U
activity.startSupportActionMode(multiSelectorCallback)
adapterListener.toggleItemSelectionAdapter(true, adapterPosition)
}
adapterListener.itemLongClicked(adapterPosition)
}
}
}

View File

@ -138,7 +138,7 @@ class DayFragment : Fragment(), DBHelper.EventUpdateListener, DeleteEventsListen
if (activity == null)
return
val eventsAdapter = DayEventsAdapter(activity as SimpleActivity, events, this) {
val eventsAdapter = DayEventsAdapter(activity as SimpleActivity, events, this, mHolder.day_events) {
editEvent(it as Event)
}

View File

@ -6,6 +6,8 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:foreground="@drawable/selector">
<RelativeLayout
@ -31,7 +33,7 @@
android:textSize="@dimen/day_text_size"/>
<com.simplemobiletools.commons.views.MyTextView
android:id="@+id/event_item_title"
android:id="@+id/event_section_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/activity_margin"
@ -47,7 +49,7 @@
android:id="@+id/event_item_description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/event_item_title"
android:layout_below="@+id/event_section_title"
android:layout_marginLeft="@dimen/activity_margin"
android:layout_toLeftOf="@+id/event_item_color"
android:layout_toRightOf="@+id/event_item_end"
@ -62,10 +64,10 @@
android:id="@+id/event_item_color"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignBottom="@+id/event_item_title"
android:layout_alignBottom="@+id/event_section_title"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_alignTop="@+id/event_item_title"
android:layout_alignTop="@+id/event_section_title"
android:paddingRight="@dimen/activity_margin"
android:src="@drawable/monthly_event_dot"/>

View File

@ -6,13 +6,14 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:foreground="@drawable/selector">
<RelativeLayout
android:id="@+id/event_item_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/selector"
android:paddingBottom="@dimen/medium_margin"
android:paddingLeft="@dimen/activity_margin"
android:paddingRight="@dimen/activity_margin"
@ -34,7 +35,7 @@
android:textSize="@dimen/day_text_size"/>
<com.simplemobiletools.commons.views.MyTextView
android:id="@+id/event_item_title"
android:id="@+id/event_section_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/activity_margin"
@ -50,7 +51,7 @@
android:id="@+id/event_item_description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/event_item_title"
android:layout_below="@+id/event_section_title"
android:layout_marginLeft="@dimen/activity_margin"
android:layout_toLeftOf="@+id/event_item_color"
android:layout_toRightOf="@+id/event_item_end"
@ -65,10 +66,10 @@
android:id="@+id/event_item_color"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignBottom="@+id/event_item_title"
android:layout_alignBottom="@+id/event_section_title"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_alignTop="@+id/event_item_title"
android:layout_alignTop="@+id/event_section_title"
android:paddingRight="@dimen/medium_margin"
android:src="@drawable/monthly_event_dot"/>

View File

@ -24,7 +24,7 @@
android:textSize="@dimen/day_text_size"/>
<TextView
android:id="@+id/event_item_title"
android:id="@+id/event_section_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/big_margin"
@ -40,7 +40,7 @@
android:id="@+id/event_item_description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/event_item_title"
android:layout_below="@+id/event_section_title"
android:layout_marginLeft="@dimen/big_margin"
android:layout_toLeftOf="@+id/event_item_color"
android:layout_toRightOf="@+id/event_item_end"
@ -55,10 +55,10 @@
android:id="@+id/event_item_color"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignBottom="@+id/event_item_title"
android:layout_alignBottom="@+id/event_section_title"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_alignTop="@+id/event_item_title"
android:layout_alignTop="@+id/event_section_title"
android:paddingRight="@dimen/activity_margin"
android:src="@drawable/monthly_event_dot"/>

View File

@ -1,11 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<com.simplemobiletools.commons.views.MyTextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/event_item_title"
android:id="@+id/event_section_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="false"
android:drawablePadding="1dp"
android:drawableTop="@drawable/divider_width"
android:focusable="false"
android:paddingTop="@dimen/medium_margin"
android:textSize="@dimen/normal_text_size"
android:textStyle="bold"/>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/event_item_title"
android:id="@+id/event_section_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawablePadding="1dp"

View File

@ -8,7 +8,7 @@
<include layout="@layout/top_navigation"/>
<android.support.v7.widget.RecyclerView
<com.simplemobiletools.commons.views.MyRecyclerView
android:id="@+id/day_events"
android:layout_width="match_parent"
android:layout_height="wrap_content"

View File

@ -5,6 +5,8 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:foreground="@drawable/selector">
<RelativeLayout