Implemented Navigation side bar to show and select bank accounts

This commit is contained in:
dankl 2020-01-12 16:18:22 +01:00 committed by dankito
parent a720430e71
commit 80e6694ec9
19 changed files with 237 additions and 32 deletions

View File

@ -2,10 +2,16 @@ package net.dankito.banking.fints4java.android
import android.os.Bundle
import android.support.design.widget.NavigationView
import android.support.v4.view.GravityCompat
import android.support.v4.widget.DrawerLayout
import android.support.v7.app.ActionBarDrawerToggle
import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.Toolbar
import android.view.Menu
import android.view.MenuItem
import android.view.MotionEvent
import android.view.SubMenu
import android.widget.TextView
import androidx.navigation.findNavController
import com.github.clans.fab.FloatingActionMenu
import kotlinx.android.synthetic.main.action_view_account_menu_item.view.*
@ -14,12 +20,20 @@ import net.dankito.banking.fints4java.android.util.Base64ServiceAndroid
import net.dankito.banking.fints4javaBankingClientCreator
import net.dankito.banking.ui.model.Account
import net.dankito.banking.ui.presenter.MainWindowPresenter
import org.slf4j.LoggerFactory
class MainActivity : AppCompatActivity() {
companion object {
private val log = LoggerFactory.getLogger(MainActivity::class.java)
}
// private lateinit var appBarConfiguration: AppBarConfiguration
private lateinit var drawerToggle: ActionBarDrawerToggle
private lateinit var floatingActionMenuButton: MainActivityFloatingActionMenuButton
@ -39,7 +53,7 @@ class MainActivity : AppCompatActivity() {
setSupportActionBar(toolbar)
val drawerLayout: DrawerLayout = findViewById(R.id.drawer_layout)
val navView: NavigationView = findViewById(R.id.nav_view)
val navigationView: NavigationView = findViewById(R.id.nav_view)
val navController = findNavController(R.id.nav_host_fragment)
// // Passing each menu ID as a set of Ids because each
@ -54,6 +68,13 @@ class MainActivity : AppCompatActivity() {
// setupActionBarWithNavController(navController, appBarConfiguration)
// navigationView.setupWithNavController(navController)
drawerToggle = ActionBarDrawerToggle(
this, drawerLayout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close)
drawerLayout.addDrawerListener(drawerToggle)
drawerToggle.syncState()
setupNavigationView(navigationView, drawerLayout)
val floatingActionMenu = findViewById<FloatingActionMenu>(R.id.floatingActionMenu)
floatingActionMenuButton = MainActivityFloatingActionMenuButton(floatingActionMenu, presenter)
}
@ -64,6 +85,84 @@ class MainActivity : AppCompatActivity() {
return true
}
private fun setupNavigationView(navigationView: NavigationView, drawerLayout: DrawerLayout) {
showAppVersion(navigationView)
val navigationMenu = navigationView.menu
val accountsMenuItem = navigationMenu.findItem(R.id.navBankAccountsSectionItem)
val accountsMenu = accountsMenuItem.subMenu
presenter.addAccountsChangedListener {
runOnUiThread { updateNavigationMenuItems(accountsMenu) }
}
updateNavigationMenuItems(accountsMenu)
navigationView.setNavigationItemSelectedListener { navigationItemSelected(it) }
}
private fun updateNavigationMenuItems(accountsMenu: SubMenu) {
accountsMenu.findItem(R.id.navAllBankAccounts).isVisible = presenter.accounts.isNotEmpty()
// removes previously shown accounts; index 0 = 'Add account', 1 = 'All accounts', don't remove these
for (index in (accountsMenu.size() - 1) downTo 2) {
accountsMenu.removeItem(accountsMenu.getItem(index).itemId)
}
presenter.accounts.forEach { account ->
val accountMenuItem = accountsMenu.add("")
accountMenuItem.setActionView(R.layout.action_view_account_menu_item)
accountMenuItem.actionView.txtvwAccountName.text = account.displayName
accountMenuItem.actionView.imgvwEditAccount.setImageResource(R.drawable.ic_build_white_48dp)
accountMenuItem.actionView.imgvwEditAccount.setOnClickListener { editAccount(account) }
accountMenuItem.setOnMenuItemClickListener { setSelectedAccount(account) }
}
}
private fun setSelectedAccount(account: Account): Boolean {
presenter.selectedAccount(account)
closeDrawer()
return true
}
private fun editAccount(account: Account) {
// TODO: implement
log.info("Edit account $account")
closeDrawer()
}
private fun showAppVersion(navigationView: NavigationView) {
try {
val packageInfo = this.packageManager.getPackageInfo(packageName, 0)
val version = packageInfo.versionName
(navigationView.getHeaderView(0).findViewById(R.id.txtAppVersion) as? TextView)?.text = version
} catch (e: Exception) {
log.error("Could not read application version")
}
}
private fun navigationItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.navAddBankAccount -> presenter.showAddAccountDialog()
R.id.navAllBankAccounts -> presenter.selectedAllBankAccounts()
}
closeDrawer()
return true
}
private fun closeDrawer() {
val drawer = findViewById(R.id.drawer_layout) as DrawerLayout
drawer.closeDrawer(GravityCompat.START)
}
// override fun onSupportNavigateUp(): Boolean {
// val navController = findNavController(R.id.nav_host_fragment)
// return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
@ -86,13 +185,4 @@ class MainActivity : AppCompatActivity() {
super.onBackPressed()
}
private fun getTanFromUserOffUiThread(account: Account, tanChallenge: TanChallenge): EnterTanResult {
return router.getTanFromUserOffUiThread(account, tanChallenge)
}
private fun getAtcFromUserOffUiThread(tanMedium: TanGeneratorTanMedium): EnterTanGeneratorAtcResult {
return router.getAtcFromUserOffUiThread(tanMedium)
}
}

