Skip to content

Commit

Permalink
Merge pull request #81 from Trendyol/dialogs/infolist
Browse files Browse the repository at this point in the history
Dialogs - Info List
  • Loading branch information
bsobe authored Nov 2, 2021
2 parents bef46f3 + 4290819 commit 8b2670d
Show file tree
Hide file tree
Showing 21 changed files with 446 additions and 68 deletions.
Binary file added images/dialogs-5.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
26 changes: 25 additions & 1 deletion libraries/dialogs/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

<img src="https://raw.githubusercontent.com/Trendyol/android-ui-components/master/images/dialogs-1.png" width="240"/> <img src="https://raw.githubusercontent.com/Trendyol/android-ui-components/master/images/dialogs-2.png" width="240"/> <img src="https://raw.githubusercontent.com/Trendyol/android-ui-components/master/images/dialogs-3.png" width="240"/> <img src="https://raw.githubusercontent.com/Trendyol/android-ui-components/master/images/dialogs-4.png" width="240"/>
<img src="https://raw.githubusercontent.com/Trendyol/android-ui-components/master/images/dialogs-1.png" width="280"/> <img src="https://raw.githubusercontent.com/Trendyol/android-ui-components/master/images/dialogs-2.png" width="280"/> <img src="https://raw.githubusercontent.com/Trendyol/android-ui-components/master/images/dialogs-3.png" width="280"/> <img src="https://raw.githubusercontent.com/Trendyol/android-ui-components/master/images/dialogs-4.png" width="280"/> <img src="https://raw.githubusercontent.com/Trendyol/android-ui-components/master/images/dialogs-5.png" width="280"/>

$dialogsVersion = dialogs-1.2.4 [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)

