Skip to content

Commit

Permalink
Add header info section to OptionsSheet #109
Browse files Browse the repository at this point in the history
  • Loading branch information
maxkeppeler committed May 9, 2022
1 parent 900ebf8 commit 5db9f76
Show file tree
Hide file tree
Showing 4 changed files with 248 additions and 21 deletions.
121 changes: 121 additions & 0 deletions options/src/main/java/com/maxkeppeler/sheets/options/Info.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/*
* Copyright (C) 2020. Maximilian Keppeler (https://www.maxkeppeler.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

@file:Suppress("unused")

package com.maxkeppeler.sheets.options

import android.graphics.drawable.Drawable
import androidx.annotation.ColorInt
import androidx.annotation.ColorRes
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes

/**
* A info section that is displayed above all options.
*/
class Info internal constructor() {

@ColorInt
internal var drawableColor: Int? = null
private set

@ColorRes
internal var drawableColorRes: Int? = null
private set

internal var drawable: Drawable? = null
private set

@DrawableRes
internal var drawableRes: Int? = null
private set

internal var contentText: CharSequence? = null
private set

@StringRes
internal var contentTextRes: Int? = null
private set

constructor(
@StringRes contentRes: Int? = null,
drawable: Drawable? = null,
@ColorInt drawableColor: Int? = null,
) : this() {
this.contentTextRes = contentRes
this.drawable = drawable
this.drawableColor = drawableColor
}

constructor(
@StringRes contentRes: Int? = null,
@DrawableRes drawableRes: Int? = null,
@ColorInt drawableColor: Int? = null,
) : this() {
this.contentTextRes = contentRes
this.drawableRes = drawableRes
this.drawableColor = drawableColor
}

constructor(
@StringRes contentRes: Int? = null,
) : this() {
this.contentTextRes = contentRes
}

constructor(
content: CharSequence? = null,
) : this() {
this.contentText = content
}

constructor(
content: CharSequence? = null,
@DrawableRes drawableRes: Int? = null,
@ColorRes drawableColorRes: Int? = null,
) : this() {
this.contentText = content
this.drawableRes = drawableRes
this.drawableColorRes = drawableColorRes
}

constructor(
content: CharSequence? = null,
drawable: Drawable? = null,
@ColorRes drawableColorRes: Int? = null,
) : this() {
this.contentText = content
this.drawable = drawable
this.drawableColorRes = drawableColorRes
}

constructor(
content: CharSequence? = null,
@StringRes contentRes: Int? = null,
drawable: Drawable? = null,
@DrawableRes drawableRes: Int? = null,
@ColorInt drawableColor: Int? = null,
@ColorRes drawableColorRes: Int? = null,
) : this() {
this.drawableColor = drawableColor
this.drawableColorRes = drawableColorRes
this.drawable = drawable
this.drawableRes = drawableRes
this.contentText = content
this.contentTextRes = contentRes
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,12 @@ import androidx.recyclerview.widget.RecyclerView
import com.maxkeppeler.sheets.core.utils.*
import com.maxkeppeler.sheets.core.views.SheetsContent
import com.maxkeppeler.sheets.options.databinding.SheetsOptionsGridItemBinding
import com.maxkeppeler.sheets.options.databinding.SheetsOptionsInfoItemBinding
import com.maxkeppeler.sheets.options.databinding.SheetsOptionsListItemBinding

internal class OptionsAdapter(
private val ctx: Context,
private val info: Info?,
private val options: MutableList<Option>,
private val globalPreventIconTint: Boolean?,
private val type: DisplayMode,
Expand All @@ -49,6 +51,8 @@ internal class OptionsAdapter(
private const val TAG_DISABLED_SELECTED = "tag_disabled_selected"
private const val SELECTOR_STATE_DISABLED_INDEX = 0
private const val SELECTOR_STATE_SELECTED_INDEX = 1
private const val VIEW_TYPE_HEADER_INFO = 0
private const val VIEW_TYPE_AUTO = 1
}

private val selectedOptions =
Expand Down Expand Up @@ -78,9 +82,21 @@ internal class OptionsAdapter(
colorOfAttr(ctx, R.attr.sheetsOptionDisabledBackgroundColor).takeUnlessNotResolved()
?: colorOf(ctx, R.color.sheetsOptionDisabledColor)

override fun getItemViewType(position: Int): Int =
if (position == 0 && info != null) VIEW_TYPE_HEADER_INFO else VIEW_TYPE_AUTO

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder =
when (type) {
DisplayMode.GRID_HORIZONTAL, DisplayMode.GRID_VERTICAL -> {
if (viewType == VIEW_TYPE_HEADER_INFO) {
InfoItem(
SheetsOptionsInfoItemBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
)
} else when (type) {
DisplayMode.GRID_HORIZONTAL,
DisplayMode.GRID_VERTICAL -> {
GridItem(
SheetsOptionsGridItemBinding.inflate(
LayoutInflater.from(parent.context),
Expand All @@ -101,9 +117,23 @@ internal class OptionsAdapter(
}

override fun onBindViewHolder(holder: RecyclerView.ViewHolder, i: Int) {
val actualIndex = i.takeUnless { info != null } ?: i - 1
when (holder) {
is GridItem -> holder.binding.buildGridItem(i)
is ListItem -> holder.binding.buildListItem(i)
is InfoItem -> holder.binding.buildHeaderItem()
is GridItem -> holder.binding.buildGridItem(actualIndex)
is ListItem -> holder.binding.buildListItem(actualIndex)
}
}

private fun SheetsOptionsInfoItemBinding.buildHeaderItem() {
info?.contentText?.let { content.text = it }
if (info?.drawableRes != null || info?.drawable != null) {
val infoIconDrawable = info.drawable ?: info.drawableRes?.let {
ContextCompat.getDrawable(ctx, it)
}
icon.setImageDrawable(infoIconDrawable)
icon.setColorFilter(info.drawableColor ?: getIconColor(ctx))
icon.visibility = View.VISIBLE
}
}

Expand Down Expand Up @@ -244,8 +274,10 @@ internal class OptionsAdapter(
?: textColor

val subtitleColor = defaultSubtitleColor ?: defaultSubtitleColorRes?.let {
ContextCompat.getColor(ctx,
it)
ContextCompat.getColor(
ctx,
it
)
} ?: textColor

val preventIconTint = option.preventIconTint ?: globalPreventIconTint
Expand Down Expand Up @@ -298,11 +330,13 @@ internal class OptionsAdapter(
if (selectedOptions.contains(index)) {
listener.deselectMultipleChoice(index)
selectedOptions[index]?.let {
showDeselected(index,
showDeselected(
index,
it.second,
it.third,
it.first,
root)
root
)
}
selectedOptions.remove(index)
} else {
Expand All @@ -312,11 +346,13 @@ internal class OptionsAdapter(
}
} else {
selectedOptions.forEach { option ->
showDeselected(option.key,
showDeselected(
option.key,
option.value.second,
option.value.third,
option.value.first,
root)
root
)
}
selectedOptions.clear()
selectedOptions[index] = Triple(icon, title, subtitle)
Expand All @@ -325,7 +361,10 @@ internal class OptionsAdapter(
}
}

override fun getItemCount(): Int = options.size
override fun getItemCount(): Int = options.size.plus(if (info != null) 1 else 0)

inner class InfoItem(val binding: SheetsOptionsInfoItemBinding) :
RecyclerView.ViewHolder(binding.root)

inner class GridItem(val binding: SheetsOptionsGridItemBinding) :
RecyclerView.ViewHolder(binding.root)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ import android.text.style.AbsoluteSizeSpan
import android.view.LayoutInflater
import android.view.Menu
import android.view.View
import androidx.annotation.DrawableRes
import androidx.annotation.*
import androidx.annotation.IntRange
import androidx.annotation.StringRes
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.maxkeppeler.sheets.core.Sheet
import com.maxkeppeler.sheets.core.layoutmanagers.CustomGridLayoutManager
Expand All @@ -56,6 +56,7 @@ class OptionsSheet : Sheet() {
private const val SMALL_GRID_ITEMS_MIN = 2
private const val SMALL_GRID_ITEMS_MAX = 8
private const val GRID_COLUMNS_MAX_DEFAULT = 4
private const val DEFAULT_COLUMN_SPAN = 1
}

private lateinit var binding: SheetsOptionsBinding
Expand All @@ -69,6 +70,7 @@ class OptionsSheet : Sheet() {
private var optionsSelected = mutableListOf<Int>()

private var mode = DisplayMode.GRID_HORIZONTAL
private var info: Info? = null
private var multipleChoices = false
private var displayMultipleChoicesInfo = false
private var minChoices: Int? = null
Expand All @@ -87,6 +89,11 @@ class OptionsSheet : Sheet() {
return validMultipleChoice || validSingleChoice
}

/** Set an info section above the options. */
fun withInfo(info: Info) {
this.info = info
}

/** Set the nax amount of columns in [DisplayMode.GRID_VERTICAL] and [DisplayMode.GRID_HORIZONTAL]. */
fun columns(@IntRange(from = 2, to = 8) columns: Int) {
this.gridColumns = columns
Expand Down Expand Up @@ -362,7 +369,6 @@ class OptionsSheet : Sheet() {
checkSetup()
displayButtonsView(multipleChoices || displayButtons)
setButtonPositiveListener(::save)

colorActive = getPrimaryColor(requireContext())

with(binding.optionsRecyclerView) {
Expand All @@ -377,7 +383,8 @@ class OptionsSheet : Sheet() {

optionsAdapter =
OptionsAdapter(
requireActivity(),
requireContext(),
info,
options,
preventIconTint,
mode,
Expand All @@ -389,21 +396,23 @@ class OptionsSheet : Sheet() {

setItemViewCacheSize(options.size)

val spanLookUp = object : GridLayoutManager.SpanSizeLookup() {
override fun getSpanSize(position: Int): Int {
return if (position == 0 && info != null) columns else DEFAULT_COLUMN_SPAN
}
}
layoutManager = when (mode) {

DisplayMode.GRID_HORIZONTAL -> if (collapsedItems) CustomGridLayoutManager(
requireContext(),
columns,
false
)
).apply { this.spanSizeLookup = spanLookUp }
else CustomLinearLayoutManager(requireContext(), true, RecyclerView.HORIZONTAL)

DisplayMode.GRID_VERTICAL -> CustomGridLayoutManager(
requireContext(),
columns,
true
)

).apply { this.spanSizeLookup = spanLookUp }
DisplayMode.LIST -> CustomLinearLayoutManager(requireContext(), true)
}
}
Expand Down Expand Up @@ -516,7 +525,13 @@ class OptionsSheet : Sheet() {
binding.status.selectionLabel.setTextColor(colorActive)
val textSizeSmall = resources.getDimensionPixelSize(R.dimen.sheetsTextSizeBody)
val textSpan =
SpannableString(getString(R.string.sheets_current_of_total, selected, actualMaximum)).apply {
SpannableString(
getString(
R.string.sheets_current_of_total,
selected,
actualMaximum
)
).apply {
setSpan(
AbsoluteSizeSpan(textSizeSmall), selected.toString().length, this.length,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
Expand Down
Loading

0 comments on commit 5db9f76

Please sign in to comment.