Implemented Navigation side bar to show and select bank accounts
|
@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
}
|
After Width: | Height: | Size: 547 B |
After Width: | Height: | Size: 726 B |
After Width: | Height: | Size: 344 B |
After Width: | Height: | Size: 469 B |
After Width: | Height: | Size: 655 B |
After Width: | Height: | Size: 931 B |
After Width: | Height: | Size: 980 B |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.8 KiB |
|
@ -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>
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 -->
|
||||
|
||||
|
|