From 135cb1054af57499c09f4fad74a161b8d270e90e Mon Sep 17 00:00:00 2001 From: Mariotaku Lee Date: Mon, 5 Dec 2016 11:39:22 +0800 Subject: [PATCH] improved account dashboard selector --- .../twidere/model/AccountDetails.java | 21 +- .../v7/widget/RecyclerViewAccessor.java | 11 + .../twidere/model/util/AccountUtils.java | 11 +- .../twidere/activity/HomeActivity.kt | 5 +- .../fragment/AccountsDashboardFragment.kt | 471 +++++++++--------- .../layout/adapter_item_dashboard_account.xml | 2 +- .../layout/header_drawer_account_selector.xml | 4 +- 7 files changed, 257 insertions(+), 268 deletions(-) create mode 100644 twidere/src/main/java/android/support/v7/widget/RecyclerViewAccessor.java diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/model/AccountDetails.java b/twidere.component.common/src/main/java/org/mariotaku/twidere/model/AccountDetails.java index 5960e08d5..68813dbf8 100644 --- a/twidere.component.common/src/main/java/org/mariotaku/twidere/model/AccountDetails.java +++ b/twidere.component.common/src/main/java/org/mariotaku/twidere/model/AccountDetails.java @@ -17,7 +17,7 @@ import org.mariotaku.twidere.model.account.cred.Credentials; */ @ParcelablePlease -public class AccountDetails implements Parcelable { +public class AccountDetails implements Parcelable, Comparable { public boolean dummy; public Account account; @@ -61,6 +61,18 @@ public class AccountDetails implements Parcelable { '}'; } + @Override + public int compareTo(@NonNull AccountDetails that) { + return this.position - that.position; + } + + @NonNull + public static AccountDetails dummy() { + AccountDetails dummy = new AccountDetails(); + dummy.dummy = true; + return dummy; + } + public static final Creator CREATOR = new Creator() { public AccountDetails createFromParcel(Parcel source) { AccountDetails target = new AccountDetails(); @@ -72,11 +84,4 @@ public class AccountDetails implements Parcelable { return new AccountDetails[size]; } }; - - @NonNull - public static AccountDetails dummy() { - AccountDetails dummy = new AccountDetails(); - dummy.dummy = true; - return dummy; - } } diff --git a/twidere/src/main/java/android/support/v7/widget/RecyclerViewAccessor.java b/twidere/src/main/java/android/support/v7/widget/RecyclerViewAccessor.java new file mode 100644 index 000000000..a00823074 --- /dev/null +++ b/twidere/src/main/java/android/support/v7/widget/RecyclerViewAccessor.java @@ -0,0 +1,11 @@ +package android.support.v7.widget; + +/** + * Created by mariotaku on 2016/12/5. + */ + +public class RecyclerViewAccessor { + public static void setLayoutPosition(RecyclerView.ViewHolder holder, int position) { + holder.mPreLayoutPosition = position; + } +} diff --git a/twidere/src/main/java/org/mariotaku/twidere/model/util/AccountUtils.java b/twidere/src/main/java/org/mariotaku/twidere/model/util/AccountUtils.java index 5c7070700..b53187eb9 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/model/util/AccountUtils.java +++ b/twidere/src/main/java/org/mariotaku/twidere/model/util/AccountUtils.java @@ -14,6 +14,8 @@ import org.mariotaku.twidere.model.AccountDetails; import org.mariotaku.twidere.model.UserKey; import org.mariotaku.twidere.model.account.cred.Credentials; +import java.util.Arrays; + import static org.mariotaku.twidere.TwidereConstants.ACCOUNT_TYPE; /** @@ -42,6 +44,7 @@ public class AccountUtils { for (int i = 0; i < accounts.length; i++) { details[i] = getAccountDetails(am, accounts[i]); } + Arrays.sort(details); return details; } @@ -50,16 +53,12 @@ public class AccountUtils { for (int i = 0; i < accountKeys.length; i++) { details[i] = getAccountDetails(am, accountKeys[i]); } + Arrays.sort(details); return details; } public static AccountDetails[] getAllAccountDetails(@NonNull AccountManager am) { - Account[] accounts = getAccounts(am); - AccountDetails[] details = new AccountDetails[accounts.length]; - for (int i = 0; i < accounts.length; i++) { - details[i] = getAccountDetails(am, accounts[i]); - } - return details; + return getAllAccountDetails(am, getAccounts(am)); } @Nullable diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/activity/HomeActivity.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/activity/HomeActivity.kt index 32d4001da..f3edaabfc 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/activity/HomeActivity.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/activity/HomeActivity.kt @@ -757,10 +757,7 @@ class HomeActivity : BaseActivity(), OnClickListener, OnPageChangeListener, Supp homeMenu.setShouldDisableDecider(HomeDrawerLayout.ShouldDisableDecider { e -> val fragment = leftDrawerFragment if (fragment is AccountsDashboardFragment) { - val accountsSelector = fragment.accountsSelector - if (accountsSelector != null) { - return@ShouldDisableDecider TwidereViewUtils.hitView(e.rawX, e.rawY, accountsSelector) - } + return@ShouldDisableDecider fragment.shouldDisableDrawerSlide(e) } false }) diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/AccountsDashboardFragment.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/AccountsDashboardFragment.kt index eb0e99ea7..78cb3b494 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/AccountsDashboardFragment.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/AccountsDashboardFragment.kt @@ -40,12 +40,14 @@ import android.support.v4.app.LoaderManager.LoaderCallbacks import android.support.v4.content.AsyncTaskLoader import android.support.v4.content.Loader import android.support.v4.view.MenuItemCompat +import android.support.v4.view.PagerAdapter +import android.support.v4.view.ViewPager import android.support.v7.view.SupportMenuInflater import android.support.v7.widget.ActionMenuView.OnMenuItemClickListener import android.support.v7.widget.FixedLinearLayoutManager import android.support.v7.widget.LinearLayoutManager -import android.support.v7.widget.RecyclerView.Adapter import android.support.v7.widget.RecyclerView.ViewHolder +import android.support.v7.widget.RecyclerViewAccessor import android.view.* import android.view.View.OnClickListener import android.view.animation.DecelerateInterpolator @@ -81,11 +83,9 @@ class AccountsDashboardFragment : BaseSupportFragment(), LoaderCallbacks - get() { - if (mAccountActionProvider != null) { - return mAccountActionProvider!!.activatedAccountIds - } - return DataStoreUtils.getActivatedAccountKeys(activity) - } - - override fun handleKeyboardShortcutSingle(handler: KeyboardShortcutsHandler, - keyCode: Int, event: KeyEvent, metaState: Int): Boolean { - return false - } - - override fun isKeyboardShortcutHandled(handler: KeyboardShortcutsHandler, keyCode: Int, event: KeyEvent, metaState: Int): Boolean { - val action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event, metaState) - return ACTION_NAVIGATION_PREVIOUS == action || ACTION_NAVIGATION_NEXT == action - } - - override fun handleKeyboardShortcutRepeat(handler: KeyboardShortcutsHandler, - keyCode: Int, repeatCount: Int, - event: KeyEvent, metaState: Int): Boolean { - val action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event, metaState) ?: return false - val offset: Int - when (action) { - ACTION_NAVIGATION_PREVIOUS -> { - offset = -1 - } - ACTION_NAVIGATION_NEXT -> { - offset = 1 - } - else -> { - return false - } - } - // final int selectedItem = mNavigationView.getSelectedItemPosition(); - // final int count = mNavigationView.getCount(); - // int resultPosition; - // if (!mNavigationView.isFocused() || selectedItem == ListView.INVALID_POSITION) { - // resultPosition = firstVisiblePosition; - // } else { - // resultPosition = selectedItem + offset; - // while (resultPosition >= 0 && resultPosition < count && !mAdapter.isEnabled(resultPosition)) { - // resultPosition += offset; - // } - // } - // final View focusedChild = mNavigationView.getFocusedChild(); - // if (focusedChild == null) { - // mNavigationView.requestChildFocus(mNavigationView.getChildAt(0), null); - // } - // if (resultPosition >= 0 && resultPosition < count) { - // mNavigationView.setSelection(resultPosition); - // } - return true - } - - override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - when (requestCode) { - REQUEST_SETTINGS -> { - if (data == null) return - if (data.getBooleanExtra(EXTRA_SHOULD_RESTART, false)) { - Utils.restartActivity(activity) - } else if (data.getBooleanExtra(EXTRA_SHOULD_RECREATE, false)) { - activity.recreate() - } - return - } - } - super.onActivityResult(requestCode, resultCode, data) - } - - override fun onResume() { - super.onResume() - updateDefaultAccountState() - } - - override fun onClick(v: View) { - when (v.id) { - R.id.profileContainer -> { - val account = mAccountsAdapter!!.selectedAccount ?: return - val activity = activity - if (account.user != null) { - IntentUtils.openUserProfile(activity, account.user!!, null, - preferences.getBoolean(KEY_NEW_DOCUMENT_API), - Referral.SELF_PROFILE) - } else { - IntentUtils.openUserProfile(activity, account.key, account.key, - account.user.screen_name, null, - preferences.getBoolean(KEY_NEW_DOCUMENT_API), - Referral.SELF_PROFILE) - } - } - } - } - - override fun onCreateLoader(id: Int, args: Bundle?): Loader { - return AccountsInfoLoader(activity) - } - - override fun onLoadFinished(loader: Loader, data: AccountsInfo) { - updateAccountProviderData(data) - } - - private fun updateAccountProviderData(data: AccountsInfo) { - val menu = accountDashboardMenu.menu - mAccountActionProvider = MenuItemCompat.getActionProvider(menu.findItem(R.id.select_account)) as AccountToggleProvider - val accounts = data.accounts - if (accounts.isNotEmpty()) { - noAccountContainer.visibility = View.GONE - profileContainer.visibility = View.VISIBLE - } else { - noAccountContainer.visibility = View.VISIBLE - profileContainer.visibility = View.INVISIBLE - } - var defaultId: UserKey? = null - for (account in accounts) { - if (account.activated) { - defaultId = account.key - break - } - } - mUseStarsForLikes = preferences.getBoolean(KEY_I_WANT_MY_STARS_BACK) - - mAccountsAdapter!!.accounts = accounts - var accountKey = preferences.getString(KEY_DEFAULT_ACCOUNT_KEY, null)?.convert(UserKey::valueOf) - if (accountKey == null) { - accountKey = defaultId - } - var selectedAccount: AccountDetails? = null - for (account in accounts) { - if (account.key.maybeEquals(accountKey)) { - selectedAccount = account - break - } - } - mAccountsAdapter!!.selectedAccount = selectedAccount - - if (mAccountActionProvider != null) { - mAccountActionProvider!!.isExclusive = false - mAccountActionProvider!!.accounts = accounts - } - updateAccountActions() - val currentAccount = mAccountsAdapter!!.selectedAccount - if (currentAccount != null) { - displayAccountBanner(currentAccount) - displayCurrentAccount(null) - } - updateDefaultAccountState() - - if (data.draftsCount > 0) { - navigationView.menu.findItem(R.id.drafts).title = "${getString(R.string.drafts)} (${data.draftsCount})" - } else { - navigationView.menu.findItem(R.id.drafts).title = getString(R.string.drafts) - } - } - - override fun onLoaderReset(loader: Loader) { - } - - - override fun onSharedPreferenceChanged(preferences: SharedPreferences, key: String) { - if (KEY_DEFAULT_ACCOUNT_KEY == key) { - updateDefaultAccountState() - } - } - - override fun fitSystemWindows(insets: Rect) { - mSystemWindowsInsets.set(insets) - updateSystemWindowsInsets() - } - - private fun updateSystemWindowsInsets() { - } + private var switchAccountAnimationPlaying: Boolean = false + private var useStarsForLikes: Boolean = false + private var loaderInitialized: Boolean = false override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) mResolver = contentResolver val inflater = getLayoutInflater(savedInstanceState) - mAccountsAdapter = AccountSelectorAdapter(inflater, this) + accountsAdapter = AccountSelectorAdapter(inflater, this) val layoutManager = FixedLinearLayoutManager(context) layoutManager.orientation = LinearLayoutManager.HORIZONTAL layoutManager.stackFromEnd = true - accountsSelector.layoutManager = layoutManager - accountsSelector.adapter = mAccountsAdapter - accountsSelector.itemAnimator = null + accountsSelector.adapter = accountsAdapter + accountsSelector.setPageTransformer(false, AccountsSelectorTransformer) val menuInflater = SupportMenuInflater(context) menuInflater.inflate(R.menu.action_dashboard_timeline_toggle, accountDashboardMenu.menu) accountDashboardMenu.setOnMenuItemClickListener(OnMenuItemClickListener { item -> if (item.groupId != AccountToggleProvider.MENU_GROUP) { when (item.itemId) { R.id.compose -> { - val account = mAccountsAdapter!!.selectedAccount ?: return@OnMenuItemClickListener true + val account = accountsAdapter!!.selectedAccount ?: return@OnMenuItemClickListener true val composeIntent = Intent(INTENT_ACTION_COMPOSE) composeIntent.setClass(activity, ComposeActivity::class.java) composeIntent.putExtra(EXTRA_ACCOUNT_KEY, account.key) @@ -303,11 +129,11 @@ class AccountsDashboardFragment : BaseSupportFragment(), LoaderCallbacks { + if (data == null) return + if (data.getBooleanExtra(EXTRA_SHOULD_RESTART, false)) { + Utils.restartActivity(activity) + } else if (data.getBooleanExtra(EXTRA_SHOULD_RECREATE, false)) { + activity.recreate() + } + return + } + } + super.onActivityResult(requestCode, resultCode, data) + } + + override fun handleKeyboardShortcutSingle(handler: KeyboardShortcutsHandler, + keyCode: Int, event: KeyEvent, metaState: Int): Boolean { + return false + } + + override fun isKeyboardShortcutHandled(handler: KeyboardShortcutsHandler, keyCode: Int, event: KeyEvent, metaState: Int): Boolean { + val action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event, metaState) + return ACTION_NAVIGATION_PREVIOUS == action || ACTION_NAVIGATION_NEXT == action + } + + override fun handleKeyboardShortcutRepeat(handler: KeyboardShortcutsHandler, keyCode: Int, + repeatCount: Int, event: KeyEvent, metaState: Int): Boolean { + return true + } + + override fun onClick(v: View) { + when (v.id) { + R.id.profileContainer -> { + val account = accountsAdapter!!.selectedAccount ?: return + val activity = activity + if (account.user != null) { + IntentUtils.openUserProfile(activity, account.user!!, null, + preferences.getBoolean(KEY_NEW_DOCUMENT_API), + Referral.SELF_PROFILE) + } else { + IntentUtils.openUserProfile(activity, account.key, account.key, + account.user.screen_name, null, + preferences.getBoolean(KEY_NEW_DOCUMENT_API), + Referral.SELF_PROFILE) + } + } + } + } + + override fun onCreateLoader(id: Int, args: Bundle?): Loader { + return AccountsInfoLoader(activity) + } + + + override fun onLoadFinished(loader: Loader, data: AccountsInfo) { + updateAccountProviderData(data) + } + + private fun updateAccountProviderData(data: AccountsInfo) { + val menu = accountDashboardMenu.menu + accountActionProvider = MenuItemCompat.getActionProvider(menu.findItem(R.id.select_account)) as AccountToggleProvider + val accounts = data.accounts + if (accounts.isNotEmpty()) { + noAccountContainer.visibility = View.GONE + profileContainer.visibility = View.VISIBLE + } else { + noAccountContainer.visibility = View.VISIBLE + profileContainer.visibility = View.INVISIBLE + } + var defaultId: UserKey? = null + for (account in accounts) { + if (account.activated) { + defaultId = account.key + break + } + } + useStarsForLikes = preferences.getBoolean(KEY_I_WANT_MY_STARS_BACK) + + accountsAdapter!!.accounts = accounts + var accountKey = preferences.getString(KEY_DEFAULT_ACCOUNT_KEY, null)?.convert(UserKey::valueOf) + if (accountKey == null) { + accountKey = defaultId + } + var selectedAccount: AccountDetails? = null + for (account in accounts) { + if (account.key.maybeEquals(accountKey)) { + selectedAccount = account + break + } + } + accountsAdapter!!.selectedAccount = selectedAccount + + if (accountActionProvider != null) { + accountActionProvider!!.isExclusive = false + accountActionProvider!!.accounts = accounts + } + updateAccountActions() + val currentAccount = accountsAdapter!!.selectedAccount + if (currentAccount != null) { + displayAccountBanner(currentAccount) + displayCurrentAccount(null) + } + updateDefaultAccountState() + + if (data.draftsCount > 0) { + navigationView.menu.findItem(R.id.drafts).title = "${getString(R.string.drafts)} (${data.draftsCount})" + } else { + navigationView.menu.findItem(R.id.drafts).title = getString(R.string.drafts) + } + } + + override fun onLoaderReset(loader: Loader) { + } + + override fun onSharedPreferenceChanged(preferences: SharedPreferences, key: String) { + if (KEY_DEFAULT_ACCOUNT_KEY == key) { + updateDefaultAccountState() + } + } + + override fun fitSystemWindows(insets: Rect) { + mSystemWindowsInsets.set(insets) + updateSystemWindowsInsets() + } + + private fun updateSystemWindowsInsets() { + } + + fun loadAccounts() { + if (!loaderInitialized) { + loaderInitialized = true + loaderManager.initLoader(0, null, this) + } else { + loaderManager.restartLoader(0, null, this) + } + } + internal fun updateAccountActions() { val activity = activity as HomeActivity val tabs = activity.tabs - val account = mAccountsAdapter!!.selectedAccount ?: return + val account = accountsAdapter!!.selectedAccount ?: return var hasDmTab = false var hasInteractionsTab = false for (tab in tabs) { @@ -379,7 +338,7 @@ class AccountsDashboardFragment : BaseSupportFragment(), LoaderCallbacks { val intent = Intent(activity, QuickSearchBarActivity::class.java) @@ -615,7 +572,13 @@ class AccountsDashboardFragment : BaseSupportFragment(), LoaderCallbacks() { + ) : PagerAdapter() { private val mediaLoader: MediaLoaderWrapper + var accounts: Array? = null set(value) { if (value != null) { @@ -659,22 +624,15 @@ class AccountsDashboardFragment : BaseSupportFragment(), LoaderCallbacks(context) { - private var contentObserver: ContentObserver? = null + private var firstLoad: Boolean init { @@ -797,5 +757,20 @@ class AccountsDashboardFragment : BaseSupportFragment(), LoaderCallbacks 2f / 3) { + page.alpha = (1 - position) * 3 + } else { + page.alpha = 1f + } + } + + } + +} diff --git a/twidere/src/main/res/layout/adapter_item_dashboard_account.xml b/twidere/src/main/res/layout/adapter_item_dashboard_account.xml index e58be51d8..c7feea63f 100644 --- a/twidere/src/main/res/layout/adapter_item_dashboard_account.xml +++ b/twidere/src/main/res/layout/adapter_item_dashboard_account.xml @@ -23,7 +23,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="wrap_content" android:layout_height="match_parent" - android:layout_margin="@dimen/element_spacing_msmall" + android:padding="@dimen/element_spacing_msmall" tools:layout_height="48dp"> -