changed statuses count to listed count in profile page

improved gesture in user profile drawer
This commit is contained in:
Mariotaku Lee 2014-12-01 17:15:20 +08:00
parent b47b7c7d3b
commit 3c7b636b42
15 changed files with 369 additions and 277 deletions

View File

@ -28,7 +28,7 @@ package org.mariotaku.twidere;
public interface Constants extends TwidereConstants {
public static final String DATABASES_NAME = "twidere.sqlite";
public static final int DATABASES_VERSION = 71;
public static final int DATABASES_VERSION = 72;
public static final int MENU_GROUP_STATUS_EXTENSION = 10;
public static final int MENU_GROUP_COMPOSE_EXTENSION = 11;

View File

@ -31,10 +31,12 @@ import android.database.Cursor;
import android.graphics.PorterDuff.Mode;
import android.graphics.Rect;
import android.os.Bundle;
import android.support.v4.app.ActivityOptionsCompat;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.util.Pair;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.Adapter;
@ -181,9 +183,11 @@ public class AccountsDashboardFragment extends BaseSupportListFragment implement
final OptionItem option = (OptionItem) item;
switch (option.id) {
case MENU_VIEW_PROFILE: {
openUserProfile(getActivity(), account.account_id, account.account_id,
account.screen_name, null);
closeAccountsDrawer();
final FragmentActivity activity = getActivity();
final ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(activity,
new Pair<View, String>(mAccountProfileImageView, UserProfileFragment.TRANSITION_NAME_PROFILE_IMAGE));
openUserProfile(activity, account.account_id, account.account_id, account.screen_name,
options.toBundle());
break;
}
case MENU_SEARCH: {
@ -198,22 +202,18 @@ public class AccountsDashboardFragment extends BaseSupportListFragment implement
}
case MENU_STATUSES: {
openUserTimeline(getActivity(), account.account_id, account.account_id, account.screen_name);
closeAccountsDrawer();
break;
}
case MENU_FAVORITES: {
openUserFavorites(getActivity(), account.account_id, account.account_id, account.screen_name);
closeAccountsDrawer();
break;
}
case MENU_LISTS: {
openUserLists(getActivity(), account.account_id, account.account_id, account.screen_name);
closeAccountsDrawer();
break;
}
case MENU_LIST_MEMBERSHIPS: {
openUserListMemberships(getActivity(), account.account_id, account.account_id, account.screen_name);
closeAccountsDrawer();
break;
}
case MENU_EDIT: {
@ -223,7 +223,6 @@ public class AccountsDashboardFragment extends BaseSupportListFragment implement
intent.setClass(getActivity(), UserProfileEditorActivity.class);
intent.putExtras(bundle);
startActivity(intent);
closeAccountsDrawer();
break;
}
}

View File

@ -120,8 +120,15 @@ public class BaseSupportFragment extends Fragment implements IBaseFragment, Cons
@Override
public void requestFitSystemWindows() {
final Activity activity = getActivity();
if (!(activity instanceof SystemWindowsInsetsCallback)) return;
final SystemWindowsInsetsCallback callback = (SystemWindowsInsetsCallback) activity;
final Fragment parentFragment = getParentFragment();
final SystemWindowsInsetsCallback callback;
if (parentFragment instanceof SystemWindowsInsetsCallback) {
callback = (SystemWindowsInsetsCallback) parentFragment;
} else if (activity instanceof SystemWindowsInsetsCallback) {
callback = (SystemWindowsInsetsCallback) activity;
} else {
return;
}
final Rect insets = new Rect();
if (callback.getSystemWindowsInsets(insets)) {
fitSystemWindows(insets);

View File

@ -123,8 +123,15 @@ public class BaseSupportListFragment extends ListFragment implements IBaseFragme
@Override
public void requestFitSystemWindows() {
final Activity activity = getActivity();
if (!(activity instanceof SystemWindowsInsetsCallback)) return;
final SystemWindowsInsetsCallback callback = (SystemWindowsInsetsCallback) activity;
final Fragment parentFragment = getParentFragment();
final SystemWindowsInsetsCallback callback;
if (parentFragment instanceof SystemWindowsInsetsCallback) {
callback = (SystemWindowsInsetsCallback) parentFragment;
} else if (activity instanceof SystemWindowsInsetsCallback) {
callback = (SystemWindowsInsetsCallback) activity;
} else {
return;
}
final Rect insets = new Rect();
if (callback.getSystemWindowsInsets(insets)) {
fitSystemWindows(insets);

View File

@ -55,9 +55,17 @@ public class BaseSupportStaggeredGridFragment extends StaggeredGridFragment impl
@Override
public void requestFitSystemWindows() {
final Activity activity = getActivity();
final Fragment parentFragment = getParentFragment();
final SystemWindowsInsetsCallback callback;
if (parentFragment instanceof SystemWindowsInsetsCallback) {
callback = (SystemWindowsInsetsCallback) parentFragment;
} else if (activity instanceof SystemWindowsInsetsCallback) {
callback = (SystemWindowsInsetsCallback) activity;
} else {
return;
}
final Rect insets = new Rect();
if (activity instanceof SystemWindowsInsetsCallback
&& ((SystemWindowsInsetsCallback) activity).getSystemWindowsInsets(insets)) {
if (callback.getSystemWindowsInsets(insets)) {
fitSystemWindows(insets);
}
}

View File

@ -87,6 +87,7 @@ import org.mariotaku.twidere.activity.support.LinkHandlerActivity;
import org.mariotaku.twidere.activity.support.UserListSelectorActivity;
import org.mariotaku.twidere.activity.support.UserProfileEditorActivity;
import org.mariotaku.twidere.adapter.support.SupportTabsAdapter;
import org.mariotaku.twidere.fragment.iface.IBaseFragment.SystemWindowsInsetsCallback;
import org.mariotaku.twidere.fragment.iface.SupportFragmentCallback;
import org.mariotaku.twidere.loader.support.ParcelableUserLoader;
import org.mariotaku.twidere.model.ParcelableUser;
@ -142,15 +143,15 @@ import static org.mariotaku.twidere.util.Utils.openStatus;
import static org.mariotaku.twidere.util.Utils.openTweetSearch;
import static org.mariotaku.twidere.util.Utils.openUserFollowers;
import static org.mariotaku.twidere.util.Utils.openUserFriends;
import static org.mariotaku.twidere.util.Utils.openUserLists;
import static org.mariotaku.twidere.util.Utils.openUserProfile;
import static org.mariotaku.twidere.util.Utils.openUserTimeline;
import static org.mariotaku.twidere.util.Utils.setMenuItemAvailability;
import static org.mariotaku.twidere.util.Utils.showInfoMessage;
public class UserProfileFragment extends BaseSupportFragment implements OnClickListener,
OnMenuItemClickListener, OnLinkClickListener, OnSizeChangedListener,
OnSharedPreferenceChangeListener, OnTouchListener, ImageLoadingListener, DrawerCallback,
SupportFragmentCallback {
SupportFragmentCallback, SystemWindowsInsetsCallback {
public static final String TRANSITION_NAME_PROFILE_IMAGE = "profile_image";
public static final String TRANSITION_NAME_PROFILE_TYPE = "profile_type";
@ -164,8 +165,8 @@ public class UserProfileFragment extends BaseSupportFragment implements OnClickL
private ImageView mProfileTypeView;
private ProfileBannerImageView mProfileBannerView;
private TextView mNameView, mScreenNameView, mDescriptionView, mLocationView, mURLView, mCreatedAtView,
mTweetCount, mFollowersCount, mFriendsCount, mErrorMessageView;
private View mDescriptionContainer, mLocationContainer, mURLContainer, mTweetsContainer, mFollowersContainer,
mListedCount, mFollowersCount, mFriendsCount, mErrorMessageView;
private View mDescriptionContainer, mLocationContainer, mURLContainer, mListedContainer, mFollowersContainer,
mFriendsContainer;
private Button mRetryButton;
private ColorLabelLinearLayout mProfileNameContainer;
@ -182,16 +183,6 @@ public class UserProfileFragment extends BaseSupportFragment implements OnClickL
private Relationship mRelationship;
private ParcelableUser mUser = null;
private Locale mLocale;
private boolean mGetUserInfoLoaderInitialized, mGetFriendShipLoaderInitialized;
private int mBannerWidth;
private ActionBarDrawable mActionBarBackground;
private Fragment mCurrentVisibleFragment;
private final BroadcastReceiver mStatusReceiver = new BroadcastReceiver() {
@Override
@ -227,7 +218,6 @@ public class UserProfileFragment extends BaseSupportFragment implements OnClickL
}
}
};
private final LoaderCallbacks<SingleResponse<ParcelableUser>> mUserInfoLoaderCallbacks = new LoaderCallbacks<SingleResponse<ParcelableUser>>() {
@Override
@ -293,7 +283,6 @@ public class UserProfileFragment extends BaseSupportFragment implements OnClickL
}
};
private final LoaderCallbacks<SingleResponse<Relationship>> mFriendshipLoaderCallbacks = new LoaderCallbacks<SingleResponse<Relationship>>() {
@Override
@ -338,6 +327,11 @@ public class UserProfileFragment extends BaseSupportFragment implements OnClickL
}
};
private Locale mLocale;
private boolean mGetUserInfoLoaderInitialized, mGetFriendShipLoaderInitialized;
private int mBannerWidth;
private ActionBarDrawable mActionBarBackground;
private Fragment mCurrentVisibleFragment;
public void displayUser(final ParcelableUser user) {
mRelationship = null;
@ -383,7 +377,7 @@ public class UserProfileFragment extends BaseSupportFragment implements OnClickL
final int dailyTweets = Math.round(user.statuses_count / Math.max(1, daysSinceCreated));
mCreatedAtView.setText(res.getQuantityString(R.plurals.created_at_with_N_tweets_per_day, dailyTweets,
createdAt, dailyTweets));
mTweetCount.setText(getLocalizedNumber(mLocale, user.statuses_count));
mListedCount.setText(getLocalizedNumber(mLocale, user.listed_count));
mFollowersCount.setText(getLocalizedNumber(mLocale, user.followers_count));
mFriendsCount.setText(getLocalizedNumber(mLocale, user.friends_count));
if (userColor != 0) {
@ -454,54 +448,6 @@ public class UserProfileFragment extends BaseSupportFragment implements OnClickL
mUserProfileContent.setDrawColor(drawColor);
}
@Override
public void onActivityCreated(final Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setHasOptionsMenu(true);
getSharedPreferences(USER_COLOR_PREFERENCES_NAME, Context.MODE_PRIVATE)
.registerOnSharedPreferenceChangeListener(this);
getSharedPreferences(USER_NICKNAME_PREFERENCES_NAME, Context.MODE_PRIVATE)
.registerOnSharedPreferenceChangeListener(this);
mLocale = getResources().getConfiguration().locale;
final Bundle args = getArguments();
long accountId = -1, userId = -1;
String screenName = null;
if (savedInstanceState != null) {
args.putAll(savedInstanceState);
} else {
accountId = args.getLong(EXTRA_ACCOUNT_ID, -1);
userId = args.getLong(EXTRA_USER_ID, -1);
screenName = args.getString(EXTRA_SCREEN_NAME);
}
mProfileImageLoader = getApplication().getImageLoaderWrapper();
final FragmentActivity activity = getActivity();
ViewCompat.setTransitionName(mProfileImageView, TRANSITION_NAME_PROFILE_IMAGE);
ViewCompat.setTransitionName(mProfileTypeView, TRANSITION_NAME_PROFILE_TYPE);
mUserProfileDrawer.setDrawerCallback(this);
mPagerAdapter = new SupportTabsAdapter(activity, getChildFragmentManager());
mViewPager.setAdapter(mPagerAdapter);
mPagerIndicator.setViewPager(mViewPager);
mProfileImageView.setOnClickListener(this);
mProfileBannerView.setOnClickListener(this);
mTweetsContainer.setOnClickListener(this);
mFollowersContainer.setOnClickListener(this);
mFriendsContainer.setOnClickListener(this);
mRetryButton.setOnClickListener(this);
mProfileBannerView.setOnSizeChangedListener(this);
mProfileBannerSpace.setOnTouchListener(this);
getUserInfo(accountId, userId, screenName, false);
setupBaseActionBar();
setupUserPages();
}
private void setupUserPages() {
final Context context = getActivity();
final Bundle args = getArguments(), tabArgs = new Bundle();
@ -519,8 +465,9 @@ public class UserProfileFragment extends BaseSupportFragment implements OnClickL
}
mPagerAdapter.addTab(UserTimelineFragment.class, tabArgs, getString(R.string.statuses), null, 0);
if (Utils.isOfficialKeyAccount(context, accountId)) {
mPagerAdapter.addTab(UserMediaTimelineFragment.class, tabArgs, getString(R.string.media), null, 0);
mPagerAdapter.addTab(UserMediaTimelineFragment.class, tabArgs, getString(R.string.media), null, 1);
}
mPagerAdapter.addTab(UserFavoritesFragment.class, tabArgs, getString(R.string.favorites), null, 2);
mPagerIndicator.notifyDataSetChanged();
}
@ -544,6 +491,7 @@ public class UserProfileFragment extends BaseSupportFragment implements OnClickL
}
mActionBarBackground.setColor(color);
mUserProfileContent.setColor(color);
mPagerIndicator.setIndicatorColor(color);
}
private boolean isUucky(long userId, String screenName, Parcelable parcelable) {
@ -593,6 +541,111 @@ public class UserProfileFragment extends BaseSupportFragment implements OnClickL
}
@Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_user_profile, container, false);
}
@Override
public void onActivityCreated(final Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setHasOptionsMenu(true);
getSharedPreferences(USER_COLOR_PREFERENCES_NAME, Context.MODE_PRIVATE)
.registerOnSharedPreferenceChangeListener(this);
getSharedPreferences(USER_NICKNAME_PREFERENCES_NAME, Context.MODE_PRIVATE)
.registerOnSharedPreferenceChangeListener(this);
mLocale = getResources().getConfiguration().locale;
final Bundle args = getArguments();
long accountId = -1, userId = -1;
String screenName = null;
if (savedInstanceState != null) {
args.putAll(savedInstanceState);
} else {
accountId = args.getLong(EXTRA_ACCOUNT_ID, -1);
userId = args.getLong(EXTRA_USER_ID, -1);
screenName = args.getString(EXTRA_SCREEN_NAME);
}
mProfileImageLoader = getApplication().getImageLoaderWrapper();
final FragmentActivity activity = getActivity();
ViewCompat.setTransitionName(mProfileImageView, TRANSITION_NAME_PROFILE_IMAGE);
ViewCompat.setTransitionName(mProfileTypeView, TRANSITION_NAME_PROFILE_TYPE);
mUserProfileDrawer.setDrawerCallback(this);
mPagerAdapter = new SupportTabsAdapter(activity, getChildFragmentManager());
mViewPager.setAdapter(mPagerAdapter);
mPagerIndicator.setViewPager(mViewPager);
mProfileImageView.setOnClickListener(this);
mProfileBannerView.setOnClickListener(this);
mListedContainer.setOnClickListener(this);
mFollowersContainer.setOnClickListener(this);
mFriendsContainer.setOnClickListener(this);
mRetryButton.setOnClickListener(this);
mProfileBannerView.setOnSizeChangedListener(this);
mProfileBannerSpace.setOnTouchListener(this);
getUserInfo(accountId, userId, screenName, false);
setupBaseActionBar();
// updateScrollOffset(0);
setupUserPages();
}
@Override
public void onStart() {
super.onStart();
final IntentFilter filter = new IntentFilter(BROADCAST_TASK_STATE_CHANGED);
filter.addAction(BROADCAST_FRIENDSHIP_CHANGED);
filter.addAction(BROADCAST_PROFILE_UPDATED);
filter.addAction(BROADCAST_PROFILE_IMAGE_UPDATED);
filter.addAction(BROADCAST_PROFILE_BANNER_UPDATED);
registerReceiver(mStatusReceiver, filter);
}
@Override
public void onSaveInstanceState(final Bundle outState) {
outState.putParcelable(EXTRA_USER, mUser);
super.onSaveInstanceState(outState);
}
@Override
public void onStop() {
unregisterReceiver(mStatusReceiver);
super.onStop();
}
@Override
public void onDestroyView() {
mUser = null;
mRelationship = null;
final LoaderManager lm = getLoaderManager();
lm.destroyLoader(LOADER_ID_USER);
lm.destroyLoader(LOADER_ID_FRIENDSHIP);
super.onDestroyView();
}
@Override
public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
if (!shouldUseNativeMenu()) return;
inflater.inflate(R.menu.menu_user_profile, menu);
}
@Override
public void onPrepareOptionsMenu(final Menu menu) {
if (!shouldUseNativeMenu() || !menu.hasVisibleItems()) return;
setMenu(menu);
}
@Override
public boolean onOptionsItemSelected(final MenuItem item) {
return handleMenuItemClick(item);
}
@Override
public void onClick(final View view) {
final FragmentActivity activity = getActivity();
@ -614,8 +667,8 @@ public class UserProfileFragment extends BaseSupportFragment implements OnClickL
openImage(getActivity(), user.account_id, profile_banner_url + "/ipad_retina", false);
break;
}
case R.id.tweets_container: {
openUserTimeline(getActivity(), user.account_id, user.id, user.screen_name);
case R.id.listed_container: {
openUserLists(getActivity(), user.account_id, user.id, user.screen_name);
break;
}
case R.id.followers_container: {
@ -635,28 +688,6 @@ public class UserProfileFragment extends BaseSupportFragment implements OnClickL
}
@Override
public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
if (!shouldUseNativeMenu()) return;
inflater.inflate(R.menu.menu_user_profile, menu);
}
@Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_user_profile, container, false);
}
@Override
public void onDestroyView() {
mUser = null;
mRelationship = null;
final LoaderManager lm = getLoaderManager();
lm.destroyLoader(LOADER_ID_USER);
lm.destroyLoader(LOADER_ID_FRIENDSHIP);
super.onDestroyView();
}
@Override
public void onLinkClick(final String link, final String orig, final long account_id, final int type,
final boolean sensitive) {
@ -703,23 +734,6 @@ public class UserProfileFragment extends BaseSupportFragment implements OnClickL
}
@Override
public boolean onOptionsItemSelected(final MenuItem item) {
return handleMenuItemClick(item);
}
@Override
public void onPrepareOptionsMenu(final Menu menu) {
if (!shouldUseNativeMenu() || !menu.hasVisibleItems()) return;
setMenu(menu);
}
@Override
public void onSaveInstanceState(final Bundle outState) {
outState.putParcelable(EXTRA_USER, mUser);
super.onSaveInstanceState(outState);
}
@Override
public void onSharedPreferenceChanged(final SharedPreferences sharedPreferences, final String key) {
if (mUser == null || !ParseUtils.parseString(mUser.id).equals(key)) return;
@ -734,48 +748,11 @@ public class UserProfileFragment extends BaseSupportFragment implements OnClickL
}
}
@Override
public void onStart() {
super.onStart();
final IntentFilter filter = new IntentFilter(BROADCAST_TASK_STATE_CHANGED);
filter.addAction(BROADCAST_FRIENDSHIP_CHANGED);
filter.addAction(BROADCAST_PROFILE_UPDATED);
filter.addAction(BROADCAST_PROFILE_IMAGE_UPDATED);
filter.addAction(BROADCAST_PROFILE_BANNER_UPDATED);
registerReceiver(mStatusReceiver, filter);
}
@Override
public void onStop() {
unregisterReceiver(mStatusReceiver);
super.onStop();
}
@Override
public boolean onTouch(final View v, final MotionEvent event) {
return mProfileBannerView.dispatchTouchEvent(event);
}
@Override
protected void fitSystemWindows(Rect insets) {
super.fitSystemWindows(insets);
final View view = getView();
if (view != null) {
final View progress = view.findViewById(R.id.progress_container);
progress.setPadding(insets.left, insets.top, insets.right, insets.bottom);
}
mErrorRetryContainer.setPadding(insets.left, insets.top, insets.right, insets.bottom);
mUserProfileDrawer.setPadding(insets.left, insets.top, insets.right, insets.bottom);
mUserProfileDrawer.setClipToPadding(false);
final int bannerHeight = mProfileBannerView.getHeight();
if (bannerHeight != 0) {
final ViewGroup.LayoutParams params = mProfileBannerSpace.getLayoutParams();
params.height = bannerHeight - insets.top;
mProfileBannerSpace.setLayoutParams(params);
mProfileBannerSpace.requestLayout();
}
}
@Override
public void onViewCreated(final View view, final Bundle savedInstanceState) {
final Context context = view.getContext();
@ -796,8 +773,8 @@ public class UserProfileFragment extends BaseSupportFragment implements OnClickL
mLocationView = (TextView) headerView.findViewById(R.id.location);
mURLView = (TextView) headerView.findViewById(R.id.url);
mCreatedAtView = (TextView) headerView.findViewById(R.id.created_at);
mTweetsContainer = headerView.findViewById(R.id.tweets_container);
mTweetCount = (TextView) headerView.findViewById(R.id.statuses_count);
mListedContainer = headerView.findViewById(R.id.listed_container);
mListedCount = (TextView) headerView.findViewById(R.id.listed_count);
mFollowersContainer = headerView.findViewById(R.id.followers_container);
mFollowersCount = (TextView) headerView.findViewById(R.id.followers_count);
mFriendsContainer = headerView.findViewById(R.id.friends_container);
@ -816,6 +793,26 @@ public class UserProfileFragment extends BaseSupportFragment implements OnClickL
ThemeUtils.applyThemeAlphaToDrawable(context, cardView.getBackground());
}
@Override
protected void fitSystemWindows(Rect insets) {
super.fitSystemWindows(insets);
final View view = getView();
if (view != null) {
final View progress = view.findViewById(R.id.progress_container);
progress.setPadding(insets.left, insets.top, insets.right, insets.bottom);
}
mErrorRetryContainer.setPadding(insets.left, insets.top, insets.right, insets.bottom);
mUserProfileDrawer.setPadding(insets.left, insets.top, insets.right, insets.bottom);
mUserProfileDrawer.setClipToPadding(false);
final int bannerHeight = mProfileBannerView.getHeight();
if (bannerHeight != 0) {
final ViewGroup.LayoutParams params = mProfileBannerSpace.getLayoutParams();
params.height = bannerHeight - insets.top;
mProfileBannerSpace.setLayoutParams(params);
mProfileBannerSpace.requestLayout();
}
}
private void getFriendship() {
final ParcelableUser user = mUser;
final LoaderManager lm = getLoaderManager();
@ -1087,8 +1084,11 @@ public class UserProfileFragment extends BaseSupportFragment implements OnClickL
@Override
public boolean isScrollContent(float x, float y) {
final Fragment fragment = mCurrentVisibleFragment;
return fragment instanceof DrawerCallback && ((DrawerCallback) fragment).isScrollContent(x, y);
final ViewPager v = mViewPager;
final int[] location = new int[2];
v.getLocationOnScreen(location);
return x >= location[0] && x <= location[0] + v.getWidth()
&& y >= location[1] && y <= location[1] + v.getHeight();
}
@Override
@ -1102,9 +1102,19 @@ public class UserProfileFragment extends BaseSupportFragment implements OnClickL
@Override
public void topChanged(int top) {
final UserProfileDrawer drawer = mUserProfileDrawer;
final View space = mProfileBannerSpace;
if (drawer == null || space == null) return;
if (drawer == null) return;
final int offset = drawer.getPaddingTop() - top;
updateScrollOffset(offset);
final Fragment fragment = mCurrentVisibleFragment;
if (fragment instanceof DrawerCallback) {
((DrawerCallback) fragment).topChanged(top);
}
}
private void updateScrollOffset(int offset) {
final View space = mProfileBannerSpace;
if (space == null) return;
final float factor = offset / (float) space.getHeight();
final ProfileBannerImageView profileBannerView = mProfileBannerView;
profileBannerView.setAlpha(1.0f - factor / 8f);
@ -1115,11 +1125,6 @@ public class UserProfileFragment extends BaseSupportFragment implements OnClickL
mActionBarBackground.setFactor(factor);
mUserProfileContent.setFactor(factor);
}
final Fragment fragment = mCurrentVisibleFragment;
if (fragment instanceof DrawerCallback) {
((DrawerCallback) fragment).topChanged(top);
}
}
@Override
@ -1142,6 +1147,11 @@ public class UserProfileFragment extends BaseSupportFragment implements OnClickL
return false;
}
@Override
public boolean getSystemWindowsInsets(Rect insets) {
return false;
}
static class FriendshipLoader extends AsyncTaskLoader<SingleResponse<Relationship>> {
@ -1267,23 +1277,38 @@ public class UserProfileFragment extends BaseSupportFragment implements OnClickL
setColor(Color.TRANSPARENT);
}
@Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
mBounds.set(bounds);
}
@Override
public void draw(Canvas canvas) {
canvas.drawRect(mBounds.left, mBounds.bottom - mLineSize, mBounds.right,
mBounds.bottom, mPaint);
}
@Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
mBounds.set(bounds);
}
private void updatePaint() {
mPaint.setColor(mColor);
mPaint.setAlpha(Color.alpha(mColor) * mAlpha / 0xFF);
invalidateSelf();
}
public int getColor() {
return mColor;
}
@Override
public int getAlpha() {
return mAlpha;
}
public void setColor(int color) {
mColor = color;
updatePaint();
}
@Override
public void setAlpha(int alpha) {
mAlpha = alpha;
@ -1300,20 +1325,6 @@ public class UserProfileFragment extends BaseSupportFragment implements OnClickL
return PixelFormat.TRANSLUCENT;
}
public void setColor(int color) {
mColor = color;
updatePaint();
}
private void updatePaint() {
mPaint.setColor(mColor);
mPaint.setAlpha(Color.alpha(mColor) * mAlpha / 0xFF);
invalidateSelf();
}
public int getColor() {
return mColor;
}
}
}
}

