diff --git a/README.md b/README.md index 26355aa..73f8692 100644 --- a/README.md +++ b/README.md @@ -17,12 +17,12 @@ repositories { Add the dependency ``` groovy dependencies { - implementation 'com.github.minibugdev:sheetselection:0.0.1' + implementation 'com.github.minibugdev:sheetselection:0.0.2' } ``` ## How to use -![Sheet Selection](screenshot/ss_1.png) +![Sheet Selection](screenshot/ss_1_0.0.2.png) ``` kotlin val items = listOf( @@ -37,6 +37,7 @@ SheetSelection.Builder(context) .items(items) .selectedPosition(2) .showDraggedIndicator(true) + .searchEnabled(true) .onItemClickListener { item, position -> // DO SOMETHING } @@ -47,6 +48,7 @@ SheetSelection.Builder(context) - Set items by `Builder.items(List)`. - Set selected item by `Builder.selectedPosition(Int)`. default is `SheetSelection.NO_SELECT` - Show dragged indicator by `Builder.showDraggedIndicator(Boolean)`. default is `false` +- Set search enabled by `Builder.searchEnabled(Boolean)`. default is `false` - Set custom theme by `Builder.theme(@StyleRes)`. - To handle the item click listener by `Builder.onItemClickListener()`. diff --git a/app/src/main/java/com/minibugdev/sheetselection/demo/MainActivity.kt b/app/src/main/java/com/minibugdev/sheetselection/demo/MainActivity.kt index b1e21b7..5dee714 100644 --- a/app/src/main/java/com/minibugdev/sheetselection/demo/MainActivity.kt +++ b/app/src/main/java/com/minibugdev/sheetselection/demo/MainActivity.kt @@ -17,7 +17,9 @@ class MainActivity : AppCompatActivity() { SheetSelectionItem("1", "Item #1", R.drawable.ic_extension), SheetSelectionItem("2", "Item #2", R.drawable.ic_nature), SheetSelectionItem("3", "Item #3", R.drawable.ic_fingerprint), - SheetSelectionItem("4", "Item #4", R.drawable.ic_face) + SheetSelectionItem("4", "Item #4", R.drawable.ic_face), + SheetSelectionItem("5", "Item #5", R.drawable.ic_extension), + SheetSelectionItem("6", "Item #6", R.drawable.ic_fingerprint) ) SheetSelection.Builder(this) @@ -25,6 +27,7 @@ class MainActivity : AppCompatActivity() { .items(items) .selectedPosition(2) .showDraggedIndicator(true) + .searchEnabled(true) .onItemClickListener { item, position -> textview.text = "You selected `${item.value}`, At position [$position]." } @@ -46,6 +49,7 @@ class MainActivity : AppCompatActivity() { ) .selectedPosition(2) .showDraggedIndicator(true) + .searchEnabled(true) .theme(R.style.Theme_Custom_SheetSelection) .onItemClickListener { item, position -> textview.text = "You selected `${item.value}`, At position [$position]." diff --git a/screenshot/ss_1.png b/screenshot/ss_1.png deleted file mode 100644 index 4c9b194..0000000 Binary files a/screenshot/ss_1.png and /dev/null differ diff --git a/screenshot/ss_1_0.0.2.png b/screenshot/ss_1_0.0.2.png new file mode 100644 index 0000000..9a91057 Binary files /dev/null and b/screenshot/ss_1_0.0.2.png differ diff --git a/sheetselection/build.gradle b/sheetselection/build.gradle index f3ba0a2..86eb736 100644 --- a/sheetselection/build.gradle +++ b/sheetselection/build.gradle @@ -13,7 +13,7 @@ android { minSdkVersion 17 targetSdkVersion 29 versionCode 1 - versionName "0.0.1" + versionName "0.0.2" } buildTypes { diff --git a/sheetselection/src/main/java/com/minibugdev/sheetselection/SheetSelection.kt b/sheetselection/src/main/java/com/minibugdev/sheetselection/SheetSelection.kt index 6aeb3cf..9a0c638 100644 --- a/sheetselection/src/main/java/com/minibugdev/sheetselection/SheetSelection.kt +++ b/sheetselection/src/main/java/com/minibugdev/sheetselection/SheetSelection.kt @@ -6,9 +6,12 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.annotation.StyleRes +import androidx.appcompat.widget.SearchView import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentActivity import androidx.fragment.app.FragmentManager +import com.google.android.material.bottomsheet.BottomSheetBehavior +import com.google.android.material.bottomsheet.BottomSheetDialog import com.google.android.material.bottomsheet.BottomSheetDialogFragment import kotlinx.android.synthetic.main.dialog_sheet_selection.* @@ -16,6 +19,24 @@ class SheetSelection private constructor() : BottomSheetDialogFragment() { var onItemClickListener: OnItemSelectedListener? = null + private val adapter by lazy { + SheetSelectionAdapter( + source = arguments?.getParcelableArrayList(ARGS_ITEMS) ?: emptyList(), + selectedPosition = arguments?.getInt(ARGS_SELECTED_POSITION, NO_SELECT) ?: NO_SELECT, + onItemSelectedListener = onItemSelectedListener + ) + } + + private val screenHeight by lazy { + val statusBarHeight = try { + val resourceId = resources.getIdentifier("status_bar_height", "dimen", "android") + resources.getDimensionPixelSize(resourceId) + } catch (e: Exception) { + 0 + } + resources.displayMetrics.heightPixels - statusBarHeight + } + override fun getTheme(): Int = arguments?.getInt(ARGS_THEME) ?: super.getTheme() override fun onCreateView( @@ -36,23 +57,61 @@ class SheetSelection private constructor() : BottomSheetDialogFragment() { val title = args.getString(ARGS_TITLE) if (title.isNullOrEmpty()) { textViewTitle.visibility = View.GONE + textViewTitle.text = null } else { + textViewTitle.visibility = View.VISIBLE textViewTitle.text = title } - recyclerViewSelectionItems.adapter = SheetSelectionAdapter( - items = args.getParcelableArrayList(ARGS_ITEMS) ?: emptyList(), - selectedPosition = args.getInt(ARGS_SELECTED_POSITION, NO_SELECT), - onItemSelectedListener = internalOnItemSelectedListener - ) + if (args.getBoolean(ARGS_SEARCH_ENABLED)) { + buttonSearch.visibility = View.VISIBLE + buttonSearch.setOnClickListener(onSearchClickListener) + searchView.setOnCloseListener(onSearchCloseListener) + searchView.setOnQueryTextListener(onSearchQueryTextListener) + } + + recyclerViewSelectionItems.setHasFixedSize(true) + recyclerViewSelectionItems.adapter = adapter } } - private val internalOnItemSelectedListener: OnItemSelectedListener = { item, position -> + private fun updateSheetHeight(viewHeight: Int) { + rootLayout.layoutParams = rootLayout.layoutParams + .apply { height = viewHeight } + } + + private val onItemSelectedListener: OnItemSelectedListener = { item, position -> dismiss() onItemClickListener?.invoke(item, position) } + private val onSearchClickListener = View.OnClickListener { + (dialog as? BottomSheetDialog)?.run { + behavior.state = BottomSheetBehavior.STATE_EXPANDED + } + updateSheetHeight(screenHeight) + viewSwitcherHeader.displayedChild = 1 + searchView.isIconified = false + } + + private val onSearchCloseListener = SearchView.OnCloseListener { + updateSheetHeight(ViewGroup.LayoutParams.WRAP_CONTENT) + viewSwitcherHeader.displayedChild = 0 + true + } + + private val onSearchQueryTextListener = object : SearchView.OnQueryTextListener { + override fun onQueryTextChange(newText: String?): Boolean { + adapter.search(newText) + return true + } + + override fun onQueryTextSubmit(query: String?): Boolean { + adapter.search(query) + return true + } + } + class Builder(context: Context) { private val manager: FragmentManager? = when (context) { is FragmentActivity -> context.supportFragmentManager @@ -66,6 +125,7 @@ class SheetSelection private constructor() : BottomSheetDialogFragment() { private var items: List = emptyList() private var selectedPosition: Int = NO_SELECT private var showDraggedIndicator: Boolean = false + private var searchEnabled: Boolean = false private var listener: OnItemSelectedListener? = null fun theme(@StyleRes themeId: Int) = apply { @@ -93,6 +153,10 @@ class SheetSelection private constructor() : BottomSheetDialogFragment() { this.showDraggedIndicator = show } + fun searchEnabled(enabled: Boolean) = apply { + this.searchEnabled = enabled + } + fun onItemClickListener(listener: OnItemSelectedListener) = apply { this.listener = listener } @@ -105,6 +169,7 @@ class SheetSelection private constructor() : BottomSheetDialogFragment() { putParcelableArrayList(ARGS_ITEMS, ArrayList(items)) putInt(ARGS_SELECTED_POSITION, selectedPosition) putBoolean(ARGS_SHOW_DRAGGED_INDICATOR, showDraggedIndicator) + putBoolean(ARGS_SEARCH_ENABLED, searchEnabled) } onItemClickListener = listener } @@ -124,5 +189,6 @@ class SheetSelection private constructor() : BottomSheetDialogFragment() { private const val ARGS_ITEMS = "SheetSelection:ARGS_ITEMS" private const val ARGS_SELECTED_POSITION = "SheetSelection:ARGS_SELECTED_POSITION" private const val ARGS_SHOW_DRAGGED_INDICATOR = "SheetSelection:ARGS_SHOW_DRAGGED_INDICATOR" + private const val ARGS_SEARCH_ENABLED = "SheetSelection:ARGS_SEARCH_ENABLED" } } \ No newline at end of file diff --git a/sheetselection/src/main/java/com/minibugdev/sheetselection/SheetSelectionAdapter.kt b/sheetselection/src/main/java/com/minibugdev/sheetselection/SheetSelectionAdapter.kt index 9987b3a..f654519 100644 --- a/sheetselection/src/main/java/com/minibugdev/sheetselection/SheetSelectionAdapter.kt +++ b/sheetselection/src/main/java/com/minibugdev/sheetselection/SheetSelectionAdapter.kt @@ -10,11 +10,13 @@ import kotlinx.android.synthetic.main.row_selection_item.* typealias OnItemSelectedListener = (item: SheetSelectionItem, position: Int) -> Unit class SheetSelectionAdapter( - private val items: List, + private val source: List, private val selectedPosition: Int, private val onItemSelectedListener: OnItemSelectedListener? ) : RecyclerView.Adapter() { + private var items: List = source + override fun getItemCount() = items.size override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { @@ -27,13 +29,31 @@ class SheetSelectionAdapter( override fun onBindViewHolder(holder: ViewHolder, position: Int) { holder.onBindView( - items[position], - position, - position == selectedPosition, - onItemSelectedListener + item = items[position], + position = position, + selected = position == selectedPosition, + onItemSelectedListener = onItemSelectedListener ) } + fun search(keyword: String?) { + if (keyword.isNullOrBlank()) { + updateItems(source) + } else { + val searchResult = source.filter { it.value.contains(keyword, true) } + if (searchResult.isEmpty()) { + updateItems(listOf(SheetSelectionItem("search_not_found", "Search not found."))) + } else { + updateItems(searchResult) + } + } + } + + private fun updateItems(items: List) { + this.items = items + notifyDataSetChanged() + } + class ViewHolder(override val containerView: View) : RecyclerView.ViewHolder(containerView), LayoutContainer { diff --git a/sheetselection/src/main/res/drawable/ic_search.xml b/sheetselection/src/main/res/drawable/ic_search.xml new file mode 100644 index 0000000..affc7ba --- /dev/null +++ b/sheetselection/src/main/res/drawable/ic_search.xml @@ -0,0 +1,9 @@ + + + diff --git a/sheetselection/src/main/res/layout/dialog_sheet_selection.xml b/sheetselection/src/main/res/layout/dialog_sheet_selection.xml index 7c0a147..a0f7829 100644 --- a/sheetselection/src/main/res/layout/dialog_sheet_selection.xml +++ b/sheetselection/src/main/res/layout/dialog_sheet_selection.xml @@ -2,6 +2,7 @@ - + android:measureAllChildren="false"> + + + + + + + + + +