redesigned account selector
This commit is contained in:
parent
72aaf3a887
commit
8ad206a9c8
|
@ -25,6 +25,7 @@ import android.graphics.Color;
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
import org.mariotaku.querybuilder.Columns.Column;
|
import org.mariotaku.querybuilder.Columns.Column;
|
||||||
import org.mariotaku.querybuilder.Expression;
|
import org.mariotaku.querybuilder.Expression;
|
||||||
|
@ -144,24 +145,37 @@ public class ParcelableAccount implements Parcelable {
|
||||||
return list.toArray(new ParcelableAccount[list.size()]);
|
return list.toArray(new ParcelableAccount[list.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ParcelableAccount[] getAccounts(final Context context, final long[] accountIds) {
|
@NonNull
|
||||||
|
public static ParcelableAccount[] getAccounts(@Nullable final Context context, @Nullable final long[] accountIds) {
|
||||||
if (context == null) return new ParcelableAccount[0];
|
if (context == null) return new ParcelableAccount[0];
|
||||||
final String where = accountIds != null ? Expression.in(new Column(Accounts.ACCOUNT_ID),
|
final String where = accountIds != null ? Expression.in(new Column(Accounts.ACCOUNT_ID),
|
||||||
new RawItemArray(accountIds)).getSQL() : null;
|
new RawItemArray(accountIds)).getSQL() : null;
|
||||||
final Cursor cur = ContentResolverUtils.query(context.getContentResolver(), Accounts.CONTENT_URI,
|
final Cursor cur = ContentResolverUtils.query(context.getContentResolver(), Accounts.CONTENT_URI,
|
||||||
Accounts.COLUMNS_NO_CREDENTIALS, where, null, null);
|
Accounts.COLUMNS_NO_CREDENTIALS, where, null, null);
|
||||||
if (cur == null) return new ParcelableAccount[0];
|
if (cur == null) return new ParcelableAccount[0];
|
||||||
|
return getAccounts(cur, new Indices(cur));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public static ParcelableAccount[] getAccounts(@Nullable final Cursor cursor) {
|
||||||
|
if (cursor == null) return new ParcelableAccount[0];
|
||||||
|
return getAccounts(cursor, new Indices(cursor));
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public static ParcelableAccount[] getAccounts(@Nullable final Cursor cursor,@Nullable final Indices indices) {
|
||||||
|
if (cursor == null || indices == null) return new ParcelableAccount[0];
|
||||||
try {
|
try {
|
||||||
final Indices idx = new Indices(cur);
|
cursor.moveToFirst();
|
||||||
cur.moveToFirst();
|
final ParcelableAccount[] names = new ParcelableAccount[cursor.getCount()];
|
||||||
final ParcelableAccount[] names = new ParcelableAccount[cur.getCount()];
|
while (!cursor.isAfterLast()) {
|
||||||
while (!cur.isAfterLast()) {
|
names[cursor.getPosition()] = new ParcelableAccount(cursor, indices);
|
||||||
names[cur.getPosition()] = new ParcelableAccount(cur, idx);
|
cursor.moveToNext();
|
||||||
cur.moveToNext();
|
|
||||||
}
|
}
|
||||||
return names;
|
return names;
|
||||||
} finally {
|
} finally {
|
||||||
cur.close();
|
cursor.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,10 @@
|
||||||
|
|
||||||
package org.mariotaku.twidere.fragment.support;
|
package org.mariotaku.twidere.fragment.support;
|
||||||
|
|
||||||
|
import android.animation.Animator;
|
||||||
|
import android.animation.Animator.AnimatorListener;
|
||||||
|
import android.animation.AnimatorSet;
|
||||||
|
import android.animation.ObjectAnimator;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.ContentResolver;
|
import android.content.ContentResolver;
|
||||||
import android.content.ContentValues;
|
import android.content.ContentValues;
|
||||||
|
@ -29,13 +33,18 @@ import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.Matrix;
|
||||||
import android.graphics.PorterDuff.Mode;
|
import android.graphics.PorterDuff.Mode;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
|
import android.graphics.RectF;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v4.app.FragmentActivity;
|
import android.support.v4.app.FragmentActivity;
|
||||||
import android.support.v4.app.LoaderManager.LoaderCallbacks;
|
import android.support.v4.app.LoaderManager.LoaderCallbacks;
|
||||||
import android.support.v4.content.CursorLoader;
|
import android.support.v4.content.CursorLoader;
|
||||||
import android.support.v4.content.Loader;
|
import android.support.v4.content.Loader;
|
||||||
|
import android.support.v4.content.res.ResourcesCompat;
|
||||||
|
import android.support.v4.util.LongSparseArray;
|
||||||
import android.support.v4.util.Pair;
|
import android.support.v4.util.Pair;
|
||||||
import android.support.v4.view.MenuItemCompat;
|
import android.support.v4.view.MenuItemCompat;
|
||||||
import android.support.v7.internal.view.SupportMenuInflater;
|
import android.support.v7.internal.view.SupportMenuInflater;
|
||||||
|
@ -52,6 +61,7 @@ import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.View.OnClickListener;
|
import android.view.View.OnClickListener;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.view.animation.DecelerateInterpolator;
|
||||||
import android.widget.CompoundButton;
|
import android.widget.CompoundButton;
|
||||||
import android.widget.CompoundButton.OnCheckedChangeListener;
|
import android.widget.CompoundButton.OnCheckedChangeListener;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
|
@ -78,17 +88,19 @@ import org.mariotaku.twidere.adapter.ArrayAdapter;
|
||||||
import org.mariotaku.twidere.app.TwidereApplication;
|
import org.mariotaku.twidere.app.TwidereApplication;
|
||||||
import org.mariotaku.twidere.menu.SupportAccountActionProvider;
|
import org.mariotaku.twidere.menu.SupportAccountActionProvider;
|
||||||
import org.mariotaku.twidere.model.ParcelableAccount;
|
import org.mariotaku.twidere.model.ParcelableAccount;
|
||||||
import org.mariotaku.twidere.model.ParcelableAccount.Indices;
|
|
||||||
import org.mariotaku.twidere.provider.TwidereDataStore.Accounts;
|
import org.mariotaku.twidere.provider.TwidereDataStore.Accounts;
|
||||||
import org.mariotaku.twidere.util.CompareUtils;
|
import org.mariotaku.twidere.util.CompareUtils;
|
||||||
import org.mariotaku.twidere.util.ImageLoaderWrapper;
|
import org.mariotaku.twidere.util.ImageLoaderWrapper;
|
||||||
import org.mariotaku.twidere.util.ThemeUtils;
|
import org.mariotaku.twidere.util.ThemeUtils;
|
||||||
|
import org.mariotaku.twidere.util.TransitionUtils;
|
||||||
import org.mariotaku.twidere.util.Utils;
|
import org.mariotaku.twidere.util.Utils;
|
||||||
import org.mariotaku.twidere.util.content.SupportFragmentReloadCursorObserver;
|
import org.mariotaku.twidere.util.content.SupportFragmentReloadCursorObserver;
|
||||||
import org.mariotaku.twidere.view.ShapedImageView;
|
import org.mariotaku.twidere.view.ShapedImageView;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import static org.mariotaku.twidere.util.Utils.openUserFavorites;
|
import static org.mariotaku.twidere.util.Utils.openUserFavorites;
|
||||||
|
@ -114,6 +126,7 @@ public class AccountsDashboardFragment extends BaseSupportListFragment implement
|
||||||
private View mAccountSelectorView;
|
private View mAccountSelectorView;
|
||||||
private RecyclerView mAccountsSelector;
|
private RecyclerView mAccountsSelector;
|
||||||
private ImageView mAccountProfileBannerView;
|
private ImageView mAccountProfileBannerView;
|
||||||
|
private ImageView mFloatingProfileImageSnapshotView;
|
||||||
private ShapedImageView mAccountProfileImageView;
|
private ShapedImageView mAccountProfileImageView;
|
||||||
private TextView mAccountProfileNameView, mAccountProfileScreenNameView;
|
private TextView mAccountProfileNameView, mAccountProfileScreenNameView;
|
||||||
private ActionMenuView mAccountsToggleMenu;
|
private ActionMenuView mAccountsToggleMenu;
|
||||||
|
@ -122,6 +135,7 @@ public class AccountsDashboardFragment extends BaseSupportListFragment implement
|
||||||
private Context mThemedContext;
|
private Context mThemedContext;
|
||||||
private ImageLoaderWrapper mImageLoader;
|
private ImageLoaderWrapper mImageLoader;
|
||||||
private SupportAccountActionProvider mAccountActionProvider;
|
private SupportAccountActionProvider mAccountActionProvider;
|
||||||
|
private boolean mSwitchAccountAnimationPlaying;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
|
public void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
|
||||||
|
@ -180,38 +194,30 @@ public class AccountsDashboardFragment extends BaseSupportListFragment implement
|
||||||
final Menu menu = mAccountsToggleMenu.getMenu();
|
final Menu menu = mAccountsToggleMenu.getMenu();
|
||||||
mAccountActionProvider = (SupportAccountActionProvider) MenuItemCompat.getActionProvider(menu.findItem(MENU_SELECT_ACCOUNT));
|
mAccountActionProvider = (SupportAccountActionProvider) MenuItemCompat.getActionProvider(menu.findItem(MENU_SELECT_ACCOUNT));
|
||||||
mAccountActionProvider.setExclusive(false);
|
mAccountActionProvider.setExclusive(false);
|
||||||
final ArrayList<ParcelableAccount> accounts = new ArrayList<>();
|
final ParcelableAccount[] accounts = ParcelableAccount.getAccounts(data);
|
||||||
final Set<Long> activatedIds = new HashSet<>();
|
final Set<Long> activatedIds = new HashSet<>();
|
||||||
if (data != null) {
|
|
||||||
data.moveToFirst();
|
|
||||||
final Indices indices = new Indices(data);
|
|
||||||
long defaultId = -1;
|
long defaultId = -1;
|
||||||
while (!data.isAfterLast()) {
|
for (ParcelableAccount account : accounts) {
|
||||||
final ParcelableAccount account = new ParcelableAccount(data, indices);
|
|
||||||
accounts.add(account);
|
|
||||||
if (account.is_activated) {
|
if (account.is_activated) {
|
||||||
if (defaultId < 0) {
|
if (defaultId < 0) {
|
||||||
defaultId = account.account_id;
|
defaultId = account.account_id;
|
||||||
}
|
}
|
||||||
activatedIds.add(account.account_id);
|
activatedIds.add(account.account_id);
|
||||||
}
|
}
|
||||||
data.moveToNext();
|
|
||||||
}
|
}
|
||||||
|
mAccountsAdapter.setAccounts(accounts);
|
||||||
if (mAccountsAdapter.getSelectedAccountId() <= 0) {
|
if (mAccountsAdapter.getSelectedAccountId() <= 0) {
|
||||||
mAccountsAdapter.setSelectedAccountId(mPreferences.getLong(KEY_DEFAULT_ACCOUNT_ID, defaultId));
|
mAccountsAdapter.setSelectedAccountId(mPreferences.getLong(KEY_DEFAULT_ACCOUNT_ID, defaultId));
|
||||||
}
|
}
|
||||||
}
|
mAccountActionProvider.setAccounts(accounts);
|
||||||
mAccountActionProvider.setAccounts(accounts.toArray(new ParcelableAccount[accounts.size()]));
|
|
||||||
mAccountActionProvider.setSelectedAccountIds(ArrayUtils.toPrimitive(activatedIds.toArray(new Long[activatedIds.size()])));
|
mAccountActionProvider.setSelectedAccountIds(ArrayUtils.toPrimitive(activatedIds.toArray(new Long[activatedIds.size()])));
|
||||||
|
|
||||||
mAccountsAdapter.changeCursor(data);
|
updateAccountOptionsSeparatorLabel(null);
|
||||||
updateAccountOptionsSeparatorLabel();
|
|
||||||
updateDefaultAccountState();
|
updateDefaultAccountState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLoaderReset(final Loader<Cursor> loader) {
|
public void onLoaderReset(final Loader<Cursor> loader) {
|
||||||
mAccountsAdapter.changeCursor(null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -345,9 +351,11 @@ public class AccountsDashboardFragment extends BaseSupportListFragment implement
|
||||||
layoutManager.setStackFromEnd(true);
|
layoutManager.setStackFromEnd(true);
|
||||||
mAccountsSelector.setLayoutManager(layoutManager);
|
mAccountsSelector.setLayoutManager(layoutManager);
|
||||||
mAccountsSelector.setAdapter(mAccountsAdapter);
|
mAccountsSelector.setAdapter(mAccountsAdapter);
|
||||||
|
mAccountsSelector.setItemAnimator(null);
|
||||||
mAccountProfileContainer = mAccountSelectorView.findViewById(R.id.profile_container);
|
mAccountProfileContainer = mAccountSelectorView.findViewById(R.id.profile_container);
|
||||||
mAccountProfileImageView = (ShapedImageView) mAccountSelectorView.findViewById(R.id.profile_image);
|
mAccountProfileImageView = (ShapedImageView) mAccountSelectorView.findViewById(R.id.profile_image);
|
||||||
mAccountProfileBannerView = (ImageView) mAccountSelectorView.findViewById(R.id.account_profile_banner);
|
mAccountProfileBannerView = (ImageView) mAccountSelectorView.findViewById(R.id.account_profile_banner);
|
||||||
|
mFloatingProfileImageSnapshotView = (ImageView) mAccountSelectorView.findViewById(R.id.floating_profile_image_snapshot);
|
||||||
mAccountProfileNameView = (TextView) mAccountSelectorView.findViewById(R.id.name);
|
mAccountProfileNameView = (TextView) mAccountSelectorView.findViewById(R.id.name);
|
||||||
mAccountProfileScreenNameView = (TextView) mAccountSelectorView.findViewById(R.id.screen_name);
|
mAccountProfileScreenNameView = (TextView) mAccountSelectorView.findViewById(R.id.screen_name);
|
||||||
mAccountsToggleMenu = (ActionMenuView) mAccountSelectorView.findViewById(R.id.toggle_menu);
|
mAccountsToggleMenu = (ActionMenuView) mAccountSelectorView.findViewById(R.id.toggle_menu);
|
||||||
|
@ -412,19 +420,102 @@ public class AccountsDashboardFragment extends BaseSupportListFragment implement
|
||||||
return mThemedContext = new ContextThemeWrapper(context, themeResource);
|
return mThemedContext = new ContextThemeWrapper(context, themeResource);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onAccountSelected(ParcelableAccount account) {
|
private void onAccountSelected(AccountProfileImageViewHolder holder, final ParcelableAccount account) {
|
||||||
mAccountsAdapter.setSelectedAccountId(account.account_id);
|
if (mSwitchAccountAnimationPlaying) return;
|
||||||
updateAccountOptionsSeparatorLabel();
|
final ImageView snapshotView = mFloatingProfileImageSnapshotView;
|
||||||
|
final ShapedImageView profileImageView = mAccountProfileImageView;
|
||||||
|
final ShapedImageView clickedImageView = holder.getIconView();
|
||||||
|
final Matrix matrix = new Matrix();
|
||||||
|
final Rect tempRect = new Rect();
|
||||||
|
clickedImageView.getGlobalVisibleRect(tempRect);
|
||||||
|
final RectF sourceBounds = new RectF(tempRect);
|
||||||
|
profileImageView.getGlobalVisibleRect(tempRect);
|
||||||
|
final RectF destBounds = new RectF(tempRect);
|
||||||
|
final float finalScale = destBounds.width() / sourceBounds.width();
|
||||||
|
final Bitmap snapshotBitmap = TransitionUtils.createViewBitmap(clickedImageView, matrix,
|
||||||
|
new RectF(0, 0, sourceBounds.width(), sourceBounds.height()));
|
||||||
|
final ViewGroup.LayoutParams lp = snapshotView.getLayoutParams();
|
||||||
|
lp.width = clickedImageView.getWidth();
|
||||||
|
lp.height = clickedImageView.getHeight();
|
||||||
|
snapshotView.setLayoutParams(lp);
|
||||||
|
// Copied from MaterialNavigationDrawer: https://github.com/madcyph3r/AdvancedMaterialDrawer/
|
||||||
|
AnimatorSet set = new AnimatorSet();
|
||||||
|
snapshotView.setPivotX(0);
|
||||||
|
snapshotView.setPivotY(0);
|
||||||
|
snapshotView.setX(sourceBounds.left);
|
||||||
|
snapshotView.setY(sourceBounds.top);
|
||||||
|
set.play(ObjectAnimator.ofFloat(snapshotView, View.X, sourceBounds.left, destBounds.left))
|
||||||
|
.with(ObjectAnimator.ofFloat(snapshotView, View.Y, sourceBounds.top, destBounds.top))
|
||||||
|
.with(ObjectAnimator.ofFloat(snapshotView, View.SCALE_X, 1, finalScale))
|
||||||
|
.with(ObjectAnimator.ofFloat(snapshotView, View.SCALE_Y, 1, finalScale))
|
||||||
|
.with(ObjectAnimator.ofFloat(profileImageView, View.ALPHA, 1, 0))
|
||||||
|
.with(ObjectAnimator.ofFloat(clickedImageView, View.SCALE_X, 0, 1))
|
||||||
|
.with(ObjectAnimator.ofFloat(clickedImageView, View.SCALE_Y, 0, 1));
|
||||||
|
final long animationTransition = 400;
|
||||||
|
set.setDuration(animationTransition);
|
||||||
|
set.setInterpolator(new DecelerateInterpolator());
|
||||||
|
set.addListener(new AnimatorListener() {
|
||||||
|
|
||||||
|
private Drawable clickedDrawable;
|
||||||
|
private int[] clickedColors;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAnimationStart(Animator animation) {
|
||||||
|
snapshotView.setVisibility(View.VISIBLE);
|
||||||
|
snapshotView.setImageBitmap(snapshotBitmap);
|
||||||
|
final Drawable profileDrawable = profileImageView.getDrawable();
|
||||||
|
clickedDrawable = clickedImageView.getDrawable();
|
||||||
|
clickedColors = clickedImageView.getBorderColors();
|
||||||
|
final ParcelableAccount oldSelectedAccount = mAccountsAdapter.getSelectedAccount();
|
||||||
|
mImageLoader.displayDashboardProfileImage(clickedImageView,
|
||||||
|
oldSelectedAccount.profile_image_url, profileDrawable);
|
||||||
|
// mImageLoader.displayDashboardProfileImage(profileImageView,
|
||||||
|
// account.profile_image_url, clickedDrawable);
|
||||||
|
clickedImageView.setBorderColors(profileImageView.getBorderColors());
|
||||||
|
mSwitchAccountAnimationPlaying = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateAccountOptionsSeparatorLabel() {
|
@Override
|
||||||
|
public void onAnimationEnd(Animator animation) {
|
||||||
|
finishAnimation();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void finishAnimation() {
|
||||||
|
mAccountsAdapter.setSelectedAccountId(account.account_id);
|
||||||
|
updateAccountOptionsSeparatorLabel(clickedDrawable);
|
||||||
|
snapshotView.setVisibility(View.INVISIBLE);
|
||||||
|
snapshotView.setImageDrawable(null);
|
||||||
|
profileImageView.setImageDrawable(clickedDrawable);
|
||||||
|
profileImageView.setBorderColors(clickedColors);
|
||||||
|
profileImageView.setAlpha(1f);
|
||||||
|
clickedImageView.setScaleX(1);
|
||||||
|
clickedImageView.setScaleY(1);
|
||||||
|
clickedImageView.setAlpha(1f);
|
||||||
|
mSwitchAccountAnimationPlaying = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAnimationCancel(Animator animation) {
|
||||||
|
finishAnimation();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAnimationRepeat(Animator animation) {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
set.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateAccountOptionsSeparatorLabel(Drawable profileImageSnapshot) {
|
||||||
final ParcelableAccount account = mAccountsAdapter.getSelectedAccount();
|
final ParcelableAccount account = mAccountsAdapter.getSelectedAccount();
|
||||||
if (account == null) {
|
if (account == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mAccountProfileNameView.setText(account.name);
|
mAccountProfileNameView.setText(account.name);
|
||||||
mAccountProfileScreenNameView.setText("@" + account.screen_name);
|
mAccountProfileScreenNameView.setText("@" + account.screen_name);
|
||||||
mImageLoader.displayProfileImage(mAccountProfileImageView, account.profile_image_url);
|
mImageLoader.displayDashboardProfileImage(mAccountProfileImageView,
|
||||||
|
account.profile_image_url, profileImageSnapshot);
|
||||||
mAccountProfileImageView.setBorderColors(account.color);
|
mAccountProfileImageView.setBorderColors(account.color);
|
||||||
final int bannerWidth = mAccountProfileBannerView.getWidth();
|
final int bannerWidth = mAccountProfileBannerView.getWidth();
|
||||||
final Resources res = getResources();
|
final Resources res = getResources();
|
||||||
|
@ -483,9 +574,13 @@ public class AccountsDashboardFragment extends BaseSupportListFragment implement
|
||||||
icon = (ShapedImageView) itemView.findViewById(android.R.id.icon);
|
icon = (ShapedImageView) itemView.findViewById(android.R.id.icon);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ShapedImageView getIconView() {
|
||||||
|
return icon;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
adapter.dispatchItemSelected(getPosition());
|
adapter.dispatchItemSelected(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -494,62 +589,95 @@ public class AccountsDashboardFragment extends BaseSupportListFragment implement
|
||||||
private final LayoutInflater mInflater;
|
private final LayoutInflater mInflater;
|
||||||
private final ImageLoaderWrapper mImageLoader;
|
private final ImageLoaderWrapper mImageLoader;
|
||||||
private final AccountsDashboardFragment mFragment;
|
private final AccountsDashboardFragment mFragment;
|
||||||
private Cursor mCursor;
|
private ParcelableAccount[] mAccounts;
|
||||||
private Indices mIndices;
|
private ParcelableAccount[] mInternalAccounts;
|
||||||
private long mSelectedAccountId;
|
|
||||||
private int mSelectedAccountIndex;
|
|
||||||
|
|
||||||
AccountSelectorAdapter(Context context, AccountsDashboardFragment fragment) {
|
AccountSelectorAdapter(Context context, AccountsDashboardFragment fragment) {
|
||||||
mInflater = LayoutInflater.from(context);
|
mInflater = LayoutInflater.from(context);
|
||||||
mImageLoader = TwidereApplication.getInstance(context).getImageLoaderWrapper();
|
mImageLoader = TwidereApplication.getInstance(context).getImageLoaderWrapper();
|
||||||
mFragment = fragment;
|
mFragment = fragment;
|
||||||
|
setHasStableIds(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void changeCursor(Cursor cursor) {
|
private static int indexOfAccount(List<ParcelableAccount> accounts, long accountId) {
|
||||||
mCursor = cursor;
|
for (int i = 0, j = accounts.size(); i < j; i++) {
|
||||||
if (cursor != null) {
|
if (accounts.get(i).account_id == accountId) return i;
|
||||||
mIndices = new Indices(cursor);
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAccounts(ParcelableAccount[] accounts) {
|
||||||
|
mAccounts = accounts;
|
||||||
|
if (accounts != null) {
|
||||||
|
final ParcelableAccount[] previousAccounts = mInternalAccounts;
|
||||||
|
mInternalAccounts = new ParcelableAccount[accounts.length];
|
||||||
|
int tempIdx = 0;
|
||||||
|
final List<ParcelableAccount> tempList = Arrays.asList(accounts);
|
||||||
|
if (previousAccounts != null) {
|
||||||
|
for (ParcelableAccount previousAccount : previousAccounts) {
|
||||||
|
final int idx = indexOfAccount(tempList, previousAccount.account_id);
|
||||||
|
if (idx >= 0) {
|
||||||
|
mInternalAccounts[tempIdx++] = tempList.remove(idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (ParcelableAccount account : tempList) {
|
||||||
|
mInternalAccounts[tempIdx++] = account;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mInternalAccounts = null;
|
||||||
}
|
}
|
||||||
updateSelectedAccountIndex();
|
|
||||||
notifyDataSetChanged();
|
notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateSelectedAccountIndex() {
|
|
||||||
final Cursor c = mCursor;
|
public ParcelableAccount getAdapterAccount(int adapterPosition) {
|
||||||
final Indices i = mIndices;
|
if (mInternalAccounts == null || mInternalAccounts.length < 1) {
|
||||||
mSelectedAccountIndex = -1;
|
return null;
|
||||||
if (c != null && i != null && c.moveToFirst()) {
|
|
||||||
while (!c.isAfterLast()) {
|
|
||||||
if (c.getLong(mIndices.account_id) == mSelectedAccountId) {
|
|
||||||
mSelectedAccountIndex = c.getPosition();
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
c.moveToNext();
|
return mInternalAccounts[adapterPosition + 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
private final LongSparseArray<Long> positionMap = new LongSparseArray<>();
|
||||||
|
|
||||||
|
private void swap(long fromId, long toId) {
|
||||||
|
int fromIdx = -1, toIdx = -1;
|
||||||
|
for (int i = 0, j = mInternalAccounts.length; i < j; i++) {
|
||||||
|
final ParcelableAccount account = mInternalAccounts[i];
|
||||||
|
if (account.account_id == fromId) {
|
||||||
|
fromIdx = i;
|
||||||
|
}
|
||||||
|
if (account.account_id == toId) {
|
||||||
|
toIdx = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (fromIdx < 0 || toIdx < 0) return;
|
||||||
|
final ParcelableAccount temp = mInternalAccounts[toIdx];
|
||||||
|
mInternalAccounts[toIdx] = mInternalAccounts[fromIdx];
|
||||||
|
mInternalAccounts[fromIdx] = temp;
|
||||||
|
notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ParcelableAccount getSelectedAccount() {
|
public ParcelableAccount getSelectedAccount() {
|
||||||
final Cursor c = mCursor;
|
if (mInternalAccounts == null || mInternalAccounts.length < 0) {
|
||||||
final Indices i = mIndices;
|
|
||||||
if (c != null && i != null && c.moveToFirst()) {
|
|
||||||
while (!c.isAfterLast()) {
|
|
||||||
if (c.getLong(mIndices.account_id) == mSelectedAccountId)
|
|
||||||
return new ParcelableAccount(c, mIndices);
|
|
||||||
c.moveToNext();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
return mInternalAccounts[0];
|
||||||
|
}
|
||||||
|
|
||||||
public long getSelectedAccountId() {
|
public long getSelectedAccountId() {
|
||||||
return mSelectedAccountId;
|
return getSelectedAccount().account_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSelectedAccountId(long accountId) {
|
public void setSelectedAccountId(long accountId) {
|
||||||
mSelectedAccountId = accountId;
|
final ParcelableAccount selectedAccount = getSelectedAccount();
|
||||||
updateSelectedAccountIndex();
|
if (selectedAccount == null) return;
|
||||||
notifyDataSetChanged();
|
swap(accountId, selectedAccount.account_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getItemId(int position) {
|
||||||
|
return getAdapterAccount(position).account_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -560,31 +688,22 @@ public class AccountsDashboardFragment extends BaseSupportListFragment implement
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(AccountProfileImageViewHolder holder, int position) {
|
public void onBindViewHolder(AccountProfileImageViewHolder holder, int position) {
|
||||||
final Cursor c = mCursor;
|
// holder.itemView.setAlpha(c.getInt(mIndices.is_activated) == 1 ? 1 : 0.5f);
|
||||||
if (mSelectedAccountIndex != -1 && position >= mSelectedAccountIndex) {
|
final ParcelableAccount account = getAdapterAccount(position);
|
||||||
c.moveToPosition(position + 1);
|
mImageLoader.cancelDisplayTask(holder.icon);
|
||||||
} else {
|
// holder.icon.setImageDrawable(null);
|
||||||
c.moveToPosition(position);
|
mImageLoader.displayDashboardProfileImage(holder.icon, account.profile_image_url, null);
|
||||||
}
|
holder.icon.setBorderColor(account.color);
|
||||||
holder.itemView.setAlpha(c.getInt(mIndices.is_activated) == 1 ? 1 : 0.5f);
|
|
||||||
mImageLoader.displayProfileImage(holder.icon, c.getString(mIndices.profile_image_url));
|
|
||||||
holder.icon.setBorderColor(c.getInt(mIndices.color));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemCount() {
|
public int getItemCount() {
|
||||||
if (mCursor == null) return 0;
|
if (mInternalAccounts == null || mInternalAccounts.length == 0) return 0;
|
||||||
return Math.max(mCursor.getCount() - 1, 0);
|
return mInternalAccounts.length - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void dispatchItemSelected(int position) {
|
private void dispatchItemSelected(AccountProfileImageViewHolder holder) {
|
||||||
final Cursor c = mCursor;
|
mFragment.onAccountSelected(holder, getAdapterAccount(holder.getAdapterPosition()));
|
||||||
if (mSelectedAccountIndex != -1 && position >= mSelectedAccountIndex) {
|
|
||||||
c.moveToPosition(position + 1);
|
|
||||||
} else {
|
|
||||||
c.moveToPosition(position);
|
|
||||||
}
|
|
||||||
mFragment.onAccountSelected(new ParcelableAccount(c, mIndices));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -643,7 +762,7 @@ public class AccountsDashboardFragment extends BaseSupportListFragment implement
|
||||||
final TextView text1 = (TextView) view.findViewById(android.R.id.text1);
|
final TextView text1 = (TextView) view.findViewById(android.R.id.text1);
|
||||||
final ImageView icon = (ImageView) view.findViewById(android.R.id.icon);
|
final ImageView icon = (ImageView) view.findViewById(android.R.id.icon);
|
||||||
text1.setText(option.name);
|
text1.setText(option.name);
|
||||||
icon.setImageDrawable(icon.getResources().getDrawable(option.icon));
|
icon.setImageDrawable(ResourcesCompat.getDrawable(icon.getResources(), option.icon, null));
|
||||||
icon.setColorFilter(mActionIconColor, Mode.SRC_ATOP);
|
icon.setColorFilter(mActionIconColor, Mode.SRC_ATOP);
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,9 +20,11 @@
|
||||||
package org.mariotaku.twidere.util;
|
package org.mariotaku.twidere.util;
|
||||||
|
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
|
|
||||||
import com.nostra13.universalimageloader.core.DisplayImageOptions;
|
import com.nostra13.universalimageloader.core.DisplayImageOptions;
|
||||||
|
import com.nostra13.universalimageloader.core.DisplayImageOptions.Builder;
|
||||||
import com.nostra13.universalimageloader.core.ImageLoader;
|
import com.nostra13.universalimageloader.core.ImageLoader;
|
||||||
import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer;
|
import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer;
|
||||||
import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
|
import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
|
||||||
|
@ -38,6 +40,7 @@ public class ImageLoaderWrapper implements Constants {
|
||||||
|
|
||||||
private final ImageLoader mImageLoader;
|
private final ImageLoader mImageLoader;
|
||||||
private final DisplayImageOptions mProfileImageDisplayOptions;
|
private final DisplayImageOptions mProfileImageDisplayOptions;
|
||||||
|
private final DisplayImageOptions mDashboardProfileImageDisplayOptions;
|
||||||
private final DisplayImageOptions mOvalProfileImageDisplayOptions;
|
private final DisplayImageOptions mOvalProfileImageDisplayOptions;
|
||||||
private final DisplayImageOptions mImageDisplayOptions, mBannerDisplayOptions;
|
private final DisplayImageOptions mImageDisplayOptions, mBannerDisplayOptions;
|
||||||
|
|
||||||
|
@ -72,11 +75,17 @@ public class ImageLoaderWrapper implements Constants {
|
||||||
bannerOptsBuilder.cacheOnDisk(true);
|
bannerOptsBuilder.cacheOnDisk(true);
|
||||||
bannerOptsBuilder.bitmapConfig(Bitmap.Config.RGB_565);
|
bannerOptsBuilder.bitmapConfig(Bitmap.Config.RGB_565);
|
||||||
bannerOptsBuilder.displayer(new FadeInBitmapDisplayer(200, true, true, true));
|
bannerOptsBuilder.displayer(new FadeInBitmapDisplayer(200, true, true, true));
|
||||||
|
final DisplayImageOptions.Builder dashboardProfileOptsBuilder = new DisplayImageOptions.Builder();
|
||||||
|
// dashboardProfileOptsBuilder.showImageOnLoading(android.R.color.transparent);
|
||||||
|
dashboardProfileOptsBuilder.cacheInMemory(true);
|
||||||
|
dashboardProfileOptsBuilder.cacheOnDisk(true);
|
||||||
|
dashboardProfileOptsBuilder.bitmapConfig(Bitmap.Config.RGB_565);
|
||||||
|
|
||||||
mProfileImageDisplayOptions = profileOptsBuilder.build();
|
mProfileImageDisplayOptions = profileOptsBuilder.build();
|
||||||
mOvalProfileImageDisplayOptions = ovalProfileOptsBuilder.build();
|
mOvalProfileImageDisplayOptions = ovalProfileOptsBuilder.build();
|
||||||
mImageDisplayOptions = imageOptsBuilder.build();
|
mImageDisplayOptions = imageOptsBuilder.build();
|
||||||
mBannerDisplayOptions = bannerOptsBuilder.build();
|
mBannerDisplayOptions = bannerOptsBuilder.build();
|
||||||
|
mDashboardProfileImageDisplayOptions = dashboardProfileOptsBuilder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clearFileCache() {
|
public void clearFileCache() {
|
||||||
|
@ -120,6 +129,18 @@ public class ImageLoaderWrapper implements Constants {
|
||||||
mImageLoader.displayImage(url, view, mProfileImageDisplayOptions);
|
mImageLoader.displayImage(url, view, mProfileImageDisplayOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void displayDashboardProfileImage(final ImageView view, final String url, Drawable drawableOnLoading) {
|
||||||
|
if (drawableOnLoading != null) {
|
||||||
|
final Builder builder = new Builder();
|
||||||
|
builder.cloneFrom(mDashboardProfileImageDisplayOptions);
|
||||||
|
builder.showImageOnLoading(drawableOnLoading);
|
||||||
|
builder.showImageOnFail(drawableOnLoading);
|
||||||
|
mImageLoader.displayImage(url, view, builder.build());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mImageLoader.displayImage(url, view, mDashboardProfileImageDisplayOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void displayImage(final ImageView view, final String url, DisplayImageOptions options) {
|
public void displayImage(final ImageView view, final String url, DisplayImageOptions options) {
|
||||||
mImageLoader.displayImage(url, view, options);
|
mImageLoader.displayImage(url, view, options);
|
||||||
|
|
|
@ -0,0 +1,135 @@
|
||||||
|
/*
|
||||||
|
* Twidere - Twitter client for Android
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.mariotaku.twidere.util;
|
||||||
|
|
||||||
|
import android.animation.Animator;
|
||||||
|
import android.animation.AnimatorSet;
|
||||||
|
import android.animation.TypeEvaluator;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Matrix;
|
||||||
|
import android.graphics.Rect;
|
||||||
|
import android.graphics.RectF;
|
||||||
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Static utility methods for Transitions.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public class TransitionUtils {
|
||||||
|
private static int MAX_IMAGE_SIZE = (1024 * 1024);
|
||||||
|
|
||||||
|
static Animator mergeAnimators(Animator animator1, Animator animator2) {
|
||||||
|
if (animator1 == null) {
|
||||||
|
return animator2;
|
||||||
|
} else if (animator2 == null) {
|
||||||
|
return animator1;
|
||||||
|
} else {
|
||||||
|
AnimatorSet animatorSet = new AnimatorSet();
|
||||||
|
animatorSet.playTogether(animator1, animator2);
|
||||||
|
return animatorSet;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a copy of bitmap of given drawable, return null if intrinsic size is zero
|
||||||
|
*/
|
||||||
|
public static Bitmap createDrawableBitmap(Drawable drawable) {
|
||||||
|
int width = drawable.getIntrinsicWidth();
|
||||||
|
int height = drawable.getIntrinsicHeight();
|
||||||
|
if (width <= 0 || height <= 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
float scale = Math.min(1f, ((float) MAX_IMAGE_SIZE) / (width * height));
|
||||||
|
if (drawable instanceof BitmapDrawable && scale == 1f) {
|
||||||
|
// return same bitmap if scale down not needed
|
||||||
|
return ((BitmapDrawable) drawable).getBitmap();
|
||||||
|
}
|
||||||
|
int bitmapWidth = (int) (width * scale);
|
||||||
|
int bitmapHeight = (int) (height * scale);
|
||||||
|
Bitmap bitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888);
|
||||||
|
Canvas canvas = new Canvas(bitmap);
|
||||||
|
Rect existingBounds = drawable.getBounds();
|
||||||
|
int left = existingBounds.left;
|
||||||
|
int top = existingBounds.top;
|
||||||
|
int right = existingBounds.right;
|
||||||
|
int bottom = existingBounds.bottom;
|
||||||
|
drawable.setBounds(0, 0, bitmapWidth, bitmapHeight);
|
||||||
|
drawable.draw(canvas);
|
||||||
|
drawable.setBounds(left, top, right, bottom);
|
||||||
|
return bitmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a Bitmap of the given view, using the Matrix matrix to transform to the local
|
||||||
|
* coordinates. <code>matrix</code> will be modified during the bitmap creation.
|
||||||
|
* <p/>
|
||||||
|
* <p>If the bitmap is large, it will be scaled uniformly down to at most 1MB size.</p>
|
||||||
|
*
|
||||||
|
* @param view The view to create a bitmap for.
|
||||||
|
* @param matrix The matrix converting the view local coordinates to the coordinates that
|
||||||
|
* the bitmap will be displayed in. <code>matrix</code> will be modified before
|
||||||
|
* returning.
|
||||||
|
* @param bounds The bounds of the bitmap in the destination coordinate system (where the
|
||||||
|
* view should be presented. Typically, this is matrix.mapRect(viewBounds);
|
||||||
|
* @return A bitmap of the given view or null if bounds has no width or height.
|
||||||
|
*/
|
||||||
|
public static Bitmap createViewBitmap(View view, Matrix matrix, RectF bounds) {
|
||||||
|
Bitmap bitmap = null;
|
||||||
|
int bitmapWidth = Math.round(bounds.width());
|
||||||
|
int bitmapHeight = Math.round(bounds.height());
|
||||||
|
if (bitmapWidth > 0 && bitmapHeight > 0) {
|
||||||
|
float scale = Math.min(1f, ((float) MAX_IMAGE_SIZE) / (bitmapWidth * bitmapHeight));
|
||||||
|
bitmapWidth *= scale;
|
||||||
|
bitmapHeight *= scale;
|
||||||
|
matrix.postTranslate(-bounds.left, -bounds.top);
|
||||||
|
matrix.postScale(scale, scale);
|
||||||
|
bitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888);
|
||||||
|
Canvas canvas = new Canvas(bitmap);
|
||||||
|
canvas.concat(matrix);
|
||||||
|
view.draw(canvas);
|
||||||
|
}
|
||||||
|
return bitmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class MatrixEvaluator implements TypeEvaluator<Matrix> {
|
||||||
|
|
||||||
|
float[] mTempStartValues = new float[9];
|
||||||
|
|
||||||
|
float[] mTempEndValues = new float[9];
|
||||||
|
|
||||||
|
Matrix mTempMatrix = new Matrix();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Matrix evaluate(float fraction, Matrix startValue, Matrix endValue) {
|
||||||
|
startValue.getValues(mTempStartValues);
|
||||||
|
endValue.getValues(mTempEndValues);
|
||||||
|
for (int i = 0; i < 9; i++) {
|
||||||
|
float diff = mTempEndValues[i] - mTempStartValues[i];
|
||||||
|
mTempEndValues[i] = mTempStartValues[i] + (fraction * diff);
|
||||||
|
}
|
||||||
|
mTempMatrix.setValues(mTempEndValues);
|
||||||
|
return mTempMatrix;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -228,6 +228,10 @@ public class ShapedImageView extends ImageView {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int[] getBorderColors() {
|
||||||
|
return mBorderColors;
|
||||||
|
}
|
||||||
|
|
||||||
@ShapeStyle
|
@ShapeStyle
|
||||||
public int getStyle() {
|
public int getStyle() {
|
||||||
return mStyle;
|
return mStyle;
|
||||||
|
|
|
@ -23,7 +23,9 @@
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content"
|
||||||
|
tools:layout_height="160dp"
|
||||||
|
tools:layout_width="280dp">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/account_profile_banner"
|
android:id="@+id/account_profile_banner"
|
||||||
|
@ -33,7 +35,8 @@
|
||||||
android:layout_alignTop="@id/profile_container"
|
android:layout_alignTop="@id/profile_container"
|
||||||
android:alpha="0.5"
|
android:alpha="0.5"
|
||||||
android:contentDescription="@string/profile_banner"
|
android:contentDescription="@string/profile_banner"
|
||||||
android:scaleType="centerCrop"/>
|
android:scaleType="centerCrop"
|
||||||
|
tools:src="@drawable/nyan_stars_background"/>
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/profile_container"
|
android:id="@+id/profile_container"
|
||||||
|
@ -58,7 +61,7 @@
|
||||||
android:layout_marginTop="@dimen/element_spacing_mlarge"
|
android:layout_marginTop="@dimen/element_spacing_mlarge"
|
||||||
app:sivBorder="true"
|
app:sivBorder="true"
|
||||||
app:sivBorderWidth="2dp"
|
app:sivBorderWidth="2dp"
|
||||||
tools:src="@drawable/profile_image_nyan_sakamoto"/>
|
tools:src="@mipmap/ic_launcher"/>
|
||||||
|
|
||||||
<android.support.v7.widget.RecyclerView
|
<android.support.v7.widget.RecyclerView
|
||||||
android:id="@+id/other_accounts_list"
|
android:id="@+id/other_accounts_list"
|
||||||
|
@ -76,7 +79,8 @@
|
||||||
android:layout_alignParentBottom="true"
|
android:layout_alignParentBottom="true"
|
||||||
android:layout_below="@id/profile_image"
|
android:layout_below="@id/profile_image"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal"
|
||||||
|
android:baselineAligned="false">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
|
@ -117,6 +121,14 @@
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/floating_profile_image_snapshot"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:scaleType="fitCenter"
|
||||||
|
android:visibility="invisible"
|
||||||
|
tools:ignore="ContentDescription"/>
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
Loading…
Reference in New Issue