View File

@ -15,7 +15,9 @@ import android.widget.EditText
import net.dankito.banking.fints4java.android.MainActivity
import net.dankito.banking.fints4java.android.R
import net.dankito.banking.fints4java.android.ui.adapter.AccountTransactionAdapter
import net.dankito.banking.ui.model.Account
import net.dankito.banking.ui.model.AccountTransaction
import net.dankito.banking.ui.model.BankAccount
import net.dankito.banking.ui.model.parameters.TransferMoneyData
import net.dankito.banking.ui.model.responses.GetTransactionsResponse
import net.dankito.banking.ui.presenter.MainWindowPresenter
@ -35,6 +37,8 @@ class HomeFragment : Fragment() {
private val transactionAdapter = AccountTransactionAdapter()
protected var appliedTransactionsFilter = ""
private lateinit var presenter: MainWindowPresenter
@ -127,6 +131,10 @@ class HomeFragment : Fragment() {
(context as? MainActivity)?.presenter?.let { presenter ->
this.presenter = presenter
presenter.addAccountsChangedListener { handleAccountsChanged(it) }
presenter.addSelectedBankAccountsChangedListener { handleSelectedBankAccountsChanged(it) }
presenter.addRetrievedAccountTransactionsResponseListener { _, response ->
handleGetTransactionsResponse(response)
}
@ -134,6 +142,23 @@ class HomeFragment : Fragment() {
}
private fun handleAccountsChanged(accounts: List<Account>) {
context?.asActivity()?.let { activity ->
activity.runOnUiThread {
mnitmSearchTransactions.isVisible = accounts.isNotEmpty()
mnitmUpdateTransactions.isVisible = accounts.isNotEmpty()
}
}
}
private fun handleSelectedBankAccountsChanged(selectedBankAccounts: List<BankAccount>) {
context?.asActivity()?.let { activity ->
activity.runOnUiThread {
updateTransactionsToDisplay()
}
}
}
private fun updateAccountsTransactions() {
presenter.updateAccountsTransactionsAsync { }
}
@ -142,15 +167,9 @@ class HomeFragment : Fragment() {
context?.asActivity()?.let { activity ->
activity.runOnUiThread {
if (response.isSuccessful) {
val allTransactions = presenter.allTransactions
transactionAdapter.items = allTransactions
mnitmSearchTransactions.isVisible = allTransactions.isNotEmpty()
mnitmUpdateTransactions.isVisible = allTransactions.isNotEmpty()
mnitmBalance.title = presenter.balanceOfAllAccounts.toString()
mnitmBalance.isVisible = true
} else {
updateTransactionsToDisplay()
}
else {
AlertDialog.Builder(activity) // TODO: may show account name in message
.setMessage(activity.getString(R.string.fragment_home_could_not_retrieve_account_transactions, response.errorToShowToUser))
.setPositiveButton(android.R.string.ok) { dialog, _ -> dialog.dismiss() }
@ -178,7 +197,9 @@ class HomeFragment : Fragment() {
private val searchAccountTransactionsTextListener: SearchView.OnQueryTextListener = object : SearchView.OnQueryTextListener {
override fun onQueryTextChange(query: String): Boolean {
searchAccountTransactions(query)
appliedTransactionsFilter = query
updateTransactionsToDisplay()
return true
}
@ -187,8 +208,13 @@ class HomeFragment : Fragment() {
}
}
private fun searchAccountTransactions(query: String) {
transactionAdapter.items = presenter.searchAccountTransactions(query)
private fun updateTransactionsToDisplay() {
transactionAdapter.items = presenter.searchSelectedAccountTransactions(appliedTransactionsFilter)
// TODO: if transactions are filtered calculate and show balance of displayed transactions?
mnitmBalance.title = presenter.balanceOfSelectedBankAccounts.toString()
mnitmBalance.isVisible = true
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 547 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 726 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 344 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 469 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 655 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 931 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 980 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<TextView
android:id="@+id/txtvwAccountName"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_toLeftOf="@+id/imgvwEditAccount"
android:layout_toStartOf="@+id/imgvwEditAccount"
android:gravity="center_vertical"
android:textColor="@color/primaryTextColor_Dark"
/>
<ImageView
android:id="@+id/imgvwEditAccount"
android:layout_width="@dimen/navigation_menu_icon_edit_account_width_and_height"
android:layout_height="@dimen/navigation_menu_icon_edit_account_width_and_height"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true"
android:layout_marginRight="@dimen/navigation_menu_icon_and_space_width"
android:layout_marginEnd="@dimen/navigation_menu_icon_and_space_width"
android:src="@drawable/ic_check_circle_white_48dp"
/>
</RelativeLayout>

View File

@ -20,6 +20,9 @@
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="@layout/nav_header_main"
app:menu="@menu/activity_main_drawer" />
app:menu="@menu/activity_main_drawer"
android:theme="@style/AppTheme.NavigationView"
android:background="@color/backgroundColor_Dark"
/>
</android.support.v4.widget.DrawerLayout>

View File

@ -27,10 +27,23 @@
android:text="@string/nav_header_title"
android:textAppearance="@style/TextAppearance.AppCompat.Body1" />
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/nav_header_subtitle" />
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/nav_header_version_label"
/>
<TextView
android:id="@+id/txtAppVersion"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
</LinearLayout>

View File

@ -1,6 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:showIn="navigation_view">
xmlns:tools="http://schemas.android.com/tools"
tools:showIn="navigation_view"
>
<item
android:id="@+id/navBankAccountsSectionItem"
android:title="@string/nav_menu_bank_accounts_section_title"
>
<menu
android:id="@+id/navBankAccountsSectionMenu"
>
<item
android:id="@+id/navAddBankAccount"
android:icon="@drawable/ic_add_white_48dp"
android:title="@string/nav_menu_add_bank_account_title"
/>
<item
android:id="@+id/navAllBankAccounts"
android:title="@string/nav_menu_all_bank_accounts_title"
android:visible="false"
/>
</menu>
</item>
</menu>

View File

@ -4,6 +4,9 @@
<dimen name="activity_vertical_margin">16dp</dimen>
<dimen name="nav_header_vertical_spacing">8dp</dimen>
<dimen name="nav_header_height">176dp</dimen>
<dimen name="navigation_menu_icon_title_space">8dp</dimen>
<dimen name="navigation_menu_icon_and_space_width">56dp</dimen>
<dimen name="navigation_menu_icon_edit_account_width_and_height">24dp</dimen>
<dimen name="fab_margin">16dp</dimen>
<dimen name="fab_margin_bottom_without_toolbar">16dp</dimen>
<dimen name="fab_margin_bottom_with_toolbar">42dp</dimen>

View File

@ -13,9 +13,12 @@
<string name="navigation_drawer_open">Open navigation drawer</string>
<string name="navigation_drawer_close">Close navigation drawer</string>
<string name="nav_header_title">Android Studio</string>
<string name="nav_header_subtitle">android.studio@android.com</string>
<string name="nav_header_title">@string/app_name</string>
<string name="nav_header_version_label">Version\u0020</string>
<string name="nav_header_desc">Navigation header</string>
<string name="nav_menu_bank_accounts_section_title">Accounts</string>
<string name="nav_menu_add_bank_account_title">Add account</string>
<string name="nav_menu_all_bank_accounts_title">All accounts</string>
<string name="floating_action_menu_add_account">Account</string>
<string name="floating_action_menu_transfer_money">Transfer money</string>

View File

@ -21,6 +21,15 @@
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
<style name="AppTheme.NavigationView">
<!-- Sets group title's text color -->
<item name="android:textColorSecondary">@color/primaryTextColor_Dark</item>
<!-- Sets menu items' text color -->
<item name="itemTextColor">@color/primaryTextColor_Dark</item>
<item name="itemIconTint">@color/primaryTextColor_Dark</item>
<item name="itemIconPadding">@dimen/navigation_menu_icon_title_space</item>
</style>
<!-- Floating Action Button -->