Expand Down Expand Up @@ -137,6 +137,30 @@ selectionDialog {
}
```

* Info List Dialog:

Dialog with the list. There are two textViews that are showing key-value pairs.
All **Info Dialog** arguments plus these arguments will be applicable to show info list dialogs.

| Field | Type | Description | Default Value |
| ------------- |-------------|-------------| ------------- |
| `infoListItems` | List<Pair<CharSequence, CharSequence>> | Item list that will be listed on dialog. | null |
| `itemDividers` | List<ItemDivider> | Wrapper that will decorate recyclerView | emptyList |

Sample usage:
```kotlin
infoListDialog {
title = "Info List Dialog Sample"
showCloseButton = true
closeButtonListener = infoDialogClosed
infoListItems = getInfoListItems()
itemDividers = listOf(
ItemDivider.MarginDivider(56, listOf(ItemDivider.MarginDivider.MarginDirection.TOP, ItemDivider.MarginDivider.MarginDirection.BOTTOM)),
ItemDivider.DrawableDivider(R.drawable.shape_info_list_dialog_divider)
)
}
```

## TODOs
* Implement ListDialog.
* ~~Implement SelectionDialog~~
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,3 +115,28 @@ class SelectionDialogBuilder internal constructor() : InfoDialogBuilder() {

}
}

class InfoListDialogBuilder internal constructor() : InfoDialogBuilder() {

var infoListItems: List<Pair<CharSequence, CharSequence>> = emptyList()
var itemDividers: List<ItemDivider> = emptyList()

internal fun buildInfoListDialog(block: InfoListDialogBuilder.() -> Unit): DialogFragment =
InfoListDialogBuilder().apply(block).let {
DialogFragment().apply {
arguments = DialogFragmentArguments(
title = it.title,
showCloseButton = it.showCloseButton,
content = SpannableString(it.content),
animateCornerRadiusWhenExpand = it.animateCornerRadiusWhenExpand,
showContentAsHtml = it.showContentAsHtml,
contentImage = it.contentImage,
webViewContent = it.webViewContent,
infoListItems = it.infoListItems,
itemDividers = it.itemDividers
).toBundle()
closeButtonListener = it.closeButtonListener
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ package com.trendyol.uicomponents.dialogs
fun infoDialog(block: InfoDialogBuilder.() -> Unit): DialogFragment =
InfoDialogBuilder().buildInfoDialog(block)

fun infoListDialog(block: InfoListDialogBuilder.() -> Unit): DialogFragment =
InfoListDialogBuilder().buildInfoListDialog(block)

fun agreementDialog(block: AgreementDialogBuilder.() -> Unit): DialogFragment =
AgreementDialogBuilder().buildAgreementDialog(block)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,8 @@ import android.text.SpannableString
import android.text.method.LinkMovementMethod
import android.text.util.Linkify
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.view.ViewGroup.FOCUS_AFTER_DESCENDANTS
import android.view.ViewGroup.FOCUS_DOWN
import android.view.ViewOutlineProvider
import android.webkit.WebChromeClient
import android.webkit.WebViewClient
Expand All @@ -20,8 +17,10 @@ import androidx.lifecycle.ViewModelProviders
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.trendyol.dialog.R
import com.trendyol.dialog.databinding.FragmentDialogBinding
import com.trendyol.uicomponents.dialogs.list.ItemDecorator
import com.trendyol.uicomponents.dialogs.list.DialogListAdapter
import com.trendyol.uicomponents.dialogs.list.DialogListViewModel
import com.trendyol.uicomponents.dialogs.list.info.DialogInfoListAdapter

class DialogFragment internal constructor() : BaseBottomSheetDialog() {

Expand All @@ -43,6 +42,9 @@ class DialogFragment internal constructor() : BaseBottomSheetDialog() {
dialogArguments.showRadioButton
)
}

private val infoListAdapter by lazy(LazyThreadSafetyMode.NONE) { DialogInfoListAdapter() }

private val dialogListViewModel by lazy {
ViewModelProviders.of(this)[DialogListViewModel::class.java]
}
Expand All @@ -57,7 +59,7 @@ class DialogFragment internal constructor() : BaseBottomSheetDialog() {
animateCornerRadiusWithStateChanged()
} else {
binding.cardView.outlineProvider =
BottomSheetOutlineProvider(radius = requireContext().pixel(R.dimen.dialogs_corner_radius))
BottomSheetOutlineProvider(radius = requireContext().pixel(R.dimen.ui_components_dialogs_corner_radius))
}

with(binding) {
Expand All @@ -77,37 +79,57 @@ class DialogFragment internal constructor() : BaseBottomSheetDialog() {
textContent.movementMethod = LinkMovementMethod.getInstance()

dialogArguments.items?.let { items ->
initializeRecyclerView()
editTextSearch.setOnFocusChangeListener { _, hasFocus ->
if (hasFocus) {
setBottomSheetState(BottomSheetBehavior.STATE_EXPANDED)
} else {
editTextSearch.hideKeyboard()
}
}
initializeSelectionDialog(items)
}
dialogArguments.infoListItems?.let { items ->
initializeInfoListDialog(items, dialogArguments.itemDividers)
}
}
}

editTextSearch.doAfterTextChanged {
dialogListViewModel.search(it.toString())
private fun initializeSelectionDialog(items: List<Pair<Boolean, CharSequence>>) {
with(binding) {
with(recyclerViewItems) {
adapter = itemsAdapter.apply {
onItemSelectedListener =
{ position -> dialogListViewModel.onSelectionChanged(position) }
onItemReselectedListener =
{ position -> dialogListViewModel.onReselection(position) }
}

imageClearSearchQuery.setOnClickListener {
editTextSearch.text?.clear()
dialogListViewModel.clearSearch()
isNestedScrollingEnabled = false
}
editTextSearch.setOnFocusChangeListener { _, hasFocus ->
if (hasFocus) {
setBottomSheetState(BottomSheetBehavior.STATE_EXPANDED)
} else {
editTextSearch.hideKeyboard()
}
}

setUpViewModel(items)
editTextSearch.doAfterTextChanged {
dialogListViewModel.search(it.toString())
}

imageClearSearchQuery.setOnClickListener {
editTextSearch.text?.clear()
dialogListViewModel.clearSearch()
}
}
setUpViewModel(items)
}

private fun initializeRecyclerView() = with(binding.recyclerViewItems) {
adapter = itemsAdapter.apply {
onItemSelectedListener =
{ position -> dialogListViewModel.onSelectionChanged(position) }
onItemReselectedListener =
{ position -> dialogListViewModel.onReselection(position) }
private fun initializeInfoListDialog(
items: List<Pair<CharSequence, CharSequence>>,
itemDividers: List<ItemDivider>
) {
with(binding.recyclerViewItems) {
infoListAdapter.setItems(items)
itemDividers.forEach {
addItemDecoration(ItemDecorator(it))
}
adapter = infoListAdapter
isNestedScrollingEnabled = false
}
isNestedScrollingEnabled = false
}

override fun setViewState() {
Expand All @@ -119,7 +141,7 @@ class DialogFragment internal constructor() : BaseBottomSheetDialog() {
contentImage = dialogArguments.contentImage,
leftButtonText = dialogArguments.leftButtonText,
rightButtonText = dialogArguments.rightButtonText,
isListVisible = dialogArguments.items?.isNotEmpty() == true,
isListVisible = dialogArguments.items?.isNotEmpty() == true || dialogArguments.infoListItems?.isNotEmpty() == true,
isSearchEnabled = dialogArguments.enableSearch,
isClearSearchButtonVisible = dialogArguments.showClearSearchButton,
searchHint = dialogArguments.searchHint,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ class DialogFragmentArguments(
val titleTextPosition: TextPosition? = null,
val contentTextPosition: TextPosition? = null,
val webViewContent: WebViewContent? = null,
val webViewBuilder: (WebView.() -> Unit)? = null
val webViewBuilder: (WebView.() -> Unit)? = null,
val infoListItems: List<Pair<CharSequence, CharSequence>>? = null,
val itemDividers: List<ItemDivider> = emptyList()
) : Parcelable {

fun toBundle() = bundleOf("ARGUMENTS" to this)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ internal fun <T> LiveData<T>.observeNonNull(owner: LifecycleOwner, onNotNull: (T
}

internal fun DialogFragment.animateCornerRadiusWithStateChanged() {
val roundedCardRadius = requireContext().pixel(R.dimen.dialogs_corner_radius)
val roundedCardRadius = requireContext().pixel(R.dimen.ui_components_dialogs_corner_radius)
val expandAnimator =
ValueAnimator.ofFloat(roundedCardRadius, 0.0f)
.apply {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
package com.trendyol.uicomponents.dialogs

import android.graphics.Canvas
import android.graphics.Rect
import android.graphics.drawable.Drawable
import android.os.Parcelable
import android.view.View
import androidx.annotation.DrawableRes
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
import kotlinx.parcelize.IgnoredOnParcel
import kotlinx.parcelize.Parcelize
import kotlin.math.roundToInt

sealed class ItemDivider : Parcelable {

internal open fun decorate(
outRect: Rect,
view: View,
recyclerView: RecyclerView,
state: RecyclerView.State
) {
}

internal open fun onDraw(
canvas: Canvas,
recyclerView: RecyclerView,
state: RecyclerView.State
) {
}

@Parcelize
class MarginDivider(
private val marginSize: Int,
private val marginDirections: List<MarginDirection> = listOf(
MarginDirection.START,
MarginDirection.TOP,
MarginDirection.END,
MarginDirection.BOTTOM,
),
private val shouldAddInitialTopMargin: Boolean = false,
) : ItemDivider() {

override fun decorate(
outRect: Rect,
view: View,
recyclerView: RecyclerView,
state: RecyclerView.State
) {
if (shouldAddInitialTopMargin) {
val adapterPosition = recyclerView.getChildAdapterPosition(view)
if (adapterPosition == 0) {
outRect.top = marginSize
}
}
marginDirections.forEach {
when (it) {
MarginDirection.START -> {
outRect.left = marginSize
}
MarginDirection.TOP -> {
outRect.top = marginSize
}
MarginDirection.END -> {
outRect.right = marginSize
}
MarginDirection.BOTTOM -> {
outRect.bottom = marginSize
}
}
}
}

enum class MarginDirection {
START, END, TOP, BOTTOM;
}
}

@Parcelize
class DrawableDivider(
@DrawableRes private val drawableResource: Int
) : ItemDivider() {

@IgnoredOnParcel
private var drawable: Drawable? = null

@IgnoredOnParcel
private val mBounds = Rect()

override fun decorate(
outRect: Rect,
view: View,
recyclerView: RecyclerView,
state: RecyclerView.State,
) {
if (drawable == null) {
drawable = ContextCompat.getDrawable(recyclerView.context, drawableResource)
}
outRect.set(0, 0, 0, drawable?.intrinsicHeight ?: 0)
}

override fun onDraw(
canvas: Canvas,
recyclerView: RecyclerView,
state: RecyclerView.State
) {
val drawable = drawable ?: return
canvas.save()
val left: Int
val right: Int
//noinspection AndroidLintNewApi - NewApi lint fails to handle overrides.
if (recyclerView.clipToPadding) {
left = recyclerView.paddingLeft
right = recyclerView.width - recyclerView.paddingRight
canvas.clipRect(left, recyclerView.paddingTop, right, recyclerView.height - recyclerView.paddingBottom)
} else {
left = 0
right = recyclerView.width
}

val childCount = recyclerView.childCount
for (position in 0 until childCount) {
val child = recyclerView.getChildAt(position)
recyclerView.getDecoratedBoundsWithMargins(child, mBounds)
val bottom = mBounds.bottom + child.translationY.roundToInt()
val top = bottom - drawable.intrinsicHeight
drawable.setBounds(left, top, right, bottom)
drawable.draw(canvas)
}
canvas.restore()
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.trendyol.dialog.databinding.ItemListBinding
import com.trendyol.dialog.databinding.ItemUiComponentsSelectionDialogBinding

internal class DialogListAdapter(
private val showItemsAsHtml: Boolean,
Expand All @@ -25,10 +25,10 @@ internal class DialogListAdapter(
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder =
ItemViewHolder(ItemListBinding.inflate(LayoutInflater.from(parent.context), parent, false))
ItemViewHolder(ItemUiComponentsSelectionDialogBinding.inflate(LayoutInflater.from(parent.context), parent, false))

inner class ItemViewHolder(
private val binding: ItemListBinding
private val binding: ItemUiComponentsSelectionDialogBinding
) : RecyclerView.ViewHolder(binding.root) {

init {
Expand Down
Loading

0 comments on commit 8b2670d

Please sign in to comment.