Skip to content

Commit cb4b0c8

Browse files
committed
Merge pull request #3 from minibugdev/feature/search-items
Supported to search items
2 parents 3327b03 + e0665b5 commit cb4b0c8

File tree

9 files changed

+153
-19
lines changed

9 files changed

+153
-19
lines changed

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,12 @@ repositories {
1717
Add the dependency
1818
``` groovy
1919
dependencies {
20-
implementation 'com.github.minibugdev:sheetselection:0.0.1'
20+
implementation 'com.github.minibugdev:sheetselection:0.0.2'
2121
}
2222
```
2323

2424
## How to use
25-
![Sheet Selection](screenshot/ss_1.png)
25+
![Sheet Selection](screenshot/ss_1_0.0.2.png)
2626

2727
``` kotlin
2828
val items = listOf(
@@ -37,6 +37,7 @@ SheetSelection.Builder(context)
3737
.items(items)
3838
.selectedPosition(2)
3939
.showDraggedIndicator(true)
40+
.searchEnabled(true)
4041
.onItemClickListener { item, position ->
4142
// DO SOMETHING
4243
}
@@ -47,6 +48,7 @@ SheetSelection.Builder(context)
4748
- Set items by `Builder.items(List<SheetSelectionItem>)`.
4849
- Set selected item by `Builder.selectedPosition(Int)`. default is `SheetSelection.NO_SELECT`
4950
- Show dragged indicator by `Builder.showDraggedIndicator(Boolean)`. default is `false`
51+
- Set search enabled by `Builder.searchEnabled(Boolean)`. default is `false`
5052
- Set custom theme by `Builder.theme(@StyleRes)`.
5153
- To handle the item click listener by `Builder.onItemClickListener()`.
5254

app/src/main/java/com/minibugdev/sheetselection/demo/MainActivity.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,17 @@ class MainActivity : AppCompatActivity() {
1717
SheetSelectionItem("1", "Item #1", R.drawable.ic_extension),
1818
SheetSelectionItem("2", "Item #2", R.drawable.ic_nature),
1919
SheetSelectionItem("3", "Item #3", R.drawable.ic_fingerprint),
20-
SheetSelectionItem("4", "Item #4", R.drawable.ic_face)
20+
SheetSelectionItem("4", "Item #4", R.drawable.ic_face),
21+
SheetSelectionItem("5", "Item #5", R.drawable.ic_extension),
22+
SheetSelectionItem("6", "Item #6", R.drawable.ic_fingerprint)
2123
)
2224

2325
SheetSelection.Builder(this)
2426
.title("Sheet Selection")
2527
.items(items)
2628
.selectedPosition(2)
2729
.showDraggedIndicator(true)
30+
.searchEnabled(true)
2831
.onItemClickListener { item, position ->
2932
textview.text = "You selected `${item.value}`, At position [$position]."
3033
}
@@ -46,6 +49,7 @@ class MainActivity : AppCompatActivity() {
4649
)
4750
.selectedPosition(2)
4851
.showDraggedIndicator(true)
52+
.searchEnabled(true)
4953
.theme(R.style.Theme_Custom_SheetSelection)
5054
.onItemClickListener { item, position ->
5155
textview.text = "You selected `${item.value}`, At position [$position]."

screenshot/ss_1.png

-23.4 KB
Binary file not shown.

screenshot/ss_1_0.0.2.png

28.4 KB
Loading

sheetselection/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ android {
1313
minSdkVersion 17
1414
targetSdkVersion 29
1515
versionCode 1
16-
versionName "0.0.1"
16+
versionName "0.0.2"
1717
}
1818

1919
buildTypes {

sheetselection/src/main/java/com/minibugdev/sheetselection/SheetSelection.kt

Lines changed: 72 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,37 @@ import android.view.LayoutInflater
66
import android.view.View
77
import android.view.ViewGroup
88
import androidx.annotation.StyleRes
9+
import androidx.appcompat.widget.SearchView
910
import androidx.fragment.app.Fragment
1011
import androidx.fragment.app.FragmentActivity
1112
import androidx.fragment.app.FragmentManager
13+
import com.google.android.material.bottomsheet.BottomSheetBehavior
14+
import com.google.android.material.bottomsheet.BottomSheetDialog
1215
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
1316
import kotlinx.android.synthetic.main.dialog_sheet_selection.*
1417

1518
class SheetSelection private constructor() : BottomSheetDialogFragment() {
1619

1720
var onItemClickListener: OnItemSelectedListener? = null
1821

22+
private val adapter by lazy {
23+
SheetSelectionAdapter(
24+
source = arguments?.getParcelableArrayList(ARGS_ITEMS) ?: emptyList(),
25+
selectedPosition = arguments?.getInt(ARGS_SELECTED_POSITION, NO_SELECT) ?: NO_SELECT,
26+
onItemSelectedListener = onItemSelectedListener
27+
)
28+
}
29+
30+
private val screenHeight by lazy {
31+
val statusBarHeight = try {
32+
val resourceId = resources.getIdentifier("status_bar_height", "dimen", "android")
33+
resources.getDimensionPixelSize(resourceId)
34+
} catch (e: Exception) {
35+
0
36+
}
37+
resources.displayMetrics.heightPixels - statusBarHeight
38+
}
39+
1940
override fun getTheme(): Int = arguments?.getInt(ARGS_THEME) ?: super.getTheme()
2041

2142
override fun onCreateView(
@@ -36,23 +57,61 @@ class SheetSelection private constructor() : BottomSheetDialogFragment() {
3657
val title = args.getString(ARGS_TITLE)
3758
if (title.isNullOrEmpty()) {
3859
textViewTitle.visibility = View.GONE
60+
textViewTitle.text = null
3961
} else {
62+
textViewTitle.visibility = View.VISIBLE
4063
textViewTitle.text = title
4164
}
4265

43-
recyclerViewSelectionItems.adapter = SheetSelectionAdapter(
44-
items = args.getParcelableArrayList(ARGS_ITEMS) ?: emptyList(),
45-
selectedPosition = args.getInt(ARGS_SELECTED_POSITION, NO_SELECT),
46-
onItemSelectedListener = internalOnItemSelectedListener
47-
)
66+
if (args.getBoolean(ARGS_SEARCH_ENABLED)) {
67+
buttonSearch.visibility = View.VISIBLE
68+
buttonSearch.setOnClickListener(onSearchClickListener)
69+
searchView.setOnCloseListener(onSearchCloseListener)
70+
searchView.setOnQueryTextListener(onSearchQueryTextListener)
71+
}
72+
73+
recyclerViewSelectionItems.setHasFixedSize(true)
74+
recyclerViewSelectionItems.adapter = adapter
4875
}
4976
}
5077

51-
private val internalOnItemSelectedListener: OnItemSelectedListener = { item, position ->
78+
private fun updateSheetHeight(viewHeight: Int) {
79+
rootLayout.layoutParams = rootLayout.layoutParams
80+
.apply { height = viewHeight }
81+
}
82+
83+
private val onItemSelectedListener: OnItemSelectedListener = { item, position ->
5284
dismiss()
5385
onItemClickListener?.invoke(item, position)
5486
}
5587

88+
private val onSearchClickListener = View.OnClickListener {
89+
(dialog as? BottomSheetDialog)?.run {
90+
behavior.state = BottomSheetBehavior.STATE_EXPANDED
91+
}
92+
updateSheetHeight(screenHeight)
93+
viewSwitcherHeader.displayedChild = 1
94+
searchView.isIconified = false
95+
}
96+
97+
private val onSearchCloseListener = SearchView.OnCloseListener {
98+
updateSheetHeight(ViewGroup.LayoutParams.WRAP_CONTENT)
99+
viewSwitcherHeader.displayedChild = 0
100+
true
101+
}
102+
103+
private val onSearchQueryTextListener = object : SearchView.OnQueryTextListener {
104+
override fun onQueryTextChange(newText: String?): Boolean {
105+
adapter.search(newText)
106+
return true
107+
}
108+
109+
override fun onQueryTextSubmit(query: String?): Boolean {
110+
adapter.search(query)
111+
return true
112+
}
113+
}
114+
56115
class Builder(context: Context) {
57116
private val manager: FragmentManager? = when (context) {
58117
is FragmentActivity -> context.supportFragmentManager
@@ -66,6 +125,7 @@ class SheetSelection private constructor() : BottomSheetDialogFragment() {
66125
private var items: List<SheetSelectionItem> = emptyList()
67126
private var selectedPosition: Int = NO_SELECT
68127
private var showDraggedIndicator: Boolean = false
128+
private var searchEnabled: Boolean = false
69129
private var listener: OnItemSelectedListener? = null
70130

71131
fun theme(@StyleRes themeId: Int) = apply {
@@ -93,6 +153,10 @@ class SheetSelection private constructor() : BottomSheetDialogFragment() {
93153
this.showDraggedIndicator = show
94154
}
95155

156+
fun searchEnabled(enabled: Boolean) = apply {
157+
this.searchEnabled = enabled
158+
}
159+
96160
fun onItemClickListener(listener: OnItemSelectedListener) = apply {
97161
this.listener = listener
98162
}
@@ -105,6 +169,7 @@ class SheetSelection private constructor() : BottomSheetDialogFragment() {
105169
putParcelableArrayList(ARGS_ITEMS, ArrayList(items))
106170
putInt(ARGS_SELECTED_POSITION, selectedPosition)
107171
putBoolean(ARGS_SHOW_DRAGGED_INDICATOR, showDraggedIndicator)
172+
putBoolean(ARGS_SEARCH_ENABLED, searchEnabled)
108173
}
109174
onItemClickListener = listener
110175
}
@@ -124,5 +189,6 @@ class SheetSelection private constructor() : BottomSheetDialogFragment() {
124189
private const val ARGS_ITEMS = "SheetSelection:ARGS_ITEMS"
125190
private const val ARGS_SELECTED_POSITION = "SheetSelection:ARGS_SELECTED_POSITION"
126191
private const val ARGS_SHOW_DRAGGED_INDICATOR = "SheetSelection:ARGS_SHOW_DRAGGED_INDICATOR"
192+
private const val ARGS_SEARCH_ENABLED = "SheetSelection:ARGS_SEARCH_ENABLED"
127193
}
128194
}

sheetselection/src/main/java/com/minibugdev/sheetselection/SheetSelectionAdapter.kt

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,13 @@ import kotlinx.android.synthetic.main.row_selection_item.*
1010
typealias OnItemSelectedListener = (item: SheetSelectionItem, position: Int) -> Unit
1111

1212
class SheetSelectionAdapter(
13-
private val items: List<SheetSelectionItem>,
13+
private val source: List<SheetSelectionItem>,
1414
private val selectedPosition: Int,
1515
private val onItemSelectedListener: OnItemSelectedListener?
1616
) : RecyclerView.Adapter<SheetSelectionAdapter.ViewHolder>() {
1717

18+
private var items: List<SheetSelectionItem> = source
19+
1820
override fun getItemCount() = items.size
1921

2022
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
@@ -27,13 +29,31 @@ class SheetSelectionAdapter(
2729

2830
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
2931
holder.onBindView(
30-
items[position],
31-
position,
32-
position == selectedPosition,
33-
onItemSelectedListener
32+
item = items[position],
33+
position = position,
34+
selected = position == selectedPosition,
35+
onItemSelectedListener = onItemSelectedListener
3436
)
3537
}
3638

39+
fun search(keyword: String?) {
40+
if (keyword.isNullOrBlank()) {
41+
updateItems(source)
42+
} else {
43+
val searchResult = source.filter { it.value.contains(keyword, true) }
44+
if (searchResult.isEmpty()) {
45+
updateItems(listOf(SheetSelectionItem("search_not_found", "Search not found.")))
46+
} else {
47+
updateItems(searchResult)
48+
}
49+
}
50+
}
51+
52+
private fun updateItems(items: List<SheetSelectionItem>) {
53+
this.items = items
54+
notifyDataSetChanged()
55+
}
56+
3757
class ViewHolder(override val containerView: View) : RecyclerView.ViewHolder(containerView),
3858
LayoutContainer {
3959

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
2+
android:width="24dp"
3+
android:height="24dp"
4+
android:viewportWidth="24.0"
5+
android:viewportHeight="24.0">
6+
<path
7+
android:fillColor="#FF000000"
8+
android:pathData="M15.5,14h-0.79l-0.28,-0.27C15.41,12.59 16,11.11 16,9.5 16,5.91 13.09,3 9.5,3S3,5.91 3,9.5 5.91,16 9.5,16c1.61,0 3.09,-0.59 4.23,-1.57l0.27,0.28v0.79l5,4.99L20.49,19l-4.99,-5zM9.5,14C7.01,14 5,11.99 5,9.5S7.01,5 9.5,5 14,7.01 14,9.5 11.99,14 9.5,14z"/>
9+
</vector>

sheetselection/src/main/res/layout/dialog_sheet_selection.xml

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
33
xmlns:app="http://schemas.android.com/apk/res-auto"
44
xmlns:tools="http://schemas.android.com/tools"
5+
android:id="@+id/rootLayout"
56
android:layout_width="match_parent"
67
android:layout_height="wrap_content"
78
android:orientation="vertical"
@@ -15,12 +16,44 @@
1516
android:visibility="gone"
1617
tools:visibility="visible" />
1718

18-
<TextView
19-
android:id="@+id/textViewTitle"
20-
style="?attr/sheetSelection_titleStyle"
19+
<ViewSwitcher
20+
android:id="@+id/viewSwitcherHeader"
2121
android:layout_width="match_parent"
2222
android:layout_height="wrap_content"
23-
tools:text="@tools:sample/lorem" />
23+
android:measureAllChildren="false">
24+
25+
<LinearLayout
26+
android:layout_width="match_parent"
27+
android:layout_height="wrap_content"
28+
android:orientation="horizontal">
29+
30+
<TextView
31+
android:id="@+id/textViewTitle"
32+
style="?attr/sheetSelection_titleStyle"
33+
android:layout_width="0dp"
34+
android:layout_height="wrap_content"
35+
android:layout_weight="1"
36+
tools:text="@tools:sample/lorem" />
37+
38+
<androidx.appcompat.widget.AppCompatImageButton
39+
android:id="@+id/buttonSearch"
40+
android:layout_width="wrap_content"
41+
android:layout_height="wrap_content"
42+
android:layout_gravity="center_vertical"
43+
android:layout_marginEnd="8dp"
44+
android:src="@drawable/ic_search"
45+
android:visibility="gone"
46+
app:backgroundTint="?attr/colorSurface"
47+
tools:visibility="visible" />
48+
</LinearLayout>
49+
50+
<androidx.appcompat.widget.SearchView
51+
android:id="@+id/searchView"
52+
android:layout_width="match_parent"
53+
android:layout_height="wrap_content"
54+
app:queryBackground="@null"
55+
app:submitBackground="@null" />
56+
</ViewSwitcher>
2457

2558
<androidx.recyclerview.widget.RecyclerView
2659
android:id="@+id/recyclerViewSelectionItems"

0 commit comments

Comments
 (0)