Skip to content

Commit 1a2bdef

Browse files
committed
- updated sample app
- fixed share sample action not finding any Apps to use - fixed rare error with delete action when a viewholder has -1 as adapter position - fixed some problems with replacing an action at runtime
1 parent aecbedb commit 1a2bdef

File tree

8 files changed

+137
-50
lines changed

8 files changed

+137
-50
lines changed

app/src/main/java/de/taop/swipeactionsample/MainActivity.kt

Lines changed: 72 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,68 +3,120 @@ package de.taop.swipeactionsample
33
import android.os.Bundle
44
import android.support.v7.app.AppCompatActivity
55
import android.support.v7.widget.LinearLayoutManager
6+
import android.support.v7.widget.helper.ItemTouchHelper
7+
import android.util.Log
68
import android.view.Menu
79
import android.view.MenuItem
10+
import android.view.View
11+
import android.widget.AdapterView
812
import de.taop.swipeaction.AlternatingBackgroundItemDecoration
913
import de.taop.swipeaction.SwipeActionSetupHelper
1014
import de.taop.swipeaction.actions.DeleteAction
15+
import de.taop.swipeaction.actions.SwipeAction
1116
import de.taop.swipeactionsample.dummyItems.DummyAdapter
1217
import de.taop.swipeactionsample.dummyItems.DummyItem
18+
import de.taop.swipeactionsample.sampleActions.ShareAction
1319

1420
import kotlinx.android.synthetic.main.activity_main.*
1521
import kotlinx.android.synthetic.main.content_main.*
1622

1723
class MainActivity : AppCompatActivity() {
1824

25+
//needed for changing actions at runtime
26+
private var oldItemTouchHelper: ItemTouchHelper? = null
27+
1928
override fun onCreate(savedInstanceState: Bundle?) {
2029
super.onCreate(savedInstanceState)
2130
setContentView(R.layout.activity_main)
2231
setSupportActionBar(toolbar)
2332

33+
// add new item on click
2434
fab.setOnClickListener {
2535
(list.adapter as DummyAdapter).addItem(DummyItem())
2636
}
2737

38+
//setup recyclerview
2839
list.layoutManager = LinearLayoutManager(this)
2940
list.adapter = DummyAdapter(List(6, {
3041
DummyItem(it)
3142
}) as ArrayList<DummyItem>)
3243

33-
// set Background colors of list
34-
list.addItemDecoration(AlternatingBackgroundItemDecoration(this, R.color.colorWhite, R.color.colorGrey))
35-
3644
// create swipe actions
45+
val shareAction = ShareAction(list)
3746
val pendingDeleteAction = DeleteAction(list, R.id.container)
3847
val instantDeleteAction = DeleteAction(list, R.id.container,
3948
false,
4049
iconID = R.drawable.ic_delete_forever_black_24dp,
41-
colorID = R.color.colorInstantDelete)
50+
colorID = R.color.colorInstantDelete,
51+
name = "instantDelete")
4252

43-
instantDeleteAction.setSnackBarText(R.string.deleteUndo, R.plurals.deletedItems)
44-
45-
SwipeActionSetupHelper.setUpRecyclerView(this, list, pendingDeleteAction, instantDeleteAction)
53+
// set delete snackbar Text
54+
pendingDeleteAction.setSnackBarText(R.string.deleteUndo, R.plurals.deletedItems)
4655

56+
// on delete listener
4757
instantDeleteAction.itemsDeletedCallback = {
4858
}
4959

5060
pendingDeleteAction.itemsDeletedCallback = {
5161
}
5262

53-
}
63+
// set alternating background colors (optional)
64+
list.addItemDecoration(AlternatingBackgroundItemDecoration(this, R.color.colorWhite, R.color.colorGrey))
5465

55-
override fun onCreateOptionsMenu(menu: Menu): Boolean {
56-
// Inflate the menu; this adds items to the action bar if it is present.
57-
menuInflater.inflate(R.menu.menu_main, menu)
58-
return true
59-
}
66+
/*initialize the swipe actions
67+
this is required! it's not used in the example because we use the two spinners to set up the recyclerview*/
68+
// SwipeActionSetupHelper.setUpRecyclerView(this@MainActivity, list, pendingDeleteAction, pendingDeleteAction)
69+
70+
// apply different actions
71+
var swipeLeftAction: SwipeAction = pendingDeleteAction
72+
var swipeRightAction: SwipeAction = pendingDeleteAction
73+
74+
// not very clean code but works for this example!
75+
leftActionSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
76+
override fun onNothingSelected(p0: AdapterView<*>?) {
77+
}
78+
79+
override fun onItemSelected(p0: AdapterView<*>?, p1: View?, p2: Int, p3: Long) {
80+
swipeRightAction = when (p2) {
81+
0 -> pendingDeleteAction
82+
1 -> instantDeleteAction
83+
2 -> shareAction
84+
else -> pendingDeleteAction
85+
}
86+
updateRecyclerView(swipeLeftAction, swipeRightAction)
87+
}
6088

