Skip to content

Commit

Permalink
Merge branch 'master' into feature/image-slider
Browse files Browse the repository at this point in the history
  • Loading branch information
farukguler authored Dec 13, 2019
2 parents ba4d57b + 68109db commit 41f6760
Show file tree
Hide file tree
Showing 36 changed files with 803 additions and 130 deletions.
3 changes: 3 additions & 0 deletions .idea/codeStyles/Project.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file modified images/1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified images/2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/dialogs-4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
31 changes: 27 additions & 4 deletions libraries/dialogs/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

<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-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"/>

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

## Dialogs
Dialogs is a bunch of BottomSheetDialogs to use in app to show user an information, agreement or list.
Expand All @@ -24,7 +24,9 @@ dependencies {
You can configure your dialog with given extensions with Kotlin DSL syntax.

To show the dialog you just need to call `showDialog(FragmentManager)` function.


You can call DialogFragment.findFragment(supportFragmentManager) method inorder to retrieve DialogFragment's instance and use that instance to set click listeners after configuration change.

* Info Dialog:

Simple dialog to show information, error or text.
Expand Down Expand Up @@ -89,6 +91,9 @@ All **Info Dialog** arguments plus these arguments will be applicable to show se
| `items` | List<Pair<Boolean, String>> | Item list that will be listed on dialog. | null |
| `showItemsAsHtml` | Boolean | Item texts will be parsed as Html if this flag setted as true. | false |
| `onItemSelectedListener` | (DialogFragment, Int) -> Unit | Listener to notify selected index. | null |
| `enableSearch` | Boolean | Enables search function in given `items` | false |
| `showClearSearchButton` | Boolean | Shows clean button on the right of the search input line. | false |
| `searchHint` | String | Hint to show on search input line. | "" |

Sample usage:
```kotlin
Expand All @@ -104,13 +109,31 @@ selectionDialog {
}
```

Sample usage with search:
```kotlin
selectionDialog {
title = "Selection Dialog with Search Title"
content = getContent()
items = getItemsAsHtml()
showItemsAsHtml = true
onItemSelectedListener = { dialog, index ->
onItemSelected(index)
}
enableSearch = true
showClearSearchButton = true
searchHint = "Hint for search"
}
```

## TODOs
* Implement ListDialog.
* ~~Implement SelectionDialog~~
* Implement search line.
* ~~Implement search line.~
* Implement multiple selectable type.
* Provide theme for more styling.
* Update builder for Java.
* ~~Stop using DialogFragment's constructor inorder to build DialogFragment~~


## Contributors
This library is maintained mainly by Trendyol Android Team members but also other Android lovers contributes.
Expand Down
9 changes: 8 additions & 1 deletion libraries/dialogs/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ apply plugin: 'kotlin-kapt'
apply plugin: 'com.github.dcendents.android-maven'

group="com.trendyol.ui-components"
version="1.0.2"
version="1.0.3"

android {
compileSdkVersion 29
Expand All @@ -31,6 +31,10 @@ android {
dataBinding {
enabled true
}

androidExtensions {
experimental = true
}
}

dependencies {
Expand All @@ -40,4 +44,7 @@ dependencies {
implementation 'androidx.core:core-ktx:1.1.0'
implementation 'com.google.android.material:material:1.0.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'

implementation 'androidx.lifecycle:lifecycle-extensions:2.1.0'
kapt 'androidx.lifecycle:lifecycle-compiler:2.1.0'
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import com.trendyol.dialog.R

abstract class BaseBottomSheetDialog<DB : ViewDataBinding> : BottomSheetDialogFragment() {

protected lateinit var binding: DB
lateinit var binding: DB

@LayoutRes
abstract fun getLayoutResId(): Int
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,3 @@ internal fun AppCompatImageView.setDrawableResource(@DrawableRes drawableResId:
internal fun View.setVisibility(isVisible: Boolean) {
visibility = if (isVisible) View.VISIBLE else View.GONE
}

@BindingAdapter("items")
internal fun RecyclerView.setItems(items: List<Pair<Boolean, CharSequence>>?) {
if (items != null) {
(adapter as? DialogListAdapter)?.setItems(items)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,24 @@ open class InfoDialogBuilder internal constructor() : Builder() {

internal fun buildInfoDialog(block: InfoDialogBuilder.() -> Unit): DialogFragment {
return InfoDialogBuilder().apply(block).let {
DialogFragment(
title = it.title,
showCloseButton = it.showCloseButton,
closeButtonListener = it.closeButtonListener ?: { },
content = SpannableString(it.content),
contentImage = it.contentImage,
showContentAsHtml = it.showContentAsHtml
)
DialogFragment().apply {
arguments = DialogFragmentArguments(
title = it.title,
showCloseButton = it.showCloseButton,
content = SpannableString(it.content),
contentImage = it.contentImage,
showContentAsHtml = it.showContentAsHtml
).toBundle()
this.closeButtonListener = it.closeButtonListener ?: { }
}
}
}
}

class ClickEvent() {

}

open class AgreementDialogBuilder internal constructor() : InfoDialogBuilder() {

var rightButtonText: String = ""
Expand All @@ -40,18 +46,20 @@ open class AgreementDialogBuilder internal constructor() : InfoDialogBuilder() {

internal fun buildAgreementDialog(block: AgreementDialogBuilder.() -> Unit): DialogFragment =
AgreementDialogBuilder().apply(block).let {
DialogFragment(
title = it.title,
showCloseButton = it.showCloseButton,
closeButtonListener = it.closeButtonListener,
content = SpannableString(it.content),
showContentAsHtml = it.showContentAsHtml,
contentImage = it.contentImage,
rightButtonText = it.rightButtonText,
leftButtonText = it.leftButtonText,
rightButtonClickListener = it.rightButtonClickListener,
DialogFragment().apply {
arguments = DialogFragmentArguments(
title = it.title,
showCloseButton = it.showCloseButton,
content = SpannableString(it.content),
showContentAsHtml = it.showContentAsHtml,
contentImage = it.contentImage,
rightButtonText = it.rightButtonText,
leftButtonText = it.leftButtonText
).toBundle()
closeButtonListener = it.closeButtonListener
rightButtonClickListener = it.rightButtonClickListener
leftButtonClickListener = it.leftButtonClickListener
)
}
}
}

Expand All @@ -60,19 +68,28 @@ class SelectionDialogBuilder internal constructor() : InfoDialogBuilder() {
var items: List<Pair<Boolean, CharSequence>> = emptyList()
var showItemsAsHtml: Boolean = false
var onItemSelectedListener: ((DialogFragment, Int) -> Unit)? = null
var enableSearch: Boolean = false
var showClearSearchButton: Boolean = false
var searchHint: String = ""

internal fun buildSelectionDialog(block: SelectionDialogBuilder.() -> Unit): DialogFragment =
SelectionDialogBuilder().apply(block).let {
DialogFragment(
title = it.title,
showCloseButton = it.showCloseButton,
closeButtonListener = it.closeButtonListener,
content = SpannableString(it.content),
showContentAsHtml = it.showContentAsHtml,
contentImage = it.contentImage,
items = it.items,
showItemsAsHtml = it.showItemsAsHtml,
DialogFragment().apply {
arguments = DialogFragmentArguments(
title = it.title,
showCloseButton = it.showCloseButton,
content = SpannableString(it.content),
showContentAsHtml = it.showContentAsHtml,
contentImage = it.contentImage,
items = it.items,
showItemsAsHtml = it.showItemsAsHtml,
enableSearch = it.enableSearch,
showClearSearchButton = it.showClearSearchButton,
searchHint = it.searchHint
).toBundle()
closeButtonListener = it.closeButtonListener
onItemSelectedListener = it.onItemSelectedListener
)
}

}
}
Original file line number Diff line number Diff line change
@@ -1,33 +1,38 @@
package com.trendyol.uicomponents.dialogs

import android.text.SpannableString
import androidx.annotation.DrawableRes
import android.view.ViewGroup.FOCUS_AFTER_DESCENDANTS
import androidx.core.widget.doAfterTextChanged
import androidx.fragment.app.FragmentManager
import androidx.lifecycle.Observer
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.DialogListAdapter
import com.trendyol.uicomponents.dialogs.list.DialogListViewModel

class DialogFragment internal constructor(
private val title: String? = null,
private val showCloseButton: Boolean? = null,
private val closeButtonListener: ((DialogFragment) -> Unit)? = null,
private val content: CharSequence? = null,
private val showContentAsHtml: Boolean = false,
@DrawableRes private val contentImage: Int? = null,
private val leftButtonText: String? = null,
private val rightButtonText: String? = null,
private val leftButtonClickListener: ((DialogFragment) -> Unit)? = null,
private val rightButtonClickListener: ((DialogFragment) -> Unit)? = null,
private val items: List<Pair<Boolean, CharSequence>>? = null,
private val showItemsAsHtml: Boolean = false,
private val onItemSelectedListener: ((DialogFragment, Int) -> Unit)? = null
) : BaseBottomSheetDialog<FragmentDialogBinding>() {

private val itemsAdapter by lazy { DialogListAdapter(showItemsAsHtml) }
class DialogFragment internal constructor() : BaseBottomSheetDialog<FragmentDialogBinding>() {

private val dialogArguments by lazy(LazyThreadSafetyMode.NONE)
{ requireNotNull(DialogFragmentArguments.fromBundle(requireArguments())) }

private val itemsAdapter by lazy(LazyThreadSafetyMode.NONE) { DialogListAdapter(dialogArguments.showItemsAsHtml) }

private val dialogListViewModel by lazy {
ViewModelProviders.of(this)[DialogListViewModel::class.java]
}

var closeButtonListener: ((DialogFragment) -> Unit)? = null
var leftButtonClickListener: ((DialogFragment) -> Unit)? = null
var rightButtonClickListener: ((DialogFragment) -> Unit)? = null
var onItemSelectedListener: ((DialogFragment, Int) -> Unit)? = null

override fun getLayoutResId(): Int = R.layout.fragment_dialog

override fun setUpView() {
animateCornerRadiusWithStateChanged()

with(binding) {
imageClose.setOnClickListener {
dismiss()
Expand All @@ -40,25 +45,51 @@ class DialogFragment internal constructor(
rightButtonClickListener?.invoke(this@DialogFragment)
}

recyclerViewItems.adapter = itemsAdapter
recyclerViewItems.isNestedScrollingEnabled = false
dialogArguments.items?.let { items ->
initializeRecyclerView()
editTextSearch.setOnFocusChangeListener { _, hasFocus ->
if (hasFocus) {
setBottomSheetState(BottomSheetBehavior.STATE_EXPANDED)
}
}

itemsAdapter.onItemSelectedListener = { position ->
onItemSelectedListener?.invoke(this@DialogFragment, position)
editTextSearch.doAfterTextChanged {
dialogListViewModel.search(it.toString())
}

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

constraintLayout.descendantFocusability = FOCUS_AFTER_DESCENDANTS

setUpViewModel(items)
}
}
}

private fun initializeRecyclerView() = with(binding.recyclerViewItems) {
adapter = itemsAdapter.apply {
onItemSelectedListener =
{ position -> dialogListViewModel.onSelectionChanged(position) }
}
isNestedScrollingEnabled = false
}

override fun setViewState() {
val viewState = DialogViewState(
title = title,
showCloseButton = showCloseButton,
content = content ?: SpannableString(""),
showContentAsHtml = showContentAsHtml,
contentImage = contentImage,
leftButtonText = leftButtonText,
rightButtonText = rightButtonText,
listItems = items
title = dialogArguments.title,
showCloseButton = dialogArguments.showCloseButton,
content = dialogArguments.content ?: SpannableString(""),
showContentAsHtml = dialogArguments.showContentAsHtml,
contentImage = dialogArguments.contentImage,
leftButtonText = dialogArguments.leftButtonText,
rightButtonText = dialogArguments.rightButtonText,
isListVisible = dialogArguments.items?.isNotEmpty() == true,
isSearchEnabled = dialogArguments.enableSearch,
isClearSearchButtonVisible = dialogArguments.showClearSearchButton,
searchHint = dialogArguments.searchHint
)

binding.viewState = viewState
Expand All @@ -69,8 +100,24 @@ class DialogFragment internal constructor(
show(fragmentManager, TAG)
}

private fun setUpViewModel(items: List<Pair<Boolean, CharSequence>>) {
with(dialogListViewModel) {
getDialogSearchItemsLiveData().observe(viewLifecycleOwner, Observer { items ->
itemsAdapter.setItems(items)
})
getLastChangedItemLiveData().observeNonNull(viewLifecycleOwner) { position ->
onItemSelectedListener?.invoke(this@DialogFragment, position)
}
setInitialItems(items)
}
}

companion object {

const val TAG: String = "TRENDYOL_BOTTOM_SHEET_DIALOG"

fun findFragment(fragmentManager: FragmentManager): DialogFragment? {
return fragmentManager.findFragmentByTag(TAG) as? DialogFragment
}
}
}
Loading

0 comments on commit 41f6760

Please sign in to comment.