From 85591bc15ad4da2ecebc8c6a394712ab1929918d Mon Sep 17 00:00:00 2001 From: Aurelien Hubert Date: Thu, 21 Feb 2019 11:10:51 +0100 Subject: [PATCH 1/2] Improve BottomSheet & add BottomSheetGrid --- .../pokeranalytics/android/model/LiveData.kt | 136 ++++++++++-------- .../android/model/realm/Session.kt | 4 +- .../ui/adapter/TableSizeGridAdapter.kt | 50 +++++++ .../components/bottomsheet/BottomSheetData.kt | 1 - .../BottomSheetDoubleListFragment.kt | 2 +- .../bottomsheet/BottomSheetFragment.kt | 1 + .../bottomsheet/BottomSheetListFragment.kt | 6 +- .../BottomSheetTableSizeGridFragment.kt | 72 ++++++++++ .../ui/view/GridSpacingItemDecoration.kt | 34 +++++ .../pokeranalytics/android/util/Extensions.kt | 11 ++ .../res/layout/bottom_sheet_double_list.xml | 4 +- app/src/main/res/layout/bottom_sheet_grid.xml | 11 ++ app/src/main/res/layout/bottom_sheet_list.xml | 2 +- .../layout/row_bottom_sheet_grid_title.xml | 26 ++++ 14 files changed, 293 insertions(+), 67 deletions(-) create mode 100644 app/src/main/java/net/pokeranalytics/android/ui/adapter/TableSizeGridAdapter.kt create mode 100644 app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetTableSizeGridFragment.kt create mode 100644 app/src/main/java/net/pokeranalytics/android/ui/view/GridSpacingItemDecoration.kt create mode 100644 app/src/main/res/layout/bottom_sheet_grid.xml create mode 100644 app/src/main/res/layout/row_bottom_sheet_grid_title.xml diff --git a/app/src/main/java/net/pokeranalytics/android/model/LiveData.kt b/app/src/main/java/net/pokeranalytics/android/model/LiveData.kt index f4cc0770..d35a3755 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/LiveData.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/LiveData.kt @@ -12,82 +12,102 @@ import net.pokeranalytics.android.ui.view.Localizable * An interface to easily handle the validity of any object we want to save */ interface ObjectSavable { - fun isValidForSave(): Boolean { return true } + fun isValidForSave(): Boolean { + return true + } } /** * An enum managing the business objects related to a realm results */ enum class LiveData : Localizable { - BANKROLL, - GAME, - LOCATION, - TOURNAMENT_FEATURE, - TRANSACTION_TYPE; + BANKROLL, + GAME, + LOCATION, + TOURNAMENT_FEATURE, + TRANSACTION_TYPE; - fun items(realm: Realm, fieldName: String? = null, sortOrder: Sort? = null): RealmResults<*> { - return realm.where(this.relatedEntity).findAll().sort(fieldName?:this.sortingFieldName, sortOrder?:this.sorting) - } + fun items(realm: Realm, fieldName: String? = null, sortOrder: Sort? = null): RealmResults<*> { + return realm.where(this.relatedEntity).findAll() + .sort(fieldName ?: this.sortingFieldName, sortOrder ?: this.sorting) + } - private var sortingFieldName: String = "name" - private var sorting: Sort = Sort.ASCENDING + /** + * Return a copy of a RealmResults + */ + fun itemsArray(realm: Realm, fieldName: String? = null, sortOrder: Sort? = null): ArrayList<*> { + val results: ArrayList = ArrayList() + results.addAll( + realm.copyFromRealm( + realm.where(this.relatedEntity).findAll().sort( + fieldName ?: this.sortingFieldName, sortOrder ?: this.sorting + ) + ) + ) + return results + } - private val relatedEntity: Class < out RealmObject > - get() { - return when (this) { - BANKROLL -> Bankroll::class.java - GAME -> Game::class.java - LOCATION -> Location::class.java - TOURNAMENT_FEATURE -> TournamentFeature::class.java - TRANSACTION_TYPE -> TransactionType::class.java - } - } + private var sortingFieldName: String = "name" + private var sorting: Sort = Sort.ASCENDING - fun newEntity(): RealmObject { - return when (this) { - BANKROLL -> Bankroll() - GAME -> Game() - LOCATION -> Location() - TOURNAMENT_FEATURE -> TournamentFeature() - TRANSACTION_TYPE -> TransactionType() - } - } - fun getData(realm:Realm, primaryKey:String?): RealmObject? { - var proxyItem: RealmObject? = null - primaryKey?.let { - val t = realm.where(this.relatedEntity).equalTo("id", it).findFirst() - t?.let { - proxyItem = t - } - } - return proxyItem - } + private val relatedEntity: Class + get() { + return when (this) { + BANKROLL -> Bankroll::class.java + GAME -> Game::class.java + LOCATION -> Location::class.java + TOURNAMENT_FEATURE -> TournamentFeature::class.java + TRANSACTION_TYPE -> TransactionType::class.java + } + } - fun updateOrCreate(realm:Realm, primaryKey:String?): RealmObject { - val proxyItem: RealmObject? = this.getData(realm, primaryKey) - proxyItem?.let { - return realm.copyFromRealm(it) - } ?: run { - return this.newEntity() + fun newEntity(): RealmObject { + return when (this) { + BANKROLL -> Bankroll() + GAME -> Game() + LOCATION -> Location() + TOURNAMENT_FEATURE -> TournamentFeature() + TRANSACTION_TYPE -> TransactionType() + } + } + + fun getData(realm: Realm, primaryKey: String?): RealmObject? { + var proxyItem: RealmObject? = null + primaryKey?.let { + val t = realm.where(this.relatedEntity).equalTo("id", it).findFirst() + t?.let { + proxyItem = t + } + } + return proxyItem + } + + fun updateOrCreate(realm: Realm, primaryKey: String?): RealmObject { + val proxyItem: RealmObject? = this.getData(realm, primaryKey) + proxyItem?.let { + return realm.copyFromRealm(it) + } ?: run { + return this.newEntity() /* realm.beginTransaction() val t = realm.createObject(this.relatedEntity, UUID.randomUUID().toString()) realm.commitTransaction() return realm.copyFromRealm(t)*/ - } - } + } + } - override val resId: Int? - get() { - return when (this) { - BANKROLL -> R.string.bankroll - GAME -> R.string.game - LOCATION -> R.string.location - TOURNAMENT_FEATURE -> R.string.tournament_type - TRANSACTION_TYPE -> R.string.operation_types - } - }} + override val resId: Int? + get() { + return when (this) { + BANKROLL -> R.string.bankroll + GAME -> R.string.game + LOCATION -> R.string.location + TOURNAMENT_FEATURE -> R.string.tournament_type + TRANSACTION_TYPE -> R.string.operation_types + } + } +} /* interface ListableDataSource { diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/Session.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/Session.kt index 1b7acfe3..7f328946 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/Session.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/Session.kt @@ -249,6 +249,7 @@ open class Session : RealmObject(), SessionInterface, RowRepresentableDataSource SessionRow.GAME -> game?.title ?: "--" SessionRow.LOCATION -> location?.title ?: "--" SessionRow.BANKROLL -> bankroll?.title ?: "--" + SessionRow.TABLE_SIZE -> tableSize?.toString() ?: "--" SessionRow.START_DATE -> if (timeFrame != null) timeFrame?.startDate?.short() ?: "--" else "--" SessionRow.END_DATE -> if (timeFrame != null) timeFrame?.endDate?.short() ?: "--" else "--" SessionRow.COMMENT -> if (comment.isNotEmpty()) comment else "--" @@ -292,6 +293,7 @@ open class Session : RealmObject(), SessionInterface, RowRepresentableDataSource data.add(BottomSheetData("", inputType = InputType.TYPE_CLASS_NUMBER)) data.add(BottomSheetData("", inputType = InputType.TYPE_CLASS_NUMBER)) } + SessionRow.TABLE_SIZE -> {} SessionRow.GAME -> { // Add current game & games list data.add(BottomSheetData(game, data = LiveData.GAME.items(realm))) @@ -325,7 +327,7 @@ open class Session : RealmObject(), SessionInterface, RowRepresentableDataSource localResult.buyin = value as Double result = localResult } - + SessionRow.TABLE_SIZE -> tableSize = value as Int? SessionRow.GAME -> game = value as Game? SessionRow.BANKROLL -> bankroll = value as Bankroll? SessionRow.LOCATION -> location = value as Location? diff --git a/app/src/main/java/net/pokeranalytics/android/ui/adapter/TableSizeGridAdapter.kt b/app/src/main/java/net/pokeranalytics/android/ui/adapter/TableSizeGridAdapter.kt new file mode 100644 index 00000000..c0ea5637 --- /dev/null +++ b/app/src/main/java/net/pokeranalytics/android/ui/adapter/TableSizeGridAdapter.kt @@ -0,0 +1,50 @@ +package net.pokeranalytics.android.ui.adapter + +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import kotlinx.android.synthetic.main.row_bottom_sheet_grid_title.view.* +import net.pokeranalytics.android.R + +class TableSizeGridAdapter(private var tableSizes: ArrayList) : RecyclerView.Adapter() { + + companion object { + const val ROW_TABLE_SIZE: Int = 100 + } + + var onClickOnItem: ((position: Int) -> Unit)? = null + + inner class CellSessionViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + + fun bind(tableSize: String) { + itemView.title.text = tableSize + itemView.container.setOnClickListener { + onClickOnItem?.invoke(adapterPosition) + } + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { + when (viewType) { + ROW_TABLE_SIZE -> return CellSessionViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.row_bottom_sheet_grid_title, parent, false)) + else -> throw IllegalStateException("Need to implement type $viewType in HistoryAdapter") + } + } + + override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { + when (getItemViewType(position)) { + ROW_TABLE_SIZE -> (holder as TableSizeGridAdapter.CellSessionViewHolder).bind(tableSizes[position]) + } + } + + override fun getItemCount(): Int { + return tableSizes.size + } + + override fun getItemViewType(position: Int): Int { + return ROW_TABLE_SIZE + } + + +} \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetData.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetData.kt index 703ddd1d..de66d062 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetData.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetData.kt @@ -2,7 +2,6 @@ package net.pokeranalytics.android.ui.fragment.components.bottomsheet import android.text.InputType import io.realm.RealmResults -import net.pokeranalytics.android.ui.view.RowRepresentable class BottomSheetData( var defaultValue: Any? = null, diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetDoubleListFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetDoubleListFragment.kt index 909ea02b..672817f2 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetDoubleListFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetDoubleListFragment.kt @@ -52,7 +52,7 @@ class BottomSheetDoubleListFragment : BottomSheetFragment(), LiveDataDelegate { val viewManager = LinearLayoutManager(requireContext()) val dataAdapter = LiveDataAdapter(this, R.layout.row_bottom_sheet_title) - gameNameRecyclerView.apply { + reyclerView1.apply { setHasFixedSize(true) layoutManager = viewManager adapter = dataAdapter diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetFragment.kt index 9406d9ef..bf079696 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetFragment.kt @@ -45,6 +45,7 @@ open class BottomSheetFragment : BottomSheetDialogFragment() { val bottomSheetFragment = when (row.bottomSheetType) { BottomSheetType.LIST -> BottomSheetListFragment() + BottomSheetType.GRID -> BottomSheetTableSizeGridFragment() BottomSheetType.DOUBLE_LIST -> BottomSheetDoubleListFragment() BottomSheetType.EDIT_TEXT -> BottomSheetEditTextFragment() BottomSheetType.DOUBLE_EDIT_TEXT -> BottomSheetDoubleEditTextFragment() diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetListFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetListFragment.kt index 5c0cff2e..ac569e71 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetListFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetListFragment.kt @@ -5,7 +5,7 @@ import android.view.LayoutInflater import android.view.View import androidx.recyclerview.widget.LinearLayoutManager import io.realm.RealmResults -import kotlinx.android.synthetic.main.bottom_sheet_double_list.* +import kotlinx.android.synthetic.main.bottom_sheet_list.* import kotlinx.android.synthetic.main.fragment_bottom_sheet.view.* import net.pokeranalytics.android.R import net.pokeranalytics.android.model.realm.Game @@ -58,7 +58,7 @@ class BottomSheetListFragment : BottomSheetFragment(), LiveDataDelegate { val bottomSheetData = getData() if (bottomSheetData.isNotEmpty() && bottomSheetData.first().data != null) { - this.realmData = bottomSheetData.first().data + this.realmData = bottomSheetData.first().data as RealmResults<*> } } @@ -72,7 +72,7 @@ class BottomSheetListFragment : BottomSheetFragment(), LiveDataDelegate { val viewManager = LinearLayoutManager(requireContext()) dataAdapter = LiveDataAdapter(this, R.layout.row_bottom_sheet_title) - gameNameRecyclerView.apply { + reyclerView.apply { setHasFixedSize(true) layoutManager = viewManager adapter = dataAdapter diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetTableSizeGridFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetTableSizeGridFragment.kt new file mode 100644 index 00000000..33b6c63e --- /dev/null +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetTableSizeGridFragment.kt @@ -0,0 +1,72 @@ +package net.pokeranalytics.android.ui.fragment.components.bottomsheet + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import androidx.recyclerview.widget.GridLayoutManager +import kotlinx.android.synthetic.main.bottom_sheet_grid.* +import kotlinx.android.synthetic.main.fragment_bottom_sheet.view.* +import net.pokeranalytics.android.ui.adapter.TableSizeGridAdapter +import net.pokeranalytics.android.ui.view.GridSpacingItemDecoration +import net.pokeranalytics.android.util.px + + +class BottomSheetTableSizeGridFragment : BottomSheetFragment() { + + private var dataList: ArrayList = ArrayList() + private lateinit var dataAdapter: TableSizeGridAdapter + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + initData() + initUI() + } + + override fun onResume() { + super.onResume() + dataAdapter.notifyDataSetChanged() + } + + /** + * Init data + */ + private fun initData() { + + dataList.add(getString(net.pokeranalytics.android.R.string.heads_up)) + for (i in 3..10) { + dataList.add("$i-max") + } + + } + + /** + * Init UI + */ + private fun initUI() { + + setAddButtonVisible(false) + + LayoutInflater.from(requireContext()) + .inflate(net.pokeranalytics.android.R.layout.bottom_sheet_grid, view?.bottomSheetContainer, true) + + val viewManager = GridLayoutManager(requireContext(), 3) + dataAdapter = TableSizeGridAdapter(dataList) + dataAdapter.onClickOnItem = { position -> + bottomSheetDelegate.setValue(position + 2, row) + dismiss() + } + + val spanCount = 3 + val spacing = 2.px + val includeEdge = false + + reyclerView.apply { + setHasFixedSize(true) + layoutManager = viewManager + adapter = dataAdapter + addItemDecoration(GridSpacingItemDecoration(spanCount, spacing, includeEdge)) + } + + } + +} \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/GridSpacingItemDecoration.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/GridSpacingItemDecoration.kt new file mode 100644 index 00000000..a9365df3 --- /dev/null +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/GridSpacingItemDecoration.kt @@ -0,0 +1,34 @@ +package net.pokeranalytics.android.ui.view + +import android.graphics.Rect +import android.view.View +import androidx.recyclerview.widget.RecyclerView + +/** + * Manage spacing for recycler view & grid layout manager + */ +class GridSpacingItemDecoration(val spanCount: Int, val spacing: Int, val includeEdge: Boolean) : + RecyclerView.ItemDecoration() { + + override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) { + val position = parent.getChildAdapterPosition(view) // item position + val column = position % spanCount // item column + + if (includeEdge) { + outRect.left = spacing - column * spacing / spanCount // spacing - column * ((1f / spanCount) * spacing) + outRect.right = (column + 1) * spacing / spanCount // (column + 1) * ((1f / spanCount) * spacing) + + if (position < spanCount) { // top edge + outRect.top = spacing + } + outRect.bottom = spacing // item bottom + } else { + outRect.left = column * spacing / spanCount // column * ((1f / spanCount) * spacing) + outRect.right = + spacing - (column + 1) * spacing / spanCount // spacing - (column + 1) * ((1f / spanCount) * spacing) + if (position >= spanCount) { + outRect.top = spacing // item top + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/util/Extensions.kt b/app/src/main/java/net/pokeranalytics/android/util/Extensions.kt index a4acec64..10fc83fe 100644 --- a/app/src/main/java/net/pokeranalytics/android/util/Extensions.kt +++ b/app/src/main/java/net/pokeranalytics/android/util/Extensions.kt @@ -1,5 +1,6 @@ package net.pokeranalytics.android.util +import android.content.res.Resources import android.widget.Toast import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity import net.pokeranalytics.android.ui.fragment.components.PokerAnalyticsFragment @@ -8,6 +9,16 @@ import java.text.DecimalFormat import java.text.SimpleDateFormat import java.util.* +// Sizes +val Int.dp: Int + get() = (this / Resources.getSystem().displayMetrics.density).toInt() +val Int.px: Int + get() = (this * Resources.getSystem().displayMetrics.density).toInt() +val Float.dp: Float + get() = (this / Resources.getSystem().displayMetrics.density) +val Float.px: Float + get() = (this * Resources.getSystem().displayMetrics.density) + // Double diff --git a/app/src/main/res/layout/bottom_sheet_double_list.xml b/app/src/main/res/layout/bottom_sheet_double_list.xml index 5a052178..53c8e506 100644 --- a/app/src/main/res/layout/bottom_sheet_double_list.xml +++ b/app/src/main/res/layout/bottom_sheet_double_list.xml @@ -5,13 +5,13 @@ android:orientation="horizontal"> diff --git a/app/src/main/res/layout/bottom_sheet_grid.xml b/app/src/main/res/layout/bottom_sheet_grid.xml new file mode 100644 index 00000000..eb13bef6 --- /dev/null +++ b/app/src/main/res/layout/bottom_sheet_grid.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/bottom_sheet_list.xml b/app/src/main/res/layout/bottom_sheet_list.xml index fbcf8383..eb13bef6 100644 --- a/app/src/main/res/layout/bottom_sheet_list.xml +++ b/app/src/main/res/layout/bottom_sheet_list.xml @@ -4,7 +4,7 @@ android:layout_height="wrap_content"> diff --git a/app/src/main/res/layout/row_bottom_sheet_grid_title.xml b/app/src/main/res/layout/row_bottom_sheet_grid_title.xml new file mode 100644 index 00000000..acc6c7c2 --- /dev/null +++ b/app/src/main/res/layout/row_bottom_sheet_grid_title.xml @@ -0,0 +1,26 @@ + + + + + + \ No newline at end of file From 8e661c440a7b43d91c4ca32f02b3a349379d22d0 Mon Sep 17 00:00:00 2001 From: Aurelien Hubert Date: Thu, 21 Feb 2019 11:10:59 +0100 Subject: [PATCH 2/2] Fix TimeFrame --- .../java/net/pokeranalytics/android/model/realm/TimeFrame.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/TimeFrame.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/TimeFrame.kt index 40dae22f..c41267b6 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/TimeFrame.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/TimeFrame.kt @@ -51,7 +51,7 @@ open class TimeFrame : RealmObject() { @Ignore var session: Session? = null - //get() = this.sessions?.first() ?: null + get() = if (this.sessions != null && this.sessions.isEmpty()) null else this.sessions?.first() // Group @LinkingObjects("timeFrame")