61-
override fun onOptionsItemSelected(item: MenuItem): Boolean {
62-
// Handle action bar item clicks here. The action bar will
63-
// automatically handle clicks on the Home/Up button, so long
64-
// as you specify a parent activity in AndroidManifest.xml.
65-
return when (item.itemId) {
66-
R.id.action_settings -> true
67-
else -> super.onOptionsItemSelected(item)
6889
}
90+
91+
rightActionSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
92+
override fun onNothingSelected(p0: AdapterView<*>?) {
93+
}
94+
95+
override fun onItemSelected(p0: AdapterView<*>?, p1: View?, p2: Int, p3: Long) {
96+
swipeLeftAction = when (p2) {
97+
0 -> pendingDeleteAction
98+
1 -> instantDeleteAction
99+
2 -> shareAction
100+
else -> pendingDeleteAction
101+
}
102+
updateRecyclerView(swipeLeftAction, swipeRightAction)
103+
}
104+
}
105+
}
106+
107+
private fun updateRecyclerView(swipeLeftAction: SwipeAction, swipeRightAction: SwipeAction) {
108+
// if an pending delete is active --> undo it
109+
(swipeLeftAction as? DeleteAction)?.undoPendingItems(true)
110+
(swipeRightAction as? DeleteAction)?.undoPendingItems(true)
111+
112+
113+
// reset all items --> redraws the item!
114+
list.adapter.notifyItemRangeChanged(0, list.adapter.itemCount - 1)
115+
116+
// This is absolutely necessary if you want to change the action on the fly!
117+
// Otherwise the actions won't update!
118+
oldItemTouchHelper?.attachToRecyclerView(null)
119+
oldItemTouchHelper = SwipeActionSetupHelper.setUpRecyclerView(this@MainActivity, list, swipeLeftAction, swipeRightAction)
120+
69121
}
70122
}

app/src/main/java/de/taop/swipeactionsample/sampleActions/ShareAction.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,10 @@ class ShareAction(recyclerView: RecyclerView) : de.taop.swipeaction.actions.Swip
4141
startShareIntent("Position $adapterPosition was shared!")
4242
}
4343

44-
private fun startShareIntent(urlKey: String) {
44+
private fun startShareIntent(text: String) {
4545
val share = Intent(Intent.ACTION_SEND)
46-
share.type = "text"
47-
share.putExtra(Intent.EXTRA_TEXT, urlKey)
46+
share.type = "text/plain"
47+
share.putExtra(Intent.EXTRA_TEXT, text)
4848
// grants user read permission to the uri if needed
4949
startActivity(context, Intent.createChooser(share, "Share Action"), null)
5050
}

app/src/main/res/layout/activity_main.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
android:layout_height="wrap_content"
3131
android:layout_gravity="bottom|end"
3232
android:layout_margin="@dimen/fab_margin"
33+
android:tint="@color/colorWhite"
3334
app:srcCompat="@drawable/ic_add_black_24dp" />
3435

3536
</android.support.design.widget.CoordinatorLayout>

app/src/main/res/layout/content_main.xml

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,44 @@
66
android:layout_height="match_parent"
77
app:layout_behavior="@string/appbar_scrolling_view_behavior"
88
tools:context="de.taop.swipeactionsample.MainActivity"
9-
tools:showIn="@layout/activity_main">
9+
tools:showIn="@layout/activity_main"
10+
>
11+
12+
<Spinner
13+
android:id="@+id/leftActionSpinner"
14+
android:layout_width="wrap_content"
15+
android:layout_height="wrap_content"
16+
android:layout_marginStart="8dp"
17+
android:layout_marginTop="16dp"
18+
android:entries="@array/actions"
19+
app:layout_constraintStart_toStartOf="parent"
20+
app:layout_constraintTop_toTopOf="parent"
21+
android:layout_marginLeft="8dp">
22+
23+
</Spinner>
24+
25+
<Spinner
26+
android:id="@+id/rightActionSpinner"
27+
android:layout_width="wrap_content"
28+
android:layout_height="wrap_content"
29+
android:layout_marginEnd="8dp"
30+
android:layout_marginTop="16dp"
31+
android:entries="@array/actions"
32+
app:layout_constraintEnd_toEndOf="parent"
33+
app:layout_constraintTop_toTopOf="parent"
34+
android:layout_marginRight="8dp">
35+
36+
</Spinner>
1037

1138
<android.support.v7.widget.RecyclerView
1239
android:id="@+id/list"
1340
android:layout_width="0dp"
1441
android:layout_height="0dp"
42+
android:layout_marginTop="16dp"
1543
app:layout_constraintBottom_toBottomOf="parent"
1644
app:layout_constraintEnd_toEndOf="parent"
1745
app:layout_constraintStart_toStartOf="parent"
18-
app:layout_constraintTop_toTopOf="parent">
46+
app:layout_constraintTop_toBottomOf="@+id/rightActionSpinner">
1947

2048
</android.support.v7.widget.RecyclerView>
2149

app/src/main/res/menu/menu_main.xml

Lines changed: 0 additions & 10 deletions
This file was deleted.
Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
11
<resources>
22
<string name="app_name">SwipeActionSample</string>
3-
<string name="action_settings">Settings</string>
3+
4+
<array name="actions">
5+
<item>Pending Delete</item>
6+
<item>Instant Delete</item>
7+
<item>Share</item>
8+
</array>
9+
410
</resources>

swipeaction/src/main/java/de/taop/swipeaction/SwipeActionSetupHelper.kt

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import android.graphics.drawable.Drawable
77
import android.support.v4.content.ContextCompat
88
import android.support.v7.widget.RecyclerView
99
import android.support.v7.widget.helper.ItemTouchHelper
10+
import android.util.Log
1011
import de.taop.swipeaction.actions.SwipeAction
1112

1213
/**
@@ -23,13 +24,9 @@ class SwipeActionSetupHelper {
2324
setUpRecyclerView(context, recyclerView, action, action)
2425
}
2526

26-
fun setUpRecyclerView(context: Context, recyclerView: RecyclerView, leftAction: SwipeAction, rightAction: SwipeAction) {
27-
// we won't recycle the viewHolder because otherwise it could
28-
// interfere with other actions since we change the size of the
29-
// item.
30-
27+
fun setUpRecyclerView(context: Context, recyclerView: RecyclerView, leftAction: SwipeAction, rightAction: SwipeAction) : ItemTouchHelper{
3128
val callback = object : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT) {
32-
// we want to cache these and not allocate anything repeatedly in the onChildDraw method
29+
3330
internal lateinit var leftBackground: Drawable
3431
internal lateinit var rightBackground: Drawable
3532
lateinit var background: Drawable
@@ -57,6 +54,7 @@ class SwipeActionSetupHelper {
5754
}
5855

5956
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, swipeDir: Int) {
57+
6058
when (swipeDir) {
6159
ItemTouchHelper.LEFT -> {
6260
leftAction.performAction(viewHolder, ItemTouchHelper.LEFT)
@@ -120,11 +118,18 @@ class SwipeActionSetupHelper {
120118

121119

122120
}
123-
val itemTouchHelper = ItemTouchHelper(callback)
121+
/*
122+
123+
//reset recyclerview if it has been set up before
124+
recyclerView.invalidateItemDecorations()
125+
recyclerView.clearOnChildAttachStateChangeListeners()
126+
recyclerView.recycledViewPool.clear()
127+
*/
124128

129+
val itemTouchHelper = ItemTouchHelper(callback)
125130
itemTouchHelper.attachToRecyclerView(recyclerView)
126131

127-
//recyclerView.addItemDecoration(SwipeActionItemDecoration())
132+
return itemTouchHelper
128133

129134
}
130135
}