View File

@ -72,7 +72,7 @@ public class ParcelableUser implements TwidereParcelable, Comparable<ParcelableU
public final String description_plain, name, screen_name, location, profile_image_url, profile_banner_url, url,
url_expanded, description_html, description_unescaped, description_expanded;
public final int followers_count, friends_count, statuses_count, favorites_count;
public final int followers_count, friends_count, statuses_count, favorites_count, listed_count;
public final boolean is_cache;
@ -101,6 +101,7 @@ public class ParcelableUser implements TwidereParcelable, Comparable<ParcelableU
friends_count = 0;
statuses_count = 0;
favorites_count = 0;
listed_count = 0;
is_cache = true;
}
@ -125,6 +126,7 @@ public class ParcelableUser implements TwidereParcelable, Comparable<ParcelableU
is_protected = cursor.getInt(cursor.getColumnIndex(CachedUsers.IS_PROTECTED)) == 1;
is_verified = cursor.getInt(cursor.getColumnIndex(CachedUsers.IS_VERIFIED)) == 1;
favorites_count = cursor.getInt(cursor.getColumnIndex(CachedUsers.FAVORITES_COUNT));
listed_count = cursor.getInt(cursor.getColumnIndex(CachedUsers.LISTED_COUNT));
followers_count = cursor.getInt(cursor.getColumnIndex(CachedUsers.FOLLOWERS_COUNT));
friends_count = cursor.getInt(cursor.getColumnIndex(CachedUsers.FRIENDS_COUNT));
statuses_count = cursor.getInt(cursor.getColumnIndex(CachedUsers.STATUSES_COUNT));
@ -159,6 +161,7 @@ public class ParcelableUser implements TwidereParcelable, Comparable<ParcelableU
friends_count = in.readInt("friends_count");
statuses_count = in.readInt("statuses_count");
favorites_count = in.readInt("favorites_count");
listed_count = in.readInt("listed_count");
is_cache = in.readBoolean("is_cache");
description_html = in.readString("description_html");
description_expanded = in.readString("description_expanded");
@ -186,6 +189,7 @@ public class ParcelableUser implements TwidereParcelable, Comparable<ParcelableU
friends_count = in.readInt();
statuses_count = in.readInt();
favorites_count = in.readInt();
listed_count = in.readInt();
is_cache = in.readInt() == 1;
description_html = in.readString();
description_expanded = in.readString();
@ -222,6 +226,7 @@ public class ParcelableUser implements TwidereParcelable, Comparable<ParcelableU
friends_count = user.getFriendsCount();
statuses_count = user.getStatusesCount();
favorites_count = user.getFavouritesCount();
listed_count = user.getListedCount();
is_cache = false;
is_following = user.isFollowing();
description_unescaped = toPlainText(description_html);
@ -294,6 +299,7 @@ public class ParcelableUser implements TwidereParcelable, Comparable<ParcelableU
out.writeInt("friends_count", friends_count);
out.writeInt("statuses_count", statuses_count);
out.writeInt("favorites_count", favorites_count);
out.writeInt("listed_count", listed_count);
out.writeBoolean("is_cache", is_cache);
out.writeString("description_html", description_html);
out.writeString("description_expanded", description_expanded);
@ -322,6 +328,7 @@ public class ParcelableUser implements TwidereParcelable, Comparable<ParcelableU
out.writeInt(friends_count);
out.writeInt(statuses_count);
out.writeInt(favorites_count);
out.writeInt(listed_count);
out.writeInt(is_cache ? 1 : 0);
out.writeString(description_html);
out.writeString(description_expanded);
@ -340,6 +347,7 @@ public class ParcelableUser implements TwidereParcelable, Comparable<ParcelableU
values.put(CachedUsers.CREATED_AT, user.created_at);
values.put(CachedUsers.IS_PROTECTED, user.is_protected);
values.put(CachedUsers.IS_VERIFIED, user.is_verified);
values.put(CachedUsers.LISTED_COUNT, user.listed_count);
values.put(CachedUsers.FAVORITES_COUNT, user.favorites_count);
values.put(CachedUsers.FOLLOWERS_COUNT, user.followers_count);
values.put(CachedUsers.FRIENDS_COUNT, user.friends_count);

