commit
0b60373f24
@ -0,0 +1,48 @@ |
|||||||
|
package net.pokeranalytics.android.ui.activity |
||||||
|
|
||||||
|
import android.content.Intent |
||||||
|
import android.os.Bundle |
||||||
|
import androidx.fragment.app.Fragment |
||||||
|
import net.pokeranalytics.android.R |
||||||
|
import net.pokeranalytics.android.calculus.bankroll.BankrollReport |
||||||
|
import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity |
||||||
|
import net.pokeranalytics.android.ui.fragment.BankrollDetailsFragment |
||||||
|
|
||||||
|
class BankrollDetailsActivity : PokerAnalyticsActivity() { |
||||||
|
|
||||||
|
companion object { |
||||||
|
|
||||||
|
private var bankrollReport: BankrollReport? = null |
||||||
|
|
||||||
|
/** |
||||||
|
* Default constructor |
||||||
|
*/ |
||||||
|
fun newInstanceForResult(fragment: Fragment, bankrollReport: BankrollReport, requestCode: Int) { |
||||||
|
this.bankrollReport = bankrollReport |
||||||
|
val intent = Intent(fragment.requireContext(), BankrollDetailsActivity::class.java) |
||||||
|
fragment.startActivityForResult(intent, requestCode) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) { |
||||||
|
super.onCreate(savedInstanceState) |
||||||
|
setContentView(R.layout.activity_bankroll_details) |
||||||
|
initUI() |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Init UI |
||||||
|
*/ |
||||||
|
private fun initUI() { |
||||||
|
|
||||||
|
bankrollReport?.let { |
||||||
|
val fragmentTransaction = supportFragmentManager.beginTransaction() |
||||||
|
val reportDetailsFragment = BankrollDetailsFragment.newInstance(it) |
||||||
|
fragmentTransaction.add(R.id.container, reportDetailsFragment) |
||||||
|
fragmentTransaction.commit() |
||||||
|
|
||||||
|
bankrollReport = null |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,127 @@ |
|||||||
|
package net.pokeranalytics.android.ui.activity |
||||||
|
|
||||||
|
import android.animation.Animator |
||||||
|
import android.animation.AnimatorListenerAdapter |
||||||
|
import android.content.Context |
||||||
|
import android.content.Intent |
||||||
|
import android.os.Bundle |
||||||
|
import android.view.View |
||||||
|
import android.view.ViewAnimationUtils |
||||||
|
import kotlinx.android.synthetic.main.activity_new_data.* |
||||||
|
import kotlinx.coroutines.Dispatchers |
||||||
|
import kotlinx.coroutines.GlobalScope |
||||||
|
import kotlinx.coroutines.delay |
||||||
|
import kotlinx.coroutines.launch |
||||||
|
import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity |
||||||
|
import net.pokeranalytics.android.ui.extensions.px |
||||||
|
|
||||||
|
|
||||||
|
class NewDataMenuActivity : PokerAnalyticsActivity() { |
||||||
|
|
||||||
|
enum class IntentKey(val keyName: String) { |
||||||
|
CHOICE("CHOICE"), |
||||||
|
} |
||||||
|
|
||||||
|
companion object { |
||||||
|
fun newInstance(context: Context) { |
||||||
|
val intent = Intent(context, NewDataMenuActivity::class.java) |
||||||
|
context.startActivity(intent) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private val fabSize = 48.px |
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) { |
||||||
|
super.onCreate(savedInstanceState) |
||||||
|
setContentView(net.pokeranalytics.android.R.layout.activity_new_data) |
||||||
|
initUI() |
||||||
|
} |
||||||
|
|
||||||
|
override fun onBackPressed() { |
||||||
|
hideMenu() |
||||||
|
} |
||||||
|
|
||||||
|
override fun onPause() { |
||||||
|
super.onPause() |
||||||
|
overridePendingTransition(0, 0) |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Init UI |
||||||
|
*/ |
||||||
|
private fun initUI() { |
||||||
|
|
||||||
|
overridePendingTransition(0, 0) |
||||||
|
|
||||||
|
container.viewTreeObserver.addOnGlobalLayoutListener { |
||||||
|
showMenu() |
||||||
|
} |
||||||
|
|
||||||
|
newCashGame.setOnClickListener { |
||||||
|
finishWithResult(0) |
||||||
|
} |
||||||
|
|
||||||
|
newTournament.setOnClickListener { |
||||||
|
finishWithResult(1) |
||||||
|
} |
||||||
|
|
||||||
|
newTransaction.setOnClickListener { |
||||||
|
finishWithResult(2) |
||||||
|
} |
||||||
|
|
||||||
|
container.setOnClickListener { |
||||||
|
hideMenu() |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Set the result and hide menu |
||||||
|
*/ |
||||||
|
private fun finishWithResult(choice: Int) { |
||||||
|
val intent = Intent() |
||||||
|
intent.putExtra(IntentKey.CHOICE.keyName, choice) |
||||||
|
setResult(RESULT_OK, intent) |
||||||
|
GlobalScope.launch(Dispatchers.Main) { |
||||||
|
delay(200) |
||||||
|
hideMenu(true) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Show menu |
||||||
|
*/ |
||||||
|
private fun showMenu() { |
||||||
|
|
||||||
|
val cx = menuContainer.measuredWidth - fabSize / 2 |
||||||
|
val cy = menuContainer.measuredHeight - fabSize / 2 |
||||||
|
val finalRadius = Math.max(menuContainer.width, menuContainer.height) |
||||||
|
val anim = ViewAnimationUtils.createCircularReveal(menuContainer, cx, cy, 0f, finalRadius.toFloat()) |
||||||
|
anim.duration = 300 |
||||||
|
|
||||||
|
menuContainer.visibility = View.VISIBLE |
||||||
|
anim.start() |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Hide menu |
||||||
|
*/ |
||||||
|
private fun hideMenu(hideQuickly: Boolean = false) { |
||||||
|
|
||||||
|
val cx = menuContainer.measuredWidth - fabSize / 2 |
||||||
|
val cy = menuContainer.measuredHeight - fabSize / 2 |
||||||
|
val initialRadius = menuContainer.width |
||||||
|
val anim = ViewAnimationUtils.createCircularReveal(menuContainer, cx, cy, initialRadius.toFloat(), 0f) |
||||||
|
anim.duration = if (hideQuickly) 150 else 300 |
||||||
|
|
||||||
|
anim.addListener(object : AnimatorListenerAdapter() { |
||||||
|
override fun onAnimationEnd(animation: Animator?) { |
||||||
|
super.onAnimationEnd(animation) |
||||||
|
menuContainer.visibility = View.INVISIBLE |
||||||
|
finish() |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
anim.start() |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,166 @@ |
|||||||
|
package net.pokeranalytics.android.ui.adapter |
||||||
|
|
||||||
|
import android.view.LayoutInflater |
||||||
|
import android.view.View |
||||||
|
import android.view.ViewGroup |
||||||
|
import androidx.appcompat.widget.AppCompatTextView |
||||||
|
import androidx.recyclerview.widget.RecyclerView |
||||||
|
import io.realm.RealmResults |
||||||
|
import kotlinx.android.synthetic.main.row_transaction.view.* |
||||||
|
import net.pokeranalytics.android.R |
||||||
|
import net.pokeranalytics.android.model.realm.Transaction |
||||||
|
import net.pokeranalytics.android.ui.view.BindableHolder |
||||||
|
import net.pokeranalytics.android.ui.view.RowViewType |
||||||
|
import net.pokeranalytics.android.util.NULL_TEXT |
||||||
|
import net.pokeranalytics.android.util.extensions.getMonthAndYear |
||||||
|
import timber.log.Timber |
||||||
|
import java.util.* |
||||||
|
import kotlin.collections.HashMap |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* An adapter capable of displaying a list of RowRepresentables |
||||||
|
* @param dataSource the datasource providing rows |
||||||
|
* @param delegate the delegate, notified of UI actions |
||||||
|
*/ |
||||||
|
class FeedTransactionRowRepresentableAdapter( |
||||||
|
var delegate: RowRepresentableDelegate? = null, |
||||||
|
var realmTransactions: RealmResults<Transaction>, |
||||||
|
var distinctTransactionsHeaders: RealmResults<Transaction> |
||||||
|
) : |
||||||
|
RecyclerView.Adapter<RecyclerView.ViewHolder>() { |
||||||
|
|
||||||
|
private var headersPositions = HashMap<Int, Date?>() |
||||||
|
private lateinit var sortedHeaders: SortedMap<Int, Date?> |
||||||
|
|
||||||
|
init { |
||||||
|
refreshData() |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Display a transaction view |
||||||
|
*/ |
||||||
|
inner class RowTransactionViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), BindableHolder { |
||||||
|
fun bind(position: Int, row: Transaction?, adapter: FeedTransactionRowRepresentableAdapter) { |
||||||
|
|
||||||
|
itemView.transactionRow.setData(row as Transaction) |
||||||
|
val listener = View.OnClickListener { |
||||||
|
adapter.delegate?.onRowSelected(position, row) |
||||||
|
} |
||||||
|
itemView.transactionRow.setOnClickListener(listener) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Display a header |
||||||
|
*/ |
||||||
|
inner class HeaderTitleViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), BindableHolder { |
||||||
|
fun bind(title: String) { |
||||||
|
// Title |
||||||
|
itemView.findViewById<AppCompatTextView>(R.id.title)?.let { |
||||||
|
it.text = title |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { |
||||||
|
return if (viewType == RowViewType.ROW_TRANSACTION.ordinal) { |
||||||
|
val layout = LayoutInflater.from(parent.context).inflate(R.layout.row_transaction, parent, false) |
||||||
|
RowTransactionViewHolder(layout) |
||||||
|
} else { |
||||||
|
val layout = LayoutInflater.from(parent.context).inflate(R.layout.row_header_title, parent, false) |
||||||
|
HeaderTitleViewHolder(layout) |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
override fun getItemViewType(position: Int): Int { |
||||||
|
if (sortedHeaders.containsKey(position)) { |
||||||
|
return RowViewType.HEADER_TITLE.ordinal |
||||||
|
} else { |
||||||
|
return RowViewType.ROW_TRANSACTION.ordinal |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
override fun getItemCount(): Int { |
||||||
|
return realmTransactions.size + distinctTransactionsHeaders.size |
||||||
|
} |
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { |
||||||
|
if (holder is RowTransactionViewHolder) { |
||||||
|
holder.bind(position, getTransactionForPosition(position), this) |
||||||
|
} else if (holder is HeaderTitleViewHolder) { |
||||||
|
holder.bind(getHeaderForPosition(position)) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Return the header |
||||||
|
*/ |
||||||
|
private fun getHeaderForPosition(position: Int): String { |
||||||
|
if (sortedHeaders.containsKey(position)) { |
||||||
|
val realmHeaderPosition = sortedHeaders.keys.indexOf(position) |
||||||
|
return distinctTransactionsHeaders[realmHeaderPosition]?.date?.getMonthAndYear() ?: "" |
||||||
|
} |
||||||
|
return NULL_TEXT |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Get real index |
||||||
|
*/ |
||||||
|
private fun getTransactionForPosition(position: Int): Transaction? { |
||||||
|
|
||||||
|
// Row position |
||||||
|
var headersBefore = 0 |
||||||
|
for (key in sortedHeaders.keys) { |
||||||
|
if (position > key) { |
||||||
|
headersBefore++ |
||||||
|
} else { |
||||||
|
break |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return realmTransactions[position - headersBefore] |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Refresh headers positions |
||||||
|
*/ |
||||||
|
fun refreshData() { |
||||||
|
|
||||||
|
headersPositions.clear() |
||||||
|
|
||||||
|
val start = System.currentTimeMillis() |
||||||
|
|
||||||
|
var previousYear = Int.MAX_VALUE |
||||||
|
var previousMonth = Int.MAX_VALUE |
||||||
|
|
||||||
|
val calendar = Calendar.getInstance() |
||||||
|
|
||||||
|
// Add headers if the date doesn't exist yet |
||||||
|
for ((index, transaction) in realmTransactions.withIndex()) { |
||||||
|
calendar.time = transaction.date |
||||||
|
if (checkHeaderCondition(calendar, previousYear, previousMonth)) { |
||||||
|
headersPositions[index + headersPositions.size] = transaction.date |
||||||
|
previousYear = calendar.get(Calendar.YEAR) |
||||||
|
previousMonth = calendar.get(Calendar.MONTH) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
sortedHeaders = headersPositions.toSortedMap() |
||||||
|
|
||||||
|
Timber.d("Create viewTypesPositions in: ${System.currentTimeMillis() - start}ms") |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Check if we need to add a header |
||||||
|
* Can be change to manage different condition |
||||||
|
*/ |
||||||
|
private fun checkHeaderCondition(currentCalendar: Calendar, previousYear: Int, previousMonth: Int): Boolean { |
||||||
|
return currentCalendar.get(Calendar.YEAR) == previousYear && currentCalendar.get(Calendar.MONTH) < previousMonth || (currentCalendar.get(Calendar.YEAR) < previousYear) |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,166 @@ |
|||||||
|
package net.pokeranalytics.android.ui.fragment |
||||||
|
|
||||||
|
import android.app.Activity.RESULT_OK |
||||||
|
import android.content.Intent |
||||||
|
import android.os.Bundle |
||||||
|
import android.view.* |
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager |
||||||
|
import kotlinx.android.synthetic.main.fragment_bankroll.* |
||||||
|
import kotlinx.android.synthetic.main.fragment_stats.recyclerView |
||||||
|
import net.pokeranalytics.android.R |
||||||
|
import net.pokeranalytics.android.calculus.ComputedStat |
||||||
|
import net.pokeranalytics.android.calculus.Stat |
||||||
|
import net.pokeranalytics.android.calculus.bankroll.BankrollReport |
||||||
|
import net.pokeranalytics.android.model.LiveData |
||||||
|
import net.pokeranalytics.android.ui.activity.DataListActivity |
||||||
|
import net.pokeranalytics.android.ui.activity.EditableDataActivity |
||||||
|
import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity |
||||||
|
import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter |
||||||
|
import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate |
||||||
|
import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource |
||||||
|
import net.pokeranalytics.android.ui.fragment.components.PokerAnalyticsFragment |
||||||
|
import net.pokeranalytics.android.ui.view.RowRepresentable |
||||||
|
import net.pokeranalytics.android.ui.view.RowViewType |
||||||
|
import net.pokeranalytics.android.ui.view.rowrepresentable.CustomizableRowRepresentable |
||||||
|
|
||||||
|
class BankrollDetailsFragment : PokerAnalyticsFragment(), StaticRowRepresentableDataSource, RowRepresentableDelegate { |
||||||
|
|
||||||
|
companion object { |
||||||
|
|
||||||
|
const val REQUEST_CODE_EDIT = 1000 |
||||||
|
|
||||||
|
/** |
||||||
|
* Create new instance |
||||||
|
*/ |
||||||
|
fun newInstance(bankrollReport: BankrollReport): BankrollDetailsFragment { |
||||||
|
val fragment = BankrollDetailsFragment() |
||||||
|
fragment.bankrollReport = bankrollReport |
||||||
|
return fragment |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private lateinit var parentActivity: PokerAnalyticsActivity |
||||||
|
private lateinit var bankrollAdapter: RowRepresentableAdapter |
||||||
|
private lateinit var bankrollReport: BankrollReport |
||||||
|
|
||||||
|
private var bankrollDetailsMenu: Menu? = null |
||||||
|
private var rows: ArrayList<RowRepresentable> = ArrayList() |
||||||
|
|
||||||
|
// Life Cycle |
||||||
|
|
||||||
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { |
||||||
|
return inflater.inflate(R.layout.fragment_bankroll_details, container, false) |
||||||
|
} |
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { |
||||||
|
super.onViewCreated(view, savedInstanceState) |
||||||
|
initUI() |
||||||
|
initData() |
||||||
|
} |
||||||
|
|
||||||
|
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { |
||||||
|
super.onActivityResult(requestCode, resultCode, data) |
||||||
|
if (requestCode == REQUEST_CODE_EDIT && resultCode == RESULT_OK) { |
||||||
|
if (data != null && data.getBooleanExtra(DataListActivity.IntentKey.ITEM_DELETED.keyName, false)) { |
||||||
|
activity?.setResult(RESULT_OK, data) |
||||||
|
activity?.finish() |
||||||
|
} else { |
||||||
|
updateMenuUI() |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
override fun adapterRows(): List<RowRepresentable>? { |
||||||
|
return rows |
||||||
|
} |
||||||
|
|
||||||
|
override fun onRowSelected(position: Int, row: RowRepresentable, fromAction: Boolean) { |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) { |
||||||
|
menu?.clear() |
||||||
|
inflater?.inflate(R.menu.toolbar_comparison_chart, menu) |
||||||
|
this.bankrollDetailsMenu = menu |
||||||
|
updateMenuUI() |
||||||
|
super.onCreateOptionsMenu(menu, inflater) |
||||||
|
} |
||||||
|
|
||||||
|
override fun onOptionsItemSelected(item: MenuItem?): Boolean { |
||||||
|
when (item!!.itemId) { |
||||||
|
R.id.settings -> editBankroll() |
||||||
|
} |
||||||
|
return true |
||||||
|
} |
||||||
|
|
||||||
|
// Business |
||||||
|
|
||||||
|
/** |
||||||
|
* Init data |
||||||
|
*/ |
||||||
|
private fun initData() { |
||||||
|
|
||||||
|
rows.clear() |
||||||
|
|
||||||
|
rows.add(CustomizableRowRepresentable(RowViewType.HEADER_TITLE, resId = R.string.global)) |
||||||
|
|
||||||
|
val totalComputedStat = ComputedStat(Stat.NET_RESULT, bankrollReport.total) |
||||||
|
val netComputedStat = ComputedStat(Stat.NET_RESULT, bankrollReport.netResult) |
||||||
|
val netBankedComputedStat = ComputedStat(Stat.NET_RESULT, bankrollReport.netBanked) |
||||||
|
|
||||||
|
rows.add(CustomizableRowRepresentable(RowViewType.TITLE_VALUE, resId = R.string.bankroll, computedStat = totalComputedStat)) |
||||||
|
rows.add(CustomizableRowRepresentable(RowViewType.TITLE_VALUE, resId = R.string.net_result, computedStat = netComputedStat)) |
||||||
|
rows.add(CustomizableRowRepresentable(RowViewType.TITLE_VALUE, resId = R.string.net_banked, computedStat = netBankedComputedStat)) |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Init UI |
||||||
|
*/ |
||||||
|
private fun initUI() { |
||||||
|
|
||||||
|
parentActivity = activity as PokerAnalyticsActivity |
||||||
|
|
||||||
|
// Avoid a bug during setting the title |
||||||
|
toolbar.title = "" |
||||||
|
|
||||||
|
parentActivity.setSupportActionBar(toolbar) |
||||||
|
parentActivity.supportActionBar?.setDisplayHomeAsUpEnabled(true) |
||||||
|
setHasOptionsMenu(true) |
||||||
|
updateMenuUI() |
||||||
|
|
||||||
|
bankrollAdapter = RowRepresentableAdapter(this, this) |
||||||
|
|
||||||
|
val viewManager = LinearLayoutManager(requireContext()) |
||||||
|
|
||||||
|
recyclerView.apply { |
||||||
|
setHasFixedSize(true) |
||||||
|
layoutManager = viewManager |
||||||
|
adapter = bankrollAdapter |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Update menu UI |
||||||
|
*/ |
||||||
|
private fun updateMenuUI() { |
||||||
|
if (bankrollReport.setup.virtualBankroll) { |
||||||
|
toolbar.title = getString(R.string.total) |
||||||
|
collapsingToolbar.title = getString(R.string.total) |
||||||
|
bankrollDetailsMenu?.findItem(R.id.settings)?.isVisible = false |
||||||
|
} else { |
||||||
|
toolbar.title = bankrollReport.setup.bankroll?.name |
||||||
|
collapsingToolbar.title = bankrollReport.setup.bankroll?.name |
||||||
|
bankrollDetailsMenu?.findItem(R.id.settings)?.isVisible = true |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Open Bankroll edit activity |
||||||
|
*/ |
||||||
|
private fun editBankroll() { |
||||||
|
EditableDataActivity.newInstanceForResult(this, LiveData.BANKROLL.ordinal, bankrollReport.setup.bankroll?.id, REQUEST_CODE_EDIT) |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,192 @@ |
|||||||
|
package net.pokeranalytics.android.ui.fragment |
||||||
|
|
||||||
|
import android.app.Activity.RESULT_OK |
||||||
|
import android.content.Intent |
||||||
|
import android.os.Bundle |
||||||
|
import android.view.LayoutInflater |
||||||
|
import android.view.View |
||||||
|
import android.view.ViewGroup |
||||||
|
import android.widget.Toast |
||||||
|
import androidx.core.app.ActivityOptionsCompat |
||||||
|
import androidx.core.view.isVisible |
||||||
|
import androidx.interpolator.view.animation.FastOutSlowInInterpolator |
||||||
|
import io.realm.RealmResults |
||||||
|
import io.realm.Sort |
||||||
|
import io.realm.kotlin.where |
||||||
|
import kotlinx.android.synthetic.main.fragment_feed.* |
||||||
|
import net.pokeranalytics.android.R |
||||||
|
import net.pokeranalytics.android.model.LiveData |
||||||
|
import net.pokeranalytics.android.model.interfaces.Editable |
||||||
|
import net.pokeranalytics.android.model.realm.Session |
||||||
|
import net.pokeranalytics.android.model.realm.Transaction |
||||||
|
import net.pokeranalytics.android.ui.activity.EditableDataActivity |
||||||
|
import net.pokeranalytics.android.ui.activity.NewDataMenuActivity |
||||||
|
import net.pokeranalytics.android.ui.activity.SessionActivity |
||||||
|
import net.pokeranalytics.android.ui.adapter.FeedSessionRowRepresentableAdapter |
||||||
|
import net.pokeranalytics.android.ui.adapter.FeedTransactionRowRepresentableAdapter |
||||||
|
import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate |
||||||
|
import net.pokeranalytics.android.ui.fragment.components.PokerAnalyticsFragment |
||||||
|
import net.pokeranalytics.android.ui.view.RowRepresentable |
||||||
|
import net.pokeranalytics.android.ui.view.SmoothScrollLinearLayoutManager |
||||||
|
import net.pokeranalytics.android.util.Preferences |
||||||
|
import java.text.SimpleDateFormat |
||||||
|
import java.util.* |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class FeedFragment : PokerAnalyticsFragment(), RowRepresentableDelegate { |
||||||
|
|
||||||
|
companion object { |
||||||
|
|
||||||
|
const val REQUEST_CODE_MENU = 100 |
||||||
|
|
||||||
|
fun newInstance(): FeedFragment { |
||||||
|
val fragment = FeedFragment() |
||||||
|
val bundle = Bundle() |
||||||
|
fragment.arguments = bundle |
||||||
|
return fragment |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private lateinit var feedSessionAdapter: FeedSessionRowRepresentableAdapter |
||||||
|
private lateinit var feedTransactionAdapter: FeedTransactionRowRepresentableAdapter |
||||||
|
private lateinit var realmSessions: RealmResults<Session> |
||||||
|
private lateinit var realmTransactions: RealmResults<Transaction> |
||||||
|
private lateinit var betaLimitDate: Date |
||||||
|
|
||||||
|
private var newSessionCreated: Boolean = false |
||||||
|
|
||||||
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { |
||||||
|
return inflater.inflate(R.layout.fragment_feed, container, false) |
||||||
|
} |
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { |
||||||
|
super.onViewCreated(view, savedInstanceState) |
||||||
|
initUI() |
||||||
|
initData() |
||||||
|
} |
||||||
|
|
||||||
|
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { |
||||||
|
super.onActivityResult(requestCode, resultCode, data) |
||||||
|
if (requestCode == REQUEST_CODE_MENU && resultCode == RESULT_OK && data != null) { |
||||||
|
when(data.getIntExtra(NewDataMenuActivity.IntentKey.CHOICE.keyName, -1)) { |
||||||
|
0 -> createNewSession(false) |
||||||
|
1 -> createNewSession(true) |
||||||
|
2 -> createNewTransaction() |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
override fun onDestroyView() { |
||||||
|
super.onDestroyView() |
||||||
|
realmSessions.removeAllChangeListeners() |
||||||
|
} |
||||||
|
|
||||||
|
override fun onRowSelected(position: Int, row: RowRepresentable, fromAction: Boolean) { |
||||||
|
when(row) { |
||||||
|
is Session -> SessionActivity.newInstance(requireContext(), sessionId = (row as Editable).id) |
||||||
|
is Transaction -> EditableDataActivity.newInstance(requireContext(), LiveData.TRANSACTION.ordinal, row.id) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Init UI |
||||||
|
*/ |
||||||
|
private fun initUI() { |
||||||
|
|
||||||
|
disclaimerContainer.isVisible = Preferences.shouldShowDisclaimer(requireContext()) |
||||||
|
|
||||||
|
disclaimerDismiss.setOnClickListener { |
||||||
|
Preferences.setStopShowingDisclaimer(requireContext()) |
||||||
|
|
||||||
|
disclaimerContainer.animate().translationY(disclaimerContainer.height.toFloat()) |
||||||
|
.setInterpolator(FastOutSlowInInterpolator()) |
||||||
|
.withEndAction { disclaimerContainer?.isVisible = false } |
||||||
|
.start() |
||||||
|
} |
||||||
|
|
||||||
|
addButton.setOnClickListener { |
||||||
|
activity?.let { |
||||||
|
val options = ActivityOptionsCompat.makeSceneTransitionAnimation(it) |
||||||
|
val intent = Intent(requireContext(), NewDataMenuActivity::class.java) |
||||||
|
startActivityForResult(intent, REQUEST_CODE_MENU, options.toBundle()) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
filterSessions.setOnClickListener { |
||||||
|
recyclerView.adapter = this.feedSessionAdapter |
||||||
|
} |
||||||
|
|
||||||
|
filterTransactions.setOnClickListener { |
||||||
|
recyclerView.adapter = this.feedTransactionAdapter |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Init data |
||||||
|
*/ |
||||||
|
private fun initData() { |
||||||
|
|
||||||
|
val sdf = SimpleDateFormat("dd/M/yyyy hh:mm", Locale.getDefault()) |
||||||
|
betaLimitDate = sdf.parse("17/7/2019 10:00") |
||||||
|
|
||||||
|
this.realmSessions = getRealm().where<Session>().findAll().sort("startDate", Sort.DESCENDING) |
||||||
|
this.realmSessions.addChangeListener { _, _ -> |
||||||
|
this.feedSessionAdapter.refreshData() |
||||||
|
this.feedSessionAdapter.notifyDataSetChanged() |
||||||
|
} |
||||||
|
|
||||||
|
val pendingSessions = getRealm().where<Session>().isNull("year").isNull("month").findAll().sort("startDate", Sort.DESCENDING) |
||||||
|
val distinctDateSessions = getRealm().where<Session>().distinct("year", "month").findAll().sort("startDate", Sort.DESCENDING) |
||||||
|
this.feedSessionAdapter = FeedSessionRowRepresentableAdapter(this, realmSessions, pendingSessions, distinctDateSessions) |
||||||
|
|
||||||
|
this.realmTransactions = getRealm().where<Transaction>().findAll().sort("date", Sort.DESCENDING) |
||||||
|
val distinctDateTransactions = getRealm().where<Transaction>().distinct("year", "month").findAll().sort("date", Sort.DESCENDING) |
||||||
|
this.feedTransactionAdapter = FeedTransactionRowRepresentableAdapter(this, realmTransactions, distinctDateTransactions) |
||||||
|
|
||||||
|
val viewManager = SmoothScrollLinearLayoutManager(requireContext()) |
||||||
|
recyclerView.apply { |
||||||
|
setHasFixedSize(true) |
||||||
|
layoutManager = viewManager |
||||||
|
adapter = feedSessionAdapter |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new cash game |
||||||
|
*/ |
||||||
|
private fun createNewSession(isTournament: Boolean) { |
||||||
|
|
||||||
|
if (Date().after(betaLimitDate)) { |
||||||
|
this.showEndOfBetaMessage() |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
SessionActivity.newInstance(requireContext(), isTournament) |
||||||
|
newSessionCreated = true |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new transaction |
||||||
|
*/ |
||||||
|
private fun createNewTransaction() { |
||||||
|
|
||||||
|
if (Date().after(betaLimitDate)) { |
||||||
|
this.showEndOfBetaMessage() |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
EditableDataActivity.newInstance(requireContext(), LiveData.TRANSACTION.ordinal) |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Show end of beta message |
||||||
|
*/ |
||||||
|
private fun showEndOfBetaMessage() { |
||||||
|
Toast.makeText(context, "Beta has ended. Please update with the Google Play version", Toast.LENGTH_LONG).show() |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -1,152 +0,0 @@ |
|||||||
package net.pokeranalytics.android.ui.fragment |
|
||||||
|
|
||||||
import android.os.Bundle |
|
||||||
import android.view.LayoutInflater |
|
||||||
import android.view.View |
|
||||||
import android.view.ViewGroup |
|
||||||
import android.widget.Toast |
|
||||||
import androidx.core.view.isVisible |
|
||||||
import androidx.interpolator.view.animation.FastOutSlowInInterpolator |
|
||||||
import io.realm.RealmResults |
|
||||||
import io.realm.Sort |
|
||||||
import io.realm.kotlin.where |
|
||||||
import kotlinx.android.synthetic.main.fragment_history.* |
|
||||||
import net.pokeranalytics.android.R |
|
||||||
import net.pokeranalytics.android.model.interfaces.Editable |
|
||||||
import net.pokeranalytics.android.model.realm.Session |
|
||||||
import net.pokeranalytics.android.ui.activity.SessionActivity |
|
||||||
import net.pokeranalytics.android.ui.adapter.HistorySessionRowRepresentableAdapter |
|
||||||
import net.pokeranalytics.android.ui.adapter.LiveRowRepresentableDataSource |
|
||||||
import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate |
|
||||||
import net.pokeranalytics.android.ui.fragment.components.PokerAnalyticsFragment |
|
||||||
import net.pokeranalytics.android.ui.view.RowRepresentable |
|
||||||
import net.pokeranalytics.android.ui.view.SmoothScrollLinearLayoutManager |
|
||||||
import net.pokeranalytics.android.util.Preferences |
|
||||||
import java.text.SimpleDateFormat |
|
||||||
import java.util.* |
|
||||||
|
|
||||||
class HistoryFragment : PokerAnalyticsFragment(), LiveRowRepresentableDataSource, RowRepresentableDelegate { |
|
||||||
|
|
||||||
companion object { |
|
||||||
fun newInstance(): HistoryFragment { |
|
||||||
val fragment = HistoryFragment() |
|
||||||
val bundle = Bundle() |
|
||||||
fragment.arguments = bundle |
|
||||||
return fragment |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private lateinit var historyAdapter: HistorySessionRowRepresentableAdapter |
|
||||||
|
|
||||||
private lateinit var realmSessions: RealmResults<Session> |
|
||||||
private val rows: ArrayList<RowRepresentable> = ArrayList() |
|
||||||
private var newSessionCreated: Boolean = false |
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { |
|
||||||
return inflater.inflate(R.layout.fragment_history, container, false) |
|
||||||
} |
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { |
|
||||||
super.onViewCreated(view, savedInstanceState) |
|
||||||
initUI() |
|
||||||
initData() |
|
||||||
} |
|
||||||
|
|
||||||
override fun onDestroyView() { |
|
||||||
super.onDestroyView() |
|
||||||
realmSessions.removeAllChangeListeners() |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Init UI |
|
||||||
*/ |
|
||||||
private fun initUI() { |
|
||||||
|
|
||||||
disclaimerContainer.isVisible = Preferences.shouldShowDisclaimer(requireContext()) |
|
||||||
|
|
||||||
val sdf = SimpleDateFormat("dd/M/yyyy hh:mm") |
|
||||||
val betaLimitDate = sdf.parse("17/7/2019 10:00") |
|
||||||
|
|
||||||
newCashGame.setOnClickListener { |
|
||||||
|
|
||||||
if (Date().after(betaLimitDate)) { |
|
||||||
this.showEndOfBetaMessage() |
|
||||||
return@setOnClickListener |
|
||||||
} |
|
||||||
|
|
||||||
SessionActivity.newInstance(requireContext(), false) |
|
||||||
newSessionCreated = true |
|
||||||
} |
|
||||||
|
|
||||||
newTournament.setOnClickListener { |
|
||||||
|
|
||||||
if (Date().after(betaLimitDate)) { |
|
||||||
this.showEndOfBetaMessage() |
|
||||||
return@setOnClickListener |
|
||||||
} |
|
||||||
|
|
||||||
SessionActivity.newInstance(requireContext(), true) |
|
||||||
newSessionCreated = true |
|
||||||
} |
|
||||||
|
|
||||||
disclaimerDismiss.setOnClickListener { |
|
||||||
Preferences.setStopShowingDisclaimer(requireContext()) |
|
||||||
|
|
||||||
disclaimerContainer.animate().translationY(disclaimerContainer.height.toFloat()) |
|
||||||
.setInterpolator(FastOutSlowInInterpolator()) |
|
||||||
.withEndAction { disclaimerContainer?.isVisible = false } |
|
||||||
.start() |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
private fun showEndOfBetaMessage() { |
|
||||||
Toast.makeText(context, "Beta has ended. Please update with the Google Play version", Toast.LENGTH_LONG).show() |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Init data |
|
||||||
*/ |
|
||||||
private fun initData() { |
|
||||||
|
|
||||||
this.realmSessions = getRealm().where<Session>().findAll().sort("startDate", Sort.DESCENDING) |
|
||||||
this.realmSessions.addChangeListener { _, _ -> |
|
||||||
this.historyAdapter.refreshData() |
|
||||||
this.historyAdapter.notifyDataSetChanged() |
|
||||||
} |
|
||||||
|
|
||||||
val startedSessions = getRealm().where<Session>().isNotNull("year").isNotNull("month").findAll().sort("startDate", Sort.DESCENDING) |
|
||||||
val pendingSessions = getRealm().where<Session>().isNull("year").isNull("month").findAll().sort("startDate", Sort.DESCENDING) |
|
||||||
val distinctDateSessions = getRealm().where<Session>().distinct("year", "month").findAll().sort("startDate", Sort.DESCENDING) |
|
||||||
|
|
||||||
this.historyAdapter = HistorySessionRowRepresentableAdapter(this, startedSessions, pendingSessions, distinctDateSessions) |
|
||||||
|
|
||||||
val viewManager = SmoothScrollLinearLayoutManager(requireContext()) |
|
||||||
recyclerView.apply { |
|
||||||
setHasFixedSize(true) |
|
||||||
layoutManager = viewManager |
|
||||||
adapter = historyAdapter |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
override fun rowRepresentableForPosition(position: Int): RowRepresentable? { |
|
||||||
return this.rows[position] |
|
||||||
} |
|
||||||
|
|
||||||
override fun numberOfRows(): Int { |
|
||||||
return this.rows.size |
|
||||||
} |
|
||||||
|
|
||||||
override fun viewTypeForPosition(position: Int): Int { |
|
||||||
return rows[position].viewType |
|
||||||
} |
|
||||||
|
|
||||||
override fun indexForRow(row: RowRepresentable): Int { |
|
||||||
return this.rows.indexOf(row) |
|
||||||
} |
|
||||||
|
|
||||||
override fun onRowSelected(position: Int, row: RowRepresentable, fromAction: Boolean) { |
|
||||||
SessionActivity.newInstance(requireContext(), sessionId = (row as Editable).id) |
|
||||||
} |
|
||||||
} |
|
||||||
@ -0,0 +1,7 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" |
||||||
|
android:id="@+id/container" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="match_parent"> |
||||||
|
|
||||||
|
</FrameLayout> |
||||||
@ -0,0 +1,132 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" |
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto" |
||||||
|
xmlns:tools="http://schemas.android.com/tools" |
||||||
|
android:id="@+id/container" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="match_parent"> |
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout |
||||||
|
android:id="@+id/menuContainer" |
||||||
|
android:layout_width="wrap_content" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:layout_gravity="center" |
||||||
|
android:layout_marginEnd="16dp" |
||||||
|
android:layout_marginBottom="72dp" |
||||||
|
android:background="@android:color/transparent" |
||||||
|
android:elevation="4dp" |
||||||
|
android:orientation="vertical" |
||||||
|
android:visibility="invisible" |
||||||
|
app:layout_constraintBottom_toBottomOf="parent" |
||||||
|
app:layout_constraintEnd_toEndOf="parent" |
||||||
|
tools:visibility="visible"> |
||||||
|
|
||||||
|
<View |
||||||
|
android:layout_width="0dp" |
||||||
|
android:layout_height="0dp" |
||||||
|
android:transitionName="newButtonTransition" |
||||||
|
app:layout_constraintBottom_toBottomOf="parent" |
||||||
|
app:layout_constraintEnd_toEndOf="parent" |
||||||
|
android:background="@color/gray_darker" |
||||||
|
app:layout_constraintStart_toStartOf="parent" |
||||||
|
app:layout_constraintTop_toTopOf="parent" /> |
||||||
|
|
||||||
|
<LinearLayout |
||||||
|
android:id="@+id/newCashGame" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="48dp" |
||||||
|
android:layout_marginTop="8dp" |
||||||
|
android:background="?selectableItemBackground" |
||||||
|
android:gravity="center_vertical" |
||||||
|
android:orientation="horizontal" |
||||||
|
android:paddingStart="24dp" |
||||||
|
android:paddingEnd="24dp" |
||||||
|
app:layout_constraintEnd_toEndOf="parent" |
||||||
|
app:layout_constraintStart_toStartOf="parent" |
||||||
|
app:layout_constraintTop_toTopOf="parent"> |
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatImageView |
||||||
|
android:layout_width="32dp" |
||||||
|
android:layout_height="32dp" |
||||||
|
android:tint="@color/green" |
||||||
|
app:layout_constraintStart_toStartOf="parent" |
||||||
|
app:layout_constraintTop_toTopOf="parent" |
||||||
|
app:srcCompat="@drawable/add_cash_game" /> |
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatTextView |
||||||
|
style="@style/PokerAnalyticsTheme.TextView.RowTitle" |
||||||
|
android:layout_width="160dp" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:layout_marginStart="20dp" |
||||||
|
android:text="@string/new_cash_game" |
||||||
|
app:layout_constraintEnd_toEndOf="parent" /> |
||||||
|
|
||||||
|
</LinearLayout> |
||||||
|
|
||||||
|
<LinearLayout |
||||||
|
android:id="@+id/newTournament" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="48dp" |
||||||
|
android:background="?selectableItemBackground" |
||||||
|
android:gravity="center_vertical" |
||||||
|
android:orientation="horizontal" |
||||||
|
android:paddingStart="24dp" |
||||||
|
android:paddingEnd="24dp" |
||||||
|
app:layout_constraintEnd_toEndOf="parent" |
||||||
|
app:layout_constraintStart_toStartOf="parent" |
||||||
|
app:layout_constraintTop_toBottomOf="@+id/newCashGame"> |
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatImageView |
||||||
|
android:layout_width="32dp" |
||||||
|
android:layout_height="32dp" |
||||||
|
android:tint="@color/green" |
||||||
|
app:layout_constraintStart_toStartOf="parent" |
||||||
|
app:layout_constraintTop_toTopOf="parent" |
||||||
|
app:srcCompat="@drawable/add_tournament" /> |
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatTextView |
||||||
|
style="@style/PokerAnalyticsTheme.TextView.RowTitle" |
||||||
|
android:layout_width="160dp" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:layout_marginStart="20dp" |
||||||
|
android:text="@string/new_tournament" |
||||||
|
app:layout_constraintEnd_toEndOf="parent" /> |
||||||
|
|
||||||
|
</LinearLayout> |
||||||
|
|
||||||
|
<LinearLayout |
||||||
|
android:id="@+id/newTransaction" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="48dp" |
||||||
|
android:layout_marginBottom="8dp" |
||||||
|
android:background="?selectableItemBackground" |
||||||
|
android:gravity="center_vertical" |
||||||
|
android:orientation="horizontal" |
||||||
|
android:paddingStart="24dp" |
||||||
|
android:paddingEnd="24dp" |
||||||
|
app:layout_constraintBottom_toBottomOf="parent" |
||||||
|
app:layout_constraintEnd_toEndOf="parent" |
||||||
|
app:layout_constraintStart_toStartOf="parent" |
||||||
|
app:layout_constraintTop_toBottomOf="@+id/newTournament"> |
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatImageView |
||||||
|
android:layout_width="32dp" |
||||||
|
android:layout_height="32dp" |
||||||
|
android:tint="@color/green" |
||||||
|
app:layout_constraintStart_toStartOf="parent" |
||||||
|
app:layout_constraintTop_toTopOf="parent" |
||||||
|
app:srcCompat="@drawable/add_transaction" /> |
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatTextView |
||||||
|
style="@style/PokerAnalyticsTheme.TextView.RowTitle" |
||||||
|
android:layout_width="160dp" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:layout_marginStart="20dp" |
||||||
|
android:text="@string/new_operation" |
||||||
|
app:layout_constraintEnd_toEndOf="parent" /> |
||||||
|
|
||||||
|
</LinearLayout> |
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout> |
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout> |
||||||
@ -0,0 +1,56 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" |
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="match_parent"> |
||||||
|
|
||||||
|
<androidx.core.widget.NestedScrollView |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="match_parent" |
||||||
|
android:fillViewport="true" |
||||||
|
app:layout_behavior="@string/appbar_scrolling_view_behavior"> |
||||||
|
|
||||||
|
<FrameLayout |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content"> |
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView |
||||||
|
android:id="@+id/recyclerView" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="match_parent" |
||||||
|
android:clipToPadding="false" /> |
||||||
|
|
||||||
|
</FrameLayout> |
||||||
|
|
||||||
|
</androidx.core.widget.NestedScrollView> |
||||||
|
|
||||||
|
<com.google.android.material.appbar.AppBarLayout |
||||||
|
android:id="@+id/appBar" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="128dp" |
||||||
|
android:theme="@style/PokerAnalyticsTheme.Toolbar.Session"> |
||||||
|
|
||||||
|
<com.google.android.material.appbar.CollapsingToolbarLayout |
||||||
|
android:id="@+id/collapsingToolbar" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="match_parent" |
||||||
|
app:collapsedTitleTextAppearance="@style/PokerAnalyticsTheme.Toolbar.CollapsedTitleAppearance" |
||||||
|
app:contentScrim="?attr/colorPrimary" |
||||||
|
app:expandedTitleGravity="bottom" |
||||||
|
app:expandedTitleMarginStart="72dp" |
||||||
|
app:expandedTitleTextAppearance="@style/PokerAnalyticsTheme.Toolbar.ExpandedTitleAppearance" |
||||||
|
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"> |
||||||
|
|
||||||
|
<androidx.appcompat.widget.Toolbar |
||||||
|
android:id="@+id/toolbar" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="?attr/actionBarSize" |
||||||
|
app:layout_collapseMode="pin" |
||||||
|
app:title="@string/bankroll" |
||||||
|
app:titleTextColor="@color/white" /> |
||||||
|
|
||||||
|
</com.google.android.material.appbar.CollapsingToolbarLayout> |
||||||
|
|
||||||
|
</com.google.android.material.appbar.AppBarLayout> |
||||||
|
|
||||||
|
</androidx.coordinatorlayout.widget.CoordinatorLayout> |
||||||
@ -0,0 +1,11 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android" |
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"> |
||||||
|
|
||||||
|
<item |
||||||
|
android:id="@+id/settings" |
||||||
|
android:title="@string/services" |
||||||
|
android:icon="@drawable/ic_outline_settings" |
||||||
|
app:showAsAction="always" /> |
||||||
|
|
||||||
|
</menu> |
||||||
Loading…
Reference in new issue