swipeaction/src/main/java/de/taop/swipeaction/actions/DeleteAction.kt

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,9 @@ import de.taop.swipeaction.addEndListener
3131
*/
3232
class DeleteAction(recyclerView: RecyclerView, @IdRes val snackBarParentID: Int, val allowUndo: Boolean = true,
3333
@DrawableRes val iconID: Int = R.drawable.ic_delete_sweep_black_24dp,
34-
@ColorRes val colorID: Int = R.color.colorPendingDelete)
35-
: SwipeAction(recyclerView, "pendingDelete", actionIconID = iconID, actionBGColorID = colorID) {
34+
@ColorRes val colorID: Int = R.color.colorPendingDelete,
35+
name: String = "pendingDelete")
36+
: SwipeAction(recyclerView, name, actionIconID = iconID, actionBGColorID = colorID) {
3637

3738
@StringRes
3839
private var deleteUndoID: Int = R.string.deleteUndo
@@ -180,7 +181,9 @@ class DeleteAction(recyclerView: RecyclerView, @IdRes val snackBarParentID: Int,
180181
/**
181182
* Undos all Pending items.
182183
*/
183-
private fun undoPendingItems() {
184+
fun undoPendingItems(closeSnackBar: Boolean = false) {
185+
if (closeSnackBar) snackBar.dismiss()
186+
184187
for (i in pendingRemovalItems) {
185188
growItemToOriginalHeight(i.adapterPosition)
186189
adapter.notifyItemChanged(i.adapterPosition)
@@ -217,13 +220,15 @@ class DeleteAction(recyclerView: RecyclerView, @IdRes val snackBarParentID: Int,
217220
//if the view was sized down we first need to restore its original height
218221
//otherwise the height will stay at 0 even after recycling
219222
it.itemView?.layoutParams?.height = originalItemHeights[it]
220-
finalRemoval(it.adapterPosition)
221-
removed = true
223+
if (it.adapterPosition != -1) {
224+
finalRemoval(it.adapterPosition)
225+
removed = true
226+
}
222227
})
223228

224229
pendingRemovalItems.clear()
225230

226-
if (removed) {
231+
if (removed) { // invoke callback
227232
itemsDeletedCallback.invoke(
228233
pendingRemovalItems.map { it.adapterPosition }.toIntArray()
229234
)

0 commit comments

Comments
 (0)