View File

@ -239,6 +239,8 @@ public interface TweetStore {
public static final String FAVORITES_COUNT = "favorites_count";
public static final String LISTED_COUNT = "listed_count";
/**
* User's screen name of the status.<br>
* Type: TEXT
@ -253,12 +255,12 @@ public interface TweetStore {
public static final String[] COLUMNS = new String[]{_ID, USER_ID, CREATED_AT, NAME, SCREEN_NAME,
DESCRIPTION_PLAIN, LOCATION, URL, PROFILE_IMAGE_URL, PROFILE_BANNER_URL, IS_PROTECTED, IS_VERIFIED,
IS_FOLLOWING, FOLLOWERS_COUNT, FRIENDS_COUNT, STATUSES_COUNT, FAVORITES_COUNT, DESCRIPTION_HTML,
IS_FOLLOWING, FOLLOWERS_COUNT, FRIENDS_COUNT, STATUSES_COUNT, FAVORITES_COUNT, LISTED_COUNT, DESCRIPTION_HTML,
DESCRIPTION_EXPANDED, URL_EXPANDED};
public static final String[] TYPES = new String[]{TYPE_PRIMARY_KEY, TYPE_INT_UNIQUE, TYPE_INT, TYPE_TEXT,
TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_BOOLEAN, TYPE_BOOLEAN,
TYPE_BOOLEAN, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT};
TYPE_BOOLEAN, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT};
}

View File

@ -139,6 +139,7 @@ public final class ContentValuesCreator implements TwidereConstants {
values.put(CachedUsers.FOLLOWERS_COUNT, user.getFollowersCount());
values.put(CachedUsers.FRIENDS_COUNT, user.getFriendsCount());
values.put(CachedUsers.STATUSES_COUNT, user.getStatusesCount());
values.put(CachedUsers.LISTED_COUNT, user.getListedCount());
values.put(CachedUsers.LOCATION, user.getLocation());
values.put(CachedUsers.DESCRIPTION_PLAIN, user.getDescription());
values.put(CachedUsers.DESCRIPTION_HTML, Utils.formatUserDescription(user));

View File

@ -34,7 +34,8 @@ public class UserProfileDrawer extends ViewGroup {
private final DragCallback mDragCallback;
private DrawerCallback mDrawerCallback;
private boolean mUsingDragHelper, mScrollingHeaderByGesture;
private boolean mUsingDragHelper;
private boolean mScrollingHeaderByGesture, mScrollingContentCallback;
private boolean mTouchDown, mTouchingScrollableContent;
private int mHeaderOffset;
@ -73,6 +74,20 @@ public class UserProfileDrawer extends ViewGroup {
mScrollingHeaderByGesture = scrolling;
}
public void flingHeader(float velocity) {
if (mTouchDown) {
mScroller.abortAnimation();
return;
}
mScroller.fling(0, getHeaderTop(), 0, (int) velocity, 0, 0,
mContainer.getHeaderTopMinimum(), mContainer.getHeaderTopMaximum());
ViewCompat.postInvalidateOnAnimation(this);
}
private void flingCallback(float velocity) {
mDrawerCallback.fling(velocity);
}
@Override
public void computeScroll() {
boolean invalidate = mDragHelper.continueSettling(true);
@ -88,28 +103,8 @@ public class UserProfileDrawer extends ViewGroup {
}
}
public void flingHeader(float velocity) {
if (mTouchDown) {
mScroller.abortAnimation();
return;
}
mScroller.fling(0, getHeaderTop(), 0, (int) velocity, 0, 0,
mContainer.getHeaderTopMinimum(), mContainer.getHeaderTopMaximum());
ViewCompat.postInvalidateOnAnimation(this);
}
@Override
protected void onFinishInflate() {
if (getChildCount() != 1) {
throw new IllegalArgumentException("Add subview by XML is not allowed.");
}
}
private void flingCallback(float velocity) {
mDrawerCallback.fling(velocity);
}
private void scrollByCallback(float dy) {
setScrollingContentCallback(true);
mDrawerCallback.scrollBy(dy);
}
@ -121,6 +116,13 @@ public class UserProfileDrawer extends ViewGroup {
mDrawerCallback.cancelTouch();
}
@Override
protected void onFinishInflate() {
if (getChildCount() != 1) {
throw new IllegalArgumentException("Add subview by XML is not allowed.");
}
}
private boolean canScrollCallback(float dy) {
return mDrawerCallback.canScroll(dy);
}
@ -140,7 +142,6 @@ public class UserProfileDrawer extends ViewGroup {
mTouchDown = true;
mTouchingScrollableContent = isScrollContentCallback(ev.getX(), ev.getY());
mUsingDragHelper = false;
mScrollingHeaderByGesture = false;
break;
}
case MotionEvent.ACTION_CANCEL:
@ -148,7 +149,6 @@ public class UserProfileDrawer extends ViewGroup {
mTouchDown = false;
mTouchingScrollableContent = false;
mUsingDragHelper = false;
mScrollingHeaderByGesture = false;
}
}
mGestureDetector.onTouchEvent(ev);
@ -172,6 +172,7 @@ public class UserProfileDrawer extends ViewGroup {
final int top = i == 0 ? mHeaderOffset + getPaddingTop() : getChildAt(i - 1).getBottom();
final int bottom = top + child.getMeasuredHeight();
child.layout(left, top, right, bottom);
notifyOffsetChanged();
}
}
@ -185,17 +186,6 @@ public class UserProfileDrawer extends ViewGroup {
return mContainer.getHeader();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final View child = getChildAt(0);
final int childWidthMeasureSpec = makeChildMeasureSpec(widthMeasureSpec, getPaddingLeft() + getPaddingRight());
final int childHeightMeasureSpec = makeChildMeasureSpec(heightMeasureSpec, getPaddingTop() + getPaddingBottom());
child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
public View getContent() {
return mContainer.getContent();
}
@ -222,6 +212,17 @@ public class UserProfileDrawer extends ViewGroup {
return mContainer.getHeaderTopMinimum();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final View child = getChildAt(0);
final int childWidthMeasureSpec = makeChildMeasureSpec(widthMeasureSpec, getPaddingLeft() + getPaddingRight());
final int childHeightMeasureSpec = makeChildMeasureSpec(heightMeasureSpec, getPaddingTop() + getPaddingBottom());
child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
private boolean isTouchingScrollableContent() {
return mTouchingScrollableContent;
}
@ -240,6 +241,18 @@ public class UserProfileDrawer extends ViewGroup {
return Math.abs(direction) > getDragTouchSlop() && Math.abs(direction) > Math.abs(other);
}
private boolean isScrollingHeaderByHelper() {
return mDragCallback.isScrollingHeaderByHelper();
}
private boolean isScrollingContentCallback() {
return mScrollingContentCallback;
}
private void setScrollingContentCallback(boolean scrolling) {
mScrollingContentCallback = scrolling;
}
public static interface DrawerCallback {
void fling(float velocity);
@ -260,7 +273,7 @@ public class UserProfileDrawer extends ViewGroup {
private final UserProfileDrawer mDrawer;
private long mTime;
private float mDx, mDy, mVelocity;
private boolean mScrollingByHelper;
private boolean mScrollingHeaderByHelper;
public DragCallback(UserProfileDrawer drawer) {
mDrawer = drawer;
@ -275,7 +288,7 @@ public class UserProfileDrawer extends ViewGroup {
switch (state) {
case ViewDragHelper.STATE_SETTLING:
case ViewDragHelper.STATE_DRAGGING: {
mScrollingByHelper = false;
mScrollingHeaderByHelper = false;
break;
}
case ViewDragHelper.STATE_IDLE: {
@ -289,7 +302,7 @@ public class UserProfileDrawer extends ViewGroup {
mDx = Float.NaN;
mDy = Float.NaN;
mVelocity = Float.NaN;
mScrollingByHelper = false;
mScrollingHeaderByHelper = false;
break;
}
}
@ -331,31 +344,33 @@ public class UserProfileDrawer extends ViewGroup {
}
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
public int clampViewPositionVertical(final View child, final int top, final int dy) {
final int current = mDrawer.getHeaderTop();
if (!Float.isNaN(mDx) && mDrawer.isValidScroll(mDx, dy)) {
mScrollingByHelper = false;
mScrollingHeaderByHelper = false;
return current;
}
if (dy > 0 && mDrawer.canScrollCallback(-dy) && !mDrawer.isUsingDragHelper()) {
// Scrolling up while list still has space to scroll, so make header still
mScrollingByHelper = false;
return current;
} else if (dy > 0 && mDrawer.canScrollCallback(-dy) && mDrawer.isTouchingScrollableContent()) {
mDrawer.scrollByCallback(-dy);
mScrollingByHelper = false;
return current;
if (dy > 0 && mDrawer.canScrollCallback(-dy)) {
if (!mDrawer.isUsingDragHelper()) {
// Scrolling up while list still has space to scroll, so make header still
mScrollingHeaderByHelper = false;
return current;
} else if (mDrawer.isTouchingScrollableContent()) {
mDrawer.scrollByCallback(-dy);
mScrollingHeaderByHelper = false;
return current;
}
}
final int min = mDrawer.getHeaderTopMinimum(), max = mDrawer.getHeaderTopMaximum();
if (top < min && mDrawer.isTouchingScrollableContent()) {
if (top < min && mDrawer.isTouchingScrollableContent() && mDrawer.isUsingDragHelper()) {
mDrawer.scrollByCallback(-dy);
}
mScrollingByHelper = true;
mScrollingHeaderByHelper = true;
return MathUtils.clamp(top, min, max);
}
private boolean isScrollingByHelper() {
return mScrollingByHelper;
private boolean isScrollingHeaderByHelper() {
return mScrollingHeaderByHelper;
}
}
@ -373,14 +388,14 @@ public class UserProfileDrawer extends ViewGroup {
final int offset = mDrawer.getHeaderTop(), min = mDrawer.getHeaderTopMinimum();
if (!mDrawer.canScrollCallback(-1)) {
if (distanceY < 0) {
if (!mDrawer.mDragCallback.isScrollingByHelper()) {
if (!mDrawer.isScrollingHeaderByHelper()) {
mDrawer.offsetHeaderBy(Math.round(-distanceY));
}
mDrawer.setScrollingHeaderByGesture(true);
} else if (distanceY > 0 && offset > min) {
// Scrolling up when scrolling to list top, so we cancel touch event and scrolling header up
mDrawer.cancelTouchCallback();
if (!mDrawer.mDragCallback.isScrollingByHelper()) {
if (!mDrawer.isScrollingHeaderByHelper()) {
mDrawer.offsetHeaderBy(Math.round(-distanceY));
}
} else if (offset <= min) {
@ -393,12 +408,13 @@ public class UserProfileDrawer extends ViewGroup {
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
final int top = mDrawer.getHeaderTop(), min = mDrawer.getHeaderTopMinimum();
if (velocityY > 0 && !mDrawer.canScrollCallback(-1)) {
// Fling down when list reached top, so we fling header down here
if (Math.abs(velocityY) > Math.abs(velocityX)) {
mDrawer.flingHeader(velocityY);
}
} else if (velocityY < 0 && mDrawer.getHeaderTop() <= mDrawer.getHeaderTopMinimum()) {
} else if (velocityY < 0 && top <= min && mDrawer.isScrollingContentCallback()) {
// Fling up when showing full content, so we fling list up here
if (Math.abs(velocityY) > Math.abs(velocityX)) {
mDrawer.flingCallback(-velocityY);
@ -409,6 +425,8 @@ public class UserProfileDrawer extends ViewGroup {
@Override
public boolean onDown(MotionEvent e) {
mDrawer.setScrollingHeaderByGesture(false);
mDrawer.setScrollingContentCallback(false);
return true;
}
}

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Twidere - Twitter client for Android
~
~ Copyright (C) 2012-2014 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/>.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="@color/bg_color_tab_pressed"/>
<item android:state_focused="true" android:drawable="@color/bg_color_tab_pressed"/>
<item android:drawable="@android:color/transparent"/>
</selector>

View File

@ -20,6 +20,7 @@
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
@ -27,7 +28,8 @@
<com.astuetz.PagerSlidingTabStrip
android:id="@+id/view_pager_tabs"
android:layout_width="match_parent"
android:layout_height="@dimen/element_size_normal"/>
android:layout_height="@dimen/element_size_normal"
app:pstsTabBackground="?android:selectableItemBackground"/>
<android.support.v4.view.ViewPager
android:id="@+id/view_pager"

View File

@ -219,34 +219,6 @@
android:showDividers="middle"
android:splitMotionEvents="false">
<LinearLayout
android:id="@+id/tweets_container"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="?android:selectableItemBackground"
android:clickable="true"
android:gravity="center"
android:orientation="vertical"
android:padding="@dimen/element_spacing_small">
<org.mariotaku.twidere.view.themed.ThemedTextView
android:id="@+id/statuses_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:textAppearance="?android:textAppearanceMedium"
android:textColor="?android:textColorPrimary"/>
<org.mariotaku.twidere.view.themed.ThemedTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:text="@string/statuses"
android:textAppearance="?android:textAppearanceSmall"
android:textColor="?android:textColorSecondary"/>
</LinearLayout>
<LinearLayout
android:id="@+id/followers_container"
android:layout_width="0dp"
@ -302,6 +274,34 @@
android:textAppearance="?android:textAppearanceSmall"
android:textColor="?android:textColorSecondary"/>
</LinearLayout>
<LinearLayout
android:id="@+id/listed_container"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="?android:selectableItemBackground"
android:clickable="true"
android:gravity="center"
android:orientation="vertical"
android:padding="@dimen/element_spacing_small">
<org.mariotaku.twidere.view.themed.ThemedTextView
android:id="@+id/listed_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:textAppearance="?android:textAppearanceMedium"
android:textColor="?android:textColorPrimary"/>
<org.mariotaku.twidere.view.themed.ThemedTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:text="@string/listed"
android:textAppearance="?android:textAppearanceSmall"
android:textColor="?android:textColorSecondary"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</android.support.v7.widget.CardView>

View File

@ -23,5 +23,6 @@
<color name="highlight_reply">@color/material_light_blue</color>
<color name="unread_color">@color/material_red</color>
<color name="branding_color">@color/material_light_blue</color>
<color name="bg_color_tab_pressed">#40808080</color>
</resources>

View File

@ -677,5 +677,6 @@
<string name="replies">Replies</string>
<string name="profile_banner">Profile banner</string>
<string name="profile">Profile</string>
<string name="listed">Listed</string>
</resources>