From 8c6802a9b27318a2caa87cb9fbe83a9502be83ab Mon Sep 17 00:00:00 2001 From: Mariotaku Lee Date: Wed, 29 Oct 2014 14:48:07 +0800 Subject: [PATCH] added account manager refactoring theme --- twidere/src/main/AndroidManifest.xml | 15 + .../levelup/views/gallery/AbsSpinner.java | 517 ------ .../levelup/views/gallery/AdapterView.java | 1182 ------------- .../scvngr/levelup/views/gallery/Gallery.java | 1520 ----------------- .../mariotaku/gallery3d/ui/EdgeEffect.java | 2 +- .../java/org/mariotaku/twidere/Constants.java | 5 +- .../twidere/activity/BaseActivity.java | 3 +- .../twidere/activity/MainActivity.java | 2 +- .../twidere/activity/SettingsActivity.java | 4 +- .../support/AccountsManagerActivity.java | 54 + .../activity/support/BaseSupportActivity.java | 2 +- .../support/BaseSupportThemedActivity.java | 6 +- .../activity/support/ComposeActivity.java | 296 ++-- .../activity/support/DraftsActivity.java | 2 +- .../activity/support/HomeActivity.java | 35 +- .../activity/support/LinkHandlerActivity.java | 2 +- .../activity/support/MenuDialogFragment.java | 26 +- .../twidere/adapter/AccountsAdapter.java | 150 +- .../twidere/adapter/ArrayRecyclerAdapter.java | 67 + .../UserHashtagAutoCompleteAdapter.java | 2 +- .../twidere/dialog/ColorPickerDialog.java | 260 +-- .../support/AccountsDrawerFragment.java | 34 +- .../support/AccountsManagerFragment.java | 82 + .../fragment/support/QuickMenuFragment.java | 2 +- .../fragment/support/UserProfileFragment.java | 2 +- .../preference/ThemePreviewPreference.java | 2 +- .../twidere/provider/TweetStore.java | 6 +- .../mariotaku/twidere/util/ThemeUtils.java | 256 +-- .../org/mariotaku/twidere/util/Utils.java | 36 +- .../twidere/util/menu/StatusMenuInfo.java | 18 + .../twidere/view/HomeActionButton.java | 24 +- .../twidere/view/HomeActionButtonCompat.java | 12 +- .../twidere/view/ListMenuOverflowButton.java | 2 +- .../twidere/view/NavigationArrowButton.java | 2 +- .../twidere/view/TabPagerIndicator.java | 21 +- .../twidere/view/TwidereMenuBar.java | 7 +- .../twidere/view/iface/ICardItemView.java | 2 +- .../twidere/view/iface/IHomeActionButton.java | 5 +- .../themed/ThemedAutoCompleteTextView.java | 5 +- .../twidere/view/themed/ThemedCheckBox.java | 6 +- .../twidere/view/themed/ThemedEditText.java | 5 +- .../ThemedMultiAutoCompleteTextView.java | 5 +- .../view/themed/ThemedRadioButton.java | 24 +- .../twidere/view/themed/ThemedSwitch.java | 6 +- .../twidere/view/themed/ThemedTextView.java | 6 +- .../res/drawable-v21/btn_home_actions.xml | 8 - .../layout-v21/layout_home_actions_button.xml | 1 - .../main/res/layout/action_item_compose.xml | 11 +- .../res/layout/action_item_home_actions.xml | 36 +- .../action_item_home_actions_compat.xml | 22 + .../res/layout/activity_compose_actionbar.xml | 22 +- .../res/layout/activity_compose_bottombar.xml | 39 +- ...dler.xml => activity_content_fragment.xml} | 2 +- .../main/res/layout/activity_home_content.xml | 4 +- .../main/res/layout/dialog_color_picker.xml | 2 +- .../res/layout/fragment_accounts_manager.xml | 20 + .../layout/gallery_item_compose_account.xml | 36 +- .../src/main/res/layout/list_item_account.xml | 127 +- .../main/res/layout/list_item_custom_tab.xml | 90 +- .../res/layout/list_item_drawer_accounts.xml | 184 +- .../main/res/menu/menu_accounts_manager.xml | 9 + twidere/src/main/res/values/themes.xml | 188 +- 62 files changed, 1153 insertions(+), 4370 deletions(-) delete mode 100644 twidere/src/main/java/com/scvngr/levelup/views/gallery/AbsSpinner.java delete mode 100644 twidere/src/main/java/com/scvngr/levelup/views/gallery/AdapterView.java delete mode 100644 twidere/src/main/java/com/scvngr/levelup/views/gallery/Gallery.java create mode 100644 twidere/src/main/java/org/mariotaku/twidere/activity/support/AccountsManagerActivity.java create mode 100644 twidere/src/main/java/org/mariotaku/twidere/adapter/ArrayRecyclerAdapter.java create mode 100644 twidere/src/main/java/org/mariotaku/twidere/fragment/support/AccountsManagerFragment.java create mode 100644 twidere/src/main/java/org/mariotaku/twidere/util/menu/StatusMenuInfo.java delete mode 100644 twidere/src/main/res/drawable-v21/btn_home_actions.xml create mode 100644 twidere/src/main/res/layout/action_item_home_actions_compat.xml rename twidere/src/main/res/layout/{layout_link_handler.xml => activity_content_fragment.xml} (100%) create mode 100644 twidere/src/main/res/layout/fragment_accounts_manager.xml create mode 100644 twidere/src/main/res/menu/menu_accounts_manager.xml diff --git a/twidere/src/main/AndroidManifest.xml b/twidere/src/main/AndroidManifest.xml index ae8cdc888..5bcba65f6 100644 --- a/twidere/src/main/AndroidManifest.xml +++ b/twidere/src/main/AndroidManifest.xml @@ -354,6 +354,21 @@ android:name="android.support.PARENT_ACTIVITY" android:value=".activity.support.HomeActivity"/> + + + + + + + + + { - - SpinnerAdapter mAdapter; - - int mHeightMeasureSpec; - int mWidthMeasureSpec; - boolean mBlockLayoutRequests; - int mSelectionLeftPadding = 0; - int mSelectionTopPadding = 0; - int mSelectionRightPadding = 0; - int mSelectionBottomPadding = 0; - Rect mSpinnerPadding = new Rect(); - View mSelectedView = null; - Interpolator mInterpolator; - - RecycleBin mRecycler = new RecycleBin(); - private DataSetObserver mDataSetObserver; - - /* - * Temporary frame to hold a child View's frame rectangle. - */ - private Rect mTouchFrame; - - /** - * Constructor. - * - * @param context the context to inflate into - */ - public AbsSpinner(final Context context) { - super(context); - initAbsSpinner(); - } - - /** - * Constructor for xml inflation. - * - * @param context the context to inflate into - * @param attrs the xml attrs - */ - public AbsSpinner(final Context context, final AttributeSet attrs) { - this(context, attrs, 0); - } - - /** - * Constructor for xml inflation. - * - * @param context the context to inflate into - * @param attrs the xml attrs - * @param defStyle the default style resource - */ - public AbsSpinner(final Context context, final AttributeSet attrs, final int defStyle) { - super(context, attrs, defStyle); - initAbsSpinner(); - } - - @Override - public final SpinnerAdapter getAdapter() { - return mAdapter; - } - - @Override - public final int getCount() { - return mItemCount; - } - - @Override - public final View getSelectedView() { - if (mItemCount > 0 && mSelectedPosition >= 0) - return getChildAt(mSelectedPosition - mFirstPosition); - else - return null; - } - - @Override - public void onRestoreInstanceState(final Parcelable state) { - final SavedState ss = (SavedState) state; - - super.onRestoreInstanceState(ss.getSuperState()); - - if (ss.selectedId >= 0) { - mDataChanged = true; - mNeedSync = true; - mSyncRowId = ss.selectedId; - mSyncPosition = ss.position; - mSyncMode = SYNC_SELECTED_POSITION; - requestLayout(); - } - } - - @Override - public Parcelable onSaveInstanceState() { - final Parcelable superState = super.onSaveInstanceState(); - final SavedState ss = new SavedState(superState); - ss.selectedId = getSelectedItemId(); - if (ss.selectedId >= 0) { - ss.position = getSelectedItemPosition(); - } else { - ss.position = INVALID_POSITION; - } - return ss; - } - - /** - * Maps a point to a position in the list. - * - * @param x X in local coordinate - * @param y Y in local coordinate - * @return The position of the item which contains the specified point, or - * {@link #INVALID_POSITION} if the point does not intersect an - * item. - */ - public final int pointToPosition(final int x, final int y) { - Rect frame = mTouchFrame; - if (frame == null) { - mTouchFrame = new Rect(); - frame = mTouchFrame; - } - - final int count = getChildCount(); - for (int i = count - 1; i >= 0; i--) { - final View child = getChildAt(i); - if (child.getVisibility() == View.VISIBLE) { - child.getHitRect(frame); - if (frame.contains(x, y)) return mFirstPosition + i; - } - } - return INVALID_POSITION; - } - - /** - * Override to prevent spamming ourselves with layout requests as we place - * views. - * - * @see android.view.View#requestLayout() - */ - @Override - public final void requestLayout() { - if (!mBlockLayoutRequests) { - super.requestLayout(); - } - } - - /** - * The Adapter is used to provide the data which backs this Spinner. It also - * provides methods to transform spinner items based on their position - * relative to the selected item. - * - * @param adapter The SpinnerAdapter to use for this Spinner - */ - // CHECKSTYLE:OFF unmodified - @Override - public void setAdapter(final SpinnerAdapter adapter) { - if (null != mAdapter) { - mAdapter.unregisterDataSetObserver(mDataSetObserver); - resetList(); - } - - mAdapter = adapter; - - mOldSelectedPosition = INVALID_POSITION; - mOldSelectedRowId = INVALID_ROW_ID; - - if (mAdapter != null) { - mOldItemCount = mItemCount; - mItemCount = mAdapter.getCount(); - checkFocus(); - - mDataSetObserver = new AdapterDataSetObserver(); - mAdapter.registerDataSetObserver(mDataSetObserver); - - final int position = mItemCount > 0 ? 0 : INVALID_POSITION; - - setSelectedPositionInt(position); - setNextSelectedPositionInt(position); - - if (mItemCount == 0) { - // Nothing selected - checkSelectionChanged(); - } - - } else { - checkFocus(); - resetList(); - // Nothing selected - checkSelectionChanged(); - } - - requestLayout(); - } - - // CHECKSTYLE:ON - - @Override - public final void setSelection(final int position) { - setNextSelectedPositionInt(position); - requestLayout(); - invalidate(); - } - - /** - * Jump directly to a specific item in the adapter data. - * - * @param position the position to select - * @param animate if true, animate the selection - */ - public final void setSelection(final int position, final boolean animate) { - // Animate only if requested position is already on screen somewhere - final boolean shouldAnimate = animate && mFirstPosition <= position - && position <= mFirstPosition + getChildCount() - 1; - setSelectionInt(position, shouldAnimate); - } - - // CHECKSTYLE:OFF overridden in gallery - @Override - protected ViewGroup.LayoutParams generateDefaultLayoutParams() { - // CHECKSTYLE:ON - return new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); - } - - /** - * @see android.view.View#measure(int, int) - * - * Figure out the dimensions of this Spinner. The width comes from the - * widthMeasureSpec as Spinnners can't have their width set to - * UNSPECIFIED. The height is based on the height of the selected item - * plus padding. - */ - // CHECKSTYLE:OFF unmodified - @Override - protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { - final int widthMode = MeasureSpec.getMode(widthMeasureSpec); - int widthSize; - int heightSize; - - mSpinnerPadding.left = getPaddingLeft() > mSelectionLeftPadding ? getPaddingLeft() : mSelectionLeftPadding; - mSpinnerPadding.top = getPaddingTop() > mSelectionTopPadding ? getPaddingTop() : mSelectionTopPadding; - mSpinnerPadding.right = getPaddingRight() > mSelectionRightPadding ? getPaddingRight() : mSelectionRightPadding; - mSpinnerPadding.bottom = getPaddingBottom() > mSelectionBottomPadding ? getPaddingBottom() - : mSelectionBottomPadding; - - if (mDataChanged) { - handleDataChanged(); - } - - int preferredHeight = 0; - int preferredWidth = 0; - boolean needsMeasuring = true; - - final int selectedPosition = getSelectedItemPosition(); - if (selectedPosition >= 0 && mAdapter != null) { - // Try looking in the recycler. (Maybe we were measured once - // already) - View view = mRecycler.get(selectedPosition); - if (view == null) { - // Make a new one - view = mAdapter.getView(selectedPosition, null, this); - } - - if (view != null) { - // Put in recycler for re-measuring and/or layout - mRecycler.put(selectedPosition, view); - } - - if (view != null) { - if (view.getLayoutParams() == null) { - mBlockLayoutRequests = true; - view.setLayoutParams(generateDefaultLayoutParams()); - mBlockLayoutRequests = false; - } - measureChild(view, widthMeasureSpec, heightMeasureSpec); - - preferredHeight = getChildHeight(view) + mSpinnerPadding.top + mSpinnerPadding.bottom; - preferredWidth = getChildWidth(view) + mSpinnerPadding.left + mSpinnerPadding.right; - - needsMeasuring = false; - } - } - - if (needsMeasuring) { - // No views -- just use padding - preferredHeight = mSpinnerPadding.top + mSpinnerPadding.bottom; - if (widthMode == MeasureSpec.UNSPECIFIED) { - preferredWidth = mSpinnerPadding.left + mSpinnerPadding.right; - } - } - - preferredHeight = Math.max(preferredHeight, getSuggestedMinimumHeight()); - preferredWidth = Math.max(preferredWidth, getSuggestedMinimumWidth()); - - heightSize = resolveSize(preferredHeight, heightMeasureSpec); - widthSize = resolveSize(preferredWidth, widthMeasureSpec); - - setMeasuredDimension(widthSize, heightSize); - mHeightMeasureSpec = heightMeasureSpec; - mWidthMeasureSpec = widthMeasureSpec; - } - - // CHECKSTYLE:ON - - /** - * Common code for different constructor flavors. - */ - private void initAbsSpinner() { - setFocusable(true); - setWillNotDraw(false); - } - - /** - * Gets the height of the child view passed. - * - * @param child the child to get the height of - * @return the child's measured height - */ - final int getChildHeight(final View child) { - return child.getMeasuredHeight(); - } - - /** - * Gets the width of the child view passed. - * - * @param child the child to get the width of - * @return the child's measure width - */ - final int getChildWidth(final View child) { - return child.getMeasuredWidth(); - } - - @Override - final void handleDataChanged() { - /* - * FIXME -- this is called from both measure and layout. This is - * harmless right now, but we don't want to do redundant work if this - * gets more complicated - */ - super.handleDataChanged(); - } - - // CHECKSTYLE:OFF unmodified - abstract void layout(int delta, boolean animate); - - // CHECKSTYLE:ON - - /** - * Recycle all child views. - */ - final void recycleAllViews() { - final int childCount = getChildCount(); - final AbsSpinner.RecycleBin recycleBin = mRecycler; - - // All views go in recycler - for (int i = 0; i < childCount; i++) { - final View v = getChildAt(i); - final int index = mFirstPosition + i; - recycleBin.put(index, v); - } - } - - /** - * Clear out all children from the list. - */ - final void resetList() { - mDataChanged = false; - mNeedSync = false; - - removeAllViewsInLayout(); - mOldSelectedPosition = INVALID_POSITION; - mOldSelectedRowId = INVALID_ROW_ID; - - setSelectedPositionInt(INVALID_POSITION); - setNextSelectedPositionInt(INVALID_POSITION); - invalidate(); - } - - /** - * Makes the item at the supplied position selected. - * - * @param position Position to select - * @param animate Should the transition be animated - * - */ - final void setSelectionInt(final int position, final boolean animate) { - if (position != mOldSelectedPosition) { - mBlockLayoutRequests = true; - final int delta = position - mSelectedPosition; - setNextSelectedPositionInt(position); - layout(delta, animate); - mBlockLayoutRequests = false; - } - } - - class RecycleBin { - private final SparseArray mScrapHeap = new SparseArray(); - - public void put(final int position, final View v) { - mScrapHeap.put(position, v); - } - - void clear() { - final SparseArray scrapHeap = mScrapHeap; - final int count = scrapHeap.size(); - for (int i = 0; i < count; i++) { - final View view = scrapHeap.valueAt(i); - if (view != null) { - removeDetachedView(view, true); - } - } - scrapHeap.clear(); - } - - View get(final int position) { - // System.out.print("Looking for " + position); - final View result = mScrapHeap.get(position); - if (result != null) { - // System.out.println(" HIT"); - mScrapHeap.delete(position); - } else { - // System.out.println(" MISS"); - } - return result; - } - - View peek(final int position) { - // System.out.print("Looking for " + position); - return mScrapHeap.get(position); - } - } - - // CHECKSTYLE:ON - - // CHECKSTYLE:OFF unmodified - static class SavedState extends BaseSavedState { - long selectedId; - int position; - - public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { - @Override - public SavedState createFromParcel(final Parcel in) { - return new SavedState(in); - } - - @Override - public SavedState[] newArray(final int size) { - return new SavedState[size]; - } - }; - - /** - * Constructor called from {@link #CREATOR} - */ - private SavedState(final Parcel in) { - super(in); - selectedId = in.readLong(); - position = in.readInt(); - } - - /** - * Constructor called from {@link AbsSpinner#onSaveInstanceState()} - */ - SavedState(final Parcelable superState) { - super(superState); - } - - @Override - public String toString() { - return "AbsSpinner.SavedState{" + Integer.toHexString(System.identityHashCode(this)) + " selectedId=" - + selectedId + " position=" + position + "}"; - } - - @Override - public void writeToParcel(final Parcel out, final int flags) { - super.writeToParcel(out, flags); - out.writeLong(selectedId); - out.writeInt(position); - } - } -} diff --git a/twidere/src/main/java/com/scvngr/levelup/views/gallery/AdapterView.java b/twidere/src/main/java/com/scvngr/levelup/views/gallery/AdapterView.java deleted file mode 100644 index c3fdb446e..000000000 --- a/twidere/src/main/java/com/scvngr/levelup/views/gallery/AdapterView.java +++ /dev/null @@ -1,1182 +0,0 @@ -/* - * Modified from the Android Source code. The example for how to do so was viewed here: - * http://www.inter-fuser.com/2010/01/android-coverflow-widget.html - * - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.scvngr.levelup.views.gallery; - -// CHECKSTYLE:OFF -import android.annotation.SuppressLint; -import android.content.Context; -import android.database.DataSetObserver; -import android.os.Handler; -import android.os.Parcelable; -import android.os.SystemClock; -import android.util.AttributeSet; -import android.util.SparseArray; -import android.view.ContextMenu; -import android.view.ContextMenu.ContextMenuInfo; -import android.view.SoundEffectConstants; -import android.view.View; -import android.view.ViewDebug; -import android.view.ViewGroup; -import android.widget.Adapter; -import android.widget.GridView; -import android.widget.ListView; -import android.widget.Spinner; - -// CHECKSTYLE:ON - -/** - * An AdapterView is a view whose children are determined by an {@link Adapter}. - * - *

- * See {@link ListView}, {@link GridView}, {@link Spinner} and {@link Gallery} - * for commonly used subclasses of AdapterView. - */ -// CHECKSTYLE:OFF android comment -public abstract class AdapterView extends ViewGroup { - // CHECKSTYLE:ON - /** - * The item view type returned by {@link Adapter#getItemViewType(int)} when - * the adapter does not want the item's view recycled. - */ - public static final int ITEM_VIEW_TYPE_IGNORE = -1; - - /** - * The item view type returned by {@link Adapter#getItemViewType(int)} when - * the item is a header or footer. - */ - public static final int ITEM_VIEW_TYPE_HEADER_OR_FOOTER = -2; - - /** - * The position of the first child displayed. - */ - @ViewDebug.ExportedProperty - int mFirstPosition = 0; - - /** - * The offset in pixels from the top of the AdapterView to the top of the - * view to select during the next layout. - */ - int mSpecificTop; - - /** - * Position from which to start looking for mSyncRowId. - */ - int mSyncPosition; - - /** - * Row id to look for when data has changed. - */ - long mSyncRowId = INVALID_ROW_ID; - - /** - * Height of the view when mSyncPosition and mSyncRowId where set. - */ - long mSyncHeight; - - /** - * True if we need to sync to mSyncRowId. - */ - boolean mNeedSync = false; - - /** - * Indicates whether to sync based on the selection or position. Possible - * values are {@link #SYNC_SELECTED_POSITION} or - * {@link #SYNC_FIRST_POSITION}. - */ - int mSyncMode; - - /** - * Our height after the last layout. - */ - private int mLayoutHeight; - - /** - * Sync based on the selected child. - */ - static final int SYNC_SELECTED_POSITION = 0; - - /** - * Sync based on the first child displayed. - */ - static final int SYNC_FIRST_POSITION = 1; - - /** - * Maximum amount of time to spend in {@link #findSyncPosition()}. - */ - static final int SYNC_MAX_DURATION_MILLIS = 100; - - /** - * Indicates that this view is currently being laid out. - */ - boolean mInLayout = false; - - /** - * The listener that receives notifications when an item is selected. - */ - OnItemSelectedListener mOnItemSelectedListener; - - /** - * The listener that receives notifications when an item is clicked. - */ - OnItemClickListener mOnItemClickListener; - - /** - * The listener that receives notifications when an item is long clicked. - */ - OnItemLongClickListener mOnItemLongClickListener; - - /** - * True if the data has changed since the last layout. - */ - boolean mDataChanged; - - /** - * The position within the adapter's data set of the item to select during - * the next layout. - */ - @ViewDebug.ExportedProperty - int mNextSelectedPosition = INVALID_POSITION; - - /** - * The item id of the item to select during the next layout. - */ - long mNextSelectedRowId = INVALID_ROW_ID; - - /** - * The position within the adapter's data set of the currently selected - * item. - */ - @ViewDebug.ExportedProperty - int mSelectedPosition = INVALID_POSITION; - - /** - * The item id of the currently selected item. - */ - long mSelectedRowId = INVALID_ROW_ID; - - /** - * View to show if there are no items to show. - */ - View mEmptyView; - - /** - * The number of items in the current adapter. - */ - @ViewDebug.ExportedProperty - int mItemCount; - - /** - * The number of items in the adapter before a data changed event occured. - */ - int mOldItemCount; - - /** - * Represents an invalid position. All valid positions are in the range 0 to - * 1 less than the number of items in the current adapter. - */ - public static final int INVALID_POSITION = -1; - - /** - * Represents an empty or invalid row id. - */ - public static final long INVALID_ROW_ID = Long.MIN_VALUE; - - /** - * The last selected position we used when notifying. - */ - int mOldSelectedPosition = INVALID_POSITION; - - /** - * The id of the last selected position we used when notifying. - */ - long mOldSelectedRowId = INVALID_ROW_ID; - - /** - * Indicates what focusable state is requested when calling setFocusable(). - * In addition to this, this view has other criteria for actually - * determining the focusable state (such as whether its empty or the text - * filter is shown). - * - * @see #setFocusable(boolean) - * @see #checkFocus() - */ - private boolean mDesiredFocusableState; - private boolean mDesiredFocusableInTouchModeState; - - private SelectionNotifier mSelectionNotifier; - /** - * When set to true, calls to requestLayout() will not propagate up the - * parent hierarchy. This is used to layout the children during a layout - * pass. - */ - boolean mBlockLayoutRequests = false; - - /** - * Constructor. - * - * @param context the context to inflate with - */ - public AdapterView(final Context context) { - super(context); - } - - /** - * Constructor for xml inflation. - * - * @param context the context to inflate with - * @param attrs the xml attrs - */ - public AdapterView(final Context context, final AttributeSet attrs) { - super(context, attrs); - } - - /** - * Constructor for xml inflation. - * - * @param context the contex to inflate with - * @param attrs the xml attrs - * @param defStyle the default style resource - */ - public AdapterView(final Context context, final AttributeSet attrs, final int defStyle) { - super(context, attrs, defStyle); - } - - /** - * This method is not supported and throws an UnsupportedOperationException - * when called. - * - * @param child Ignored. - * - * @throws UnsupportedOperationException Every time this method is invoked. - */ - @Override - public final void addView(final View child) { - throw new UnsupportedOperationException("addView(View) is not supported in AdapterView"); - } - - /** - * This method is not supported and throws an UnsupportedOperationException - * when called. - * - * @param child Ignored. - * @param index Ignored. - * - * @throws UnsupportedOperationException Every time this method is invoked. - */ - @Override - public final void addView(final View child, final int index) { - throw new UnsupportedOperationException("addView(View, int) is " + "not supported in AdapterView"); - } - - /** - * This method is not supported and throws an UnsupportedOperationException - * when called. - * - * @param child Ignored. - * @param index Ignored. - * @param params Ignored. - * - * @throws UnsupportedOperationException Every time this method is invoked. - */ - @Override - public final void addView(final View child, final int index, final LayoutParams params) { - throw new UnsupportedOperationException("addView(View, int, LayoutParams) " + "is not supported in AdapterView"); - } - - /** - * This method is not supported and throws an UnsupportedOperationException - * when called. - * - * @param child Ignored. - * @param params Ignored. - * - * @throws UnsupportedOperationException Every time this method is invoked. - */ - @Override - public final void addView(final View child, final LayoutParams params) { - throw new UnsupportedOperationException("addView(View, LayoutParams) " + "is not supported in AdapterView"); - } - - /** - * Returns the adapter currently associated with this widget. - * - * @return The adapter used to provide this view's content. - */ - public abstract T getAdapter(); - - /** - * @return The number of items owned by the Adapter associated with this - * AdapterView. (This is the number of data items, which may be - * larger than the number of visible view.) - */ - // CHECKSTYLE:OFF overridden in subclass - // @ViewDebug.CapturedViewProperty - public int getCount() { - return mItemCount; - } - - // CHECKSTYLE:ON - - /** - * When the current adapter is empty, the AdapterView can display a special - * view call the empty view. The empty view is used to provide feedback to - * the user that no data is available in this AdapterView. - * - * @return The view to show if the adapter is empty. - */ - public final View getEmptyView() { - return mEmptyView; - } - - /** - * Returns the position within the adapter's data set for the first item - * displayed on screen. - * - * @return The position within the adapter's data set - */ - public final int getFirstVisiblePosition() { - return mFirstPosition; - } - - /** - * Gets the data associated with the specified position in the list. - * - * @param position Which data to get - * @return The data associated with the specified position in the list - */ - // CHECKSTYLE:OFF unmodified - public Object getItemAtPosition(final int position) { - final T adapter = getAdapter(); - return adapter == null || position < 0 ? null : adapter.getItem(position); - } - - public long getItemIdAtPosition(final int position) { - final T adapter = getAdapter(); - return adapter == null || position < 0 ? INVALID_ROW_ID : adapter.getItemId(position); - } - - // CHECKSTYLE:ON - - /** - * Returns the position within the adapter's data set for the last item - * displayed on screen. - * - * @return The position within the adapter's data set - */ - public final int getLastVisiblePosition() { - return mFirstPosition + getChildCount() - 1; - } - - /** - * @return The callback to be invoked with an item in this AdapterView has - * been clicked, or null id no callback has been set. - */ - public final OnItemClickListener getOnItemClickListener() { - return mOnItemClickListener; - } - - /** - * @return The callback to be invoked with an item in this AdapterView has - * been clicked and held, or null id no callback as been set. - */ - public final OnItemLongClickListener getOnItemLongClickListener() { - return mOnItemLongClickListener; - } - - /** - * Gets the OnItemSelected listener. - * - * @return the {@link OnItemSelectedListener} - */ - public final OnItemSelectedListener getOnItemSelectedListener() { - return mOnItemSelectedListener; - } - - /** - * Get the position within the adapter's data set for the view, where view - * is a an adapter item or a descendant of an adapter item. - * - * @param view an adapter item, or a descendant of an adapter item. This - * must be visible in this AdapterView at the time of the call. - * @return the position within the adapter's data set of the view, or - * {@link #INVALID_POSITION} if the view does not correspond to a - * list item (or it is not currently visible). - */ - public final int getPositionForView(final View view) { - View listItem = view; - try { - View v; - // CHECKSTYLE:OFF unmodified - while (!(v = (View) listItem.getParent()).equals(this)) { - // CHECKSTYLE:ON - listItem = v; - } - } catch (final ClassCastException e) { - // We made it up to the window without find this list view - return INVALID_POSITION; - } - - // Search the children for the list item - final int childCount = getChildCount(); - for (int i = 0; i < childCount; i++) { - if (getChildAt(i).equals(listItem)) return mFirstPosition + i; - } - - // Child not found! - return INVALID_POSITION; - } - - /** - * @return The data corresponding to the currently selected item, or null if - * there is nothing selected. - */ - public final Object getSelectedItem() { - final T adapter = getAdapter(); - final int selection = getSelectedItemPosition(); - if (adapter != null && adapter.getCount() > 0 && selection >= 0) - return adapter.getItem(selection); - else - return null; - } - - /** - * @return The id corresponding to the currently selected item, or - * {@link #INVALID_ROW_ID} if nothing is selected. - */ - // @ViewDebug.CapturedViewProperty - public final long getSelectedItemId() { - return mNextSelectedRowId; - } - - /** - * Return the position of the currently selected item within the adapter's - * data set. - * - * @return int Position (starting at 0), or {@link #INVALID_POSITION} if - * there is nothing selected. - */ - // @ViewDebug.CapturedViewProperty - public final int getSelectedItemPosition() { - return mNextSelectedPosition; - } - - /** - * @return The view corresponding to the currently selected item, or null if - * nothing is selected - */ - public abstract View getSelectedView(); - - /** - * Call the OnItemClickListener, if it is defined. - * - * @param view The view within the AdapterView that was clicked. - * @param position The position of the view in the adapter. - * @param id The row id of the item that was clicked. - * @return True if there was an assigned OnItemClickListener that was - * called, false otherwise is returned. - */ - public final boolean performItemClick(final View view, final int position, final long id) { - if (mOnItemClickListener != null) { - playSoundEffect(SoundEffectConstants.CLICK); - mOnItemClickListener.onItemClick(this, view, position, id); - return true; - } - - return false; - } - - /** - * This method is not supported and throws an UnsupportedOperationException - * when called. - * - * @throws UnsupportedOperationException Every time this method is invoked. - */ - @Override - public final void removeAllViews() { - throw new UnsupportedOperationException("removeAllViews() is not supported in AdapterView"); - } - - /** - * This method is not supported and throws an UnsupportedOperationException - * when called. - * - * @param child Ignored. - * - * @throws UnsupportedOperationException Every time this method is invoked. - */ - @Override - public final void removeView(final View child) { - throw new UnsupportedOperationException("removeView(View) is not supported in AdapterView"); - } - - /** - * This method is not supported and throws an UnsupportedOperationException - * when called. - * - * @param index Ignored. - * - * @throws UnsupportedOperationException Every time this method is invoked. - */ - @Override - public final void removeViewAt(final int index) { - throw new UnsupportedOperationException("removeViewAt(int) is not supported in AdapterView"); - } - - /** - * Sets the adapter that provides the data and the views to represent the - * data in this widget. - * - * @param adapter The adapter to use to create this view's content. - */ - public abstract void setAdapter(T adapter); - - /** - * Sets the view to show if the adapter is empty. - * - * @param emptyView the view to show when the adapter is empty - */ - public final void setEmptyView(final View emptyView) { - mEmptyView = emptyView; - - final T adapter = getAdapter(); - final boolean empty = adapter == null || adapter.isEmpty(); - updateEmptyStatus(empty); - } - - @Override - public final void setFocusable(final boolean focusable) { - final T adapter = getAdapter(); - final boolean empty = adapter == null || adapter.getCount() == 0; - - mDesiredFocusableState = focusable; - if (!focusable) { - mDesiredFocusableInTouchModeState = false; - } - - super.setFocusable(focusable && (!empty || isInFilterMode())); - } - - @Override - public final void setFocusableInTouchMode(final boolean focusable) { - final T adapter = getAdapter(); - final boolean empty = adapter == null || adapter.getCount() == 0; - - mDesiredFocusableInTouchModeState = focusable; - if (focusable) { - mDesiredFocusableState = true; - } - - super.setFocusableInTouchMode(focusable && (!empty || isInFilterMode())); - } - - @Override - public final void setOnClickListener(final OnClickListener l) { - throw new RuntimeException("Don't call setOnClickListener for an AdapterView. " - + "You probably want setOnItemClickListener instead"); - } - - /** - * Register a callback to be invoked when an item in this AdapterView has - * been clicked. - * - * @param listener The callback that will be invoked. - */ - public final void setOnItemClickListener(final OnItemClickListener listener) { - mOnItemClickListener = listener; - } - - /** - * Register a callback to be invoked when an item in this AdapterView has - * been clicked and held. - * - * @param listener The callback that will run - */ - public final void setOnItemLongClickListener(final OnItemLongClickListener listener) { - if (!isLongClickable()) { - setLongClickable(true); - } - mOnItemLongClickListener = listener; - } - - /** - * Register a callback to be invoked when an item in this AdapterView has - * been selected. - * - * @param listener The callback that will run - */ - public final void setOnItemSelectedListener(final OnItemSelectedListener listener) { - mOnItemSelectedListener = listener; - } - - /** - * Sets the currently selected item. - * - * @param position Index (starting at 0) of the data item to be selected. - */ - public abstract void setSelection(int position); - - @Override - protected final boolean canAnimate() { - return super.canAnimate() && mItemCount > 0; - } - - /** - * Override to prevent thawing of any views created by the adapter. - * - * @param container the container of parcelables to use to restore the state - */ - @Override - protected final void dispatchRestoreInstanceState(final SparseArray container) { - dispatchThawSelfOnly(container); - } - - /** - * Override to prevent freezing of any views created by the adapter. - * - * @param container the container of parcelables to use to save the state. - */ - @Override - protected final void dispatchSaveInstanceState(final SparseArray container) { - dispatchFreezeSelfOnly(container); - } - - // CHECKSTYLE:OFF - @Override - protected void onLayout(final boolean changed, final int left, final int top, final int right, final int bottom) { - mLayoutHeight = getHeight(); - } - - // CHECKSTYLE:ON - - /** - * Fire the onselected listener for the chosen item. - */ - private void fireOnSelected() { - if (mOnItemSelectedListener == null) return; - - final int selection = this.getSelectedItemPosition(); - if (selection >= 0) { - final View v = getSelectedView(); - mOnItemSelectedListener.onItemSelected(this, v, selection, getAdapter().getItemId(selection)); - } else { - mOnItemSelectedListener.onNothingSelected(this); - } - } - - /** - * Update the status of the list based on the empty parameter. If empty is - * true and we have an empty view, display it. In all the other cases, make - * sure that the listview is VISIBLE and that the empty view is GONE (if - * it's not null). - * - */ - // CHECKSTYLE:OFF unmodifed - @SuppressLint("WrongCall") - private void updateEmptyStatus(boolean empty) { - if (isInFilterMode()) { - empty = false; - } - - if (empty) { - if (mEmptyView != null) { - mEmptyView.setVisibility(View.VISIBLE); - setVisibility(View.GONE); - } else { - // If the caller just removed our empty view, make sure the list - // view is visible - setVisibility(View.VISIBLE); - } - - // We are now GONE, so pending layouts will not be dispatched. - // Force one here to make sure that the state of the list matches - // the state of the adapter. - if (mDataChanged) { - this.onLayout(false, getLeft(), getTop(), getRight(), getBottom()); - } - } else { - if (mEmptyView != null) { - mEmptyView.setVisibility(View.GONE); - } - setVisibility(View.VISIBLE); - } - } - - // CHECKSTYLE:ON - - // CHECKSTYLE:OFF unmodified - void checkFocus() { - final T adapter = getAdapter(); - final boolean empty = adapter == null || adapter.getCount() == 0; - final boolean focusable = !empty || isInFilterMode(); - // The order in which we set focusable in touch mode/focusable may - // matter - // for the client, see View.setFocusableInTouchMode() comments for more - // details - super.setFocusableInTouchMode(focusable && mDesiredFocusableInTouchModeState); - super.setFocusable(focusable && mDesiredFocusableState); - if (mEmptyView != null) { - updateEmptyStatus(adapter == null || adapter.isEmpty()); - } - } - - // CHECKSTYLE:ON - - void checkSelectionChanged() { - if (mSelectedPosition != mOldSelectedPosition || mSelectedRowId != mOldSelectedRowId) { - selectionChanged(); - mOldSelectedPosition = mSelectedPosition; - mOldSelectedRowId = mSelectedRowId; - } - } - - // CHECKSTYLE:ON - - /** - * Searches the adapter for a position matching mSyncRowId. The search - * starts at mSyncPosition and then alternates between moving up and moving - * down until 1) we find the right position, or 2) we run out of time, or 3) - * we have looked at every position - * - * @return Position of the row that matches mSyncRowId, or - * {@link #INVALID_POSITION} if it can't be found - */ - final int findSyncPosition() { - final int count = mItemCount; - - if (count == 0) return INVALID_POSITION; - - final long idToMatch = mSyncRowId; - int seed = mSyncPosition; - - // If there isn't a selection don't hunt for it - if (idToMatch == INVALID_ROW_ID) return INVALID_POSITION; - - // Pin seed to reasonable values - seed = Math.max(0, seed); - seed = Math.min(count - 1, seed); - - final long endTime = SystemClock.uptimeMillis() + SYNC_MAX_DURATION_MILLIS; - - long rowId; - - // First position scanned so far - int first = seed; - - // Last position scanned so far - int last = seed; - - // True if we should move down on the next iteration - boolean next = false; - - // True when we have looked at the first item in the data - boolean hitFirst; - - // True when we have looked at the last item in the data - boolean hitLast; - - // Get the item ID locally (instead of getItemIdAtPosition), so we need - // the adapter - final T adapter = getAdapter(); - if (adapter == null) return INVALID_POSITION; - - while (SystemClock.uptimeMillis() <= endTime) { - rowId = adapter.getItemId(seed); - if (rowId == idToMatch) // Found it! - return seed; - - hitLast = last == count - 1; - hitFirst = first == 0; - - if (hitLast && hitFirst) { - // Looked at everything - break; - } - - if (hitFirst || next && !hitLast) { - // Either we hit the top, or we are trying to move down - last++; - seed = last; - // Try going up next time - next = false; - } else if (hitLast || !next && !hitFirst) { - // Either we hit the bottom, or we are trying to move up - first--; - seed = first; - // Try going down next time - next = true; - } - - } - - return INVALID_POSITION; - } - - // CHECKSTYLE:OFF - void handleDataChanged() { - final int count = mItemCount; - boolean found = false; - - if (count > 0) { - - int newPos; - - // Find the row we are supposed to sync to - if (mNeedSync) { - // Update this first, since setNextSelectedPositionInt inspects - // it - mNeedSync = false; - - // See if we can find a position in the new data with the same - // id as the old selection - newPos = findSyncPosition(); - if (newPos >= 0) { - // Verify that new selection is selectable - final int selectablePos = lookForSelectablePosition(newPos, true); - if (selectablePos == newPos) { - // Same row id is selected - setNextSelectedPositionInt(newPos); - found = true; - } - } - } - if (!found) { - // Try to use the same position if we can't find matching data - newPos = getSelectedItemPosition(); - - // Pin position to the available range - if (newPos >= count) { - newPos = count - 1; - } - if (newPos < 0) { - newPos = 0; - } - - // Make sure we select something selectable -- first look down - int selectablePos = lookForSelectablePosition(newPos, true); - if (selectablePos < 0) { - // Looking down didn't work -- try looking up - selectablePos = lookForSelectablePosition(newPos, false); - } - if (selectablePos >= 0) { - setNextSelectedPositionInt(selectablePos); - checkSelectionChanged(); - found = true; - } - } - } - if (!found) { - // Nothing is selected - mSelectedPosition = INVALID_POSITION; - mSelectedRowId = INVALID_ROW_ID; - mNextSelectedPosition = INVALID_POSITION; - mNextSelectedRowId = INVALID_ROW_ID; - mNeedSync = false; - checkSelectionChanged(); - } - } - - /** - * Indicates whether this view is in filter mode. Filter mode can for - * instance be enabled by a user when typing on the keyboard. - * - * @return True if the view is in filter mode, false otherwise. - */ - final boolean isInFilterMode() { - return false; - } - - /** - * Find a position that can be selected (i.e., is not a separator). - * - * @param position The starting position to look at. - * @param lookDown Whether to look down for other positions. - * @return The next selectable position starting at position and then - * searching either up or down. Returns {@link #INVALID_POSITION} if - * nothing can be found. - */ - final int lookForSelectablePosition(final int position, final boolean lookDown) { - return position; - } - - /** - * Remember enough information to restore the screen state when the data has - * changed. - * - */ - final void rememberSyncState() { - if (getChildCount() > 0) { - mNeedSync = true; - mSyncHeight = mLayoutHeight; - if (mSelectedPosition >= 0) { - // Sync the selection state - final View v = getChildAt(mSelectedPosition - mFirstPosition); - mSyncRowId = mNextSelectedRowId; - mSyncPosition = mNextSelectedPosition; - if (v != null) { - mSpecificTop = v.getTop(); - } - mSyncMode = SYNC_SELECTED_POSITION; - } else { - // Sync the based on the offset of the first view - final View v = getChildAt(0); - final T adapter = getAdapter(); - if (mFirstPosition >= 0 && mFirstPosition < adapter.getCount()) { - mSyncRowId = adapter.getItemId(mFirstPosition); - } else { - mSyncRowId = NO_ID; - } - mSyncPosition = mFirstPosition; - if (v != null) { - mSpecificTop = v.getTop(); - } - mSyncMode = SYNC_FIRST_POSITION; - } - } - } - - void selectionChanged() { - if (mOnItemSelectedListener != null) { - if (mInLayout || mBlockLayoutRequests) { - // If we are in a layout traversal, defer notification - // by posting. This ensures that the view tree is - // in a consistent state and is able to accomodate - // new layout or invalidate requests. - if (mSelectionNotifier == null) { - mSelectionNotifier = new SelectionNotifier(); - } - mSelectionNotifier.post(mSelectionNotifier); - } else { - fireOnSelected(); - } - } - } - - // CHECKSTYLE:ON - - /** - * Utility to keep mNextSelectedPosition and mNextSelectedRowId in sync. - * - * @param position Intended value for mSelectedPosition the next time we go - * through layout - */ - // CHECKSTYLE:OFF overridden in subclass - void setNextSelectedPositionInt(final int position) { - mNextSelectedPosition = position; - mNextSelectedRowId = getItemIdAtPosition(position); - // If we are trying to sync to the selection, update that too - if (mNeedSync && mSyncMode == SYNC_SELECTED_POSITION && position >= 0) { - mSyncPosition = position; - mSyncRowId = mNextSelectedRowId; - } - } - - // CHECKSTYLE:ON - - /** - * Utility to keep mSelectedPosition and mSelectedRowId in sync. - * - * @param position Our current position - */ - // CHECKSTYLE:OFF overridden in gallery - void setSelectedPositionInt(final int position) { - mSelectedPosition = position; - mSelectedRowId = getItemIdAtPosition(position); - } - - // CHECKSTYLE:ON - - /** - * Extra menu information provided to the - * {@link android.view.View.OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo) } - * callback when a context menu is brought up for this AdapterView. - * - */ - public static class AdapterContextMenuInfo implements ContextMenu.ContextMenuInfo { - - /** - * The child view for which the context menu is being displayed. This - * will be one of the children of this AdapterView. - */ - public View targetView; - - /** - * The position in the adapter for which the context menu is being - * displayed. - */ - public int position; - - /** - * The row id of the item for which the context menu is being displayed. - */ - public long id; - - // CHECKSTYLE:OFF not modified - public AdapterContextMenuInfo(final View targetView, final int position, final long id) { - this.targetView = targetView; - this.position = position; - this.id = id; - } - // CHECKSTYLE:ON - } - - /** - * Interface definition for a callback to be invoked when an item in this - * AdapterView has been clicked. - */ - public interface OnItemClickListener { - - /** - * Callback method to be invoked when an item in this AdapterView has - * been clicked. - *

- * Implementers can call getItemAtPosition(position) if they need to - * access the data associated with the selected item. - * - * @param parent The AdapterView where the click happened. - * @param view The view within the AdapterView that was clicked (this - * will be a view provided by the adapter) - * @param position The position of the view in the adapter. - * @param id The row id of the item that was clicked. - */ - void onItemClick(AdapterView parent, View view, int position, long id); - } - - /** - * Interface definition for a callback to be invoked when an item in this - * view has been clicked and held. - */ - public interface OnItemLongClickListener { - /** - * Callback method to be invoked when an item in this view has been - * clicked and held. - * - * Implementers can call getItemAtPosition(position) if they need to - * access the data associated with the selected item. - * - * @param parent The AbsListView where the click happened - * @param view The view within the AbsListView that was clicked - * @param position The position of the view in the list - * @param id The row id of the item that was clicked - * - * @return true if the callback consumed the long click, false otherwise - */ - boolean onItemLongClick(AdapterView parent, View view, int position, long id); - } - - /** - * Interface definition for a callback to be invoked when an item in this - * view has been selected. - */ - public interface OnItemSelectedListener { - /** - * Callback method to be invoked when an item in this view has been - * selected. - * - * Impelmenters can call getItemAtPosition(position) if they need to - * access the data associated with the selected item. - * - * @param parent The AdapterView where the selection happened - * @param view The view within the AdapterView that was clicked - * @param position The position of the view in the adapter - * @param id The row id of the item that is selected - */ - void onItemSelected(AdapterView parent, View view, int position, long id); - - /** - * Callback method to be invoked when the selection disappears from this - * view. The selection can disappear for instance when touch is - * activated or when the adapter becomes empty. - * - * @param parent The AdapterView that now contains no selected item. - */ - void onNothingSelected(AdapterView parent); - } - - // CHECKSTYLE:OFF unmodified - private class SelectionNotifier extends Handler implements Runnable { - @Override - public void run() { - if (mDataChanged) { - // Data has changed between when this SelectionNotifier - // was posted and now. We need to wait until the AdapterView - // has been synched to the new data. - post(this); - } else { - fireOnSelected(); - } - } - } - - // CHECKSTYLE:OFF unmodified - class AdapterDataSetObserver extends DataSetObserver { - - private Parcelable mInstanceState = null; - - public void clearSavedState() { - mInstanceState = null; - } - - @Override - public void onChanged() { - mDataChanged = true; - mOldItemCount = mItemCount; - mItemCount = getAdapter().getCount(); - - // Detect the case where a cursor that was previously invalidated - // has - // been repopulated with new data. - if (AdapterView.this.getAdapter().hasStableIds() && mInstanceState != null && mOldItemCount == 0 - && mItemCount > 0) { - onRestoreInstanceState(mInstanceState); - mInstanceState = null; - } else { - rememberSyncState(); - } - checkFocus(); - requestLayout(); - } - - @Override - public void onInvalidated() { - mDataChanged = true; - - if (AdapterView.this.getAdapter().hasStableIds()) { - // Remember the current state for the case where our hosting - // activity is being - // stopped and later restarted - mInstanceState = onSaveInstanceState(); - } - - // Data is invalid so we should reset our state - mOldItemCount = mItemCount; - mItemCount = 0; - mSelectedPosition = INVALID_POSITION; - mSelectedRowId = INVALID_ROW_ID; - mNextSelectedPosition = INVALID_POSITION; - mNextSelectedRowId = INVALID_ROW_ID; - mNeedSync = false; - checkSelectionChanged(); - - checkFocus(); - requestLayout(); - } - } - // CHECKSTYLE:ON -} diff --git a/twidere/src/main/java/com/scvngr/levelup/views/gallery/Gallery.java b/twidere/src/main/java/com/scvngr/levelup/views/gallery/Gallery.java deleted file mode 100644 index e9d1a9e58..000000000 --- a/twidere/src/main/java/com/scvngr/levelup/views/gallery/Gallery.java +++ /dev/null @@ -1,1520 +0,0 @@ -package com.scvngr.levelup.views.gallery; - -/* - * Based on the android GalleryView source. Modified to allow the view to snap to the - * left rather than the center. The biggest changes in this class are marked with comments - * with "Note:". - * - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import android.content.Context; -import android.graphics.Rect; -import android.util.AttributeSet; -import android.view.ContextMenu.ContextMenuInfo; -import android.view.GestureDetector; -import android.view.Gravity; -import android.view.HapticFeedbackConstants; -import android.view.KeyEvent; -import android.view.MotionEvent; -import android.view.SoundEffectConstants; -import android.view.View; -import android.view.ViewConfiguration; -import android.view.ViewGroup; -import android.view.animation.Transformation; -import android.widget.Scroller; - -/** - * A view that shows items in a center-locked, horizontally scrolling list. - *

- * The default values for the Gallery assume you will be using - * {@link android.R.styleable#Theme_GalleryItemBackground} as the background for - * each View given to the Gallery from the Adapter. If you are not doing this, - * you may need to adjust some Gallery properties, such as the spacing. - *

- * Views given to the Gallery should use {@link Gallery.LayoutParams} as their - * layout parameters type. - * - *

- * See the Gallery tutorial. - *

- * - * CHECKSTYLE:OFF Android comments - * - * @attr ref android.R.styleable#Gallery_animationDuration - * @attr ref android.R.styleable#Gallery_spacing - * @attr ref android.R.styleable#Gallery_gravity CHECKSTYLE:ON - */ -public final class Gallery extends AbsSpinner implements GestureDetector.OnGestureListener { - - /** - * Duration in milliseconds from the start of a scroll during which we're - * unsure whether the user is scrolling or flinging. - */ - private static final int SCROLL_TO_FLING_UNCERTAINTY_TIMEOUT = 250; - - /** - * Horizontal spacing between items. - */ - private int mSpacing = 0; - - /** - * How long the transition animation should run when a child view changes - * position, measured in milliseconds. - */ - // CHECKSTYLE:OFF not a magic number - private int mAnimationDuration = 400; - // CHECKSTYLE:ON - - /** - * The alpha of items that are not selected. - */ - private float mUnselectedAlpha; - - /** - * Left most edge of a child seen so far during layout. - */ - private int mLeftMost; - - /** - * Right most edge of a child seen so far during layout. - */ - private int mRightMost; - - private int mGravity; - - /** - * Helper for detecting touch gestures. - */ - private final GestureDetector mGestureDetector; - - /** - * The position of the item that received the user's down touch. - */ - private int mDownTouchPosition; - - /** - * The view of the item that received the user's down touch. - */ - private View mDownTouchView; - - /** - * Executes the delta scrolls from a fling or scroll movement. - */ - private final FlingRunnable mFlingRunnable = new FlingRunnable(); - - /** - * Sets mSuppressSelectionChanged = false. This is used to set it to false - * in the future. It will also trigger a selection changed. - */ - private final Runnable mDisableSuppressSelectionChangedRunnable = new Runnable() { - @Override - public void run() { - mSuppressSelectionChanged = false; - selectionChanged(); - } - }; - - /** - * When fling runnable runs, it resets this to false. Any method along the - * path until the end of its run() can set this to true to abort any - * remaining fling. For example, if we've reached either the leftmost or - * rightmost item, we will set this to true. - */ - private boolean mShouldStopFling; - - /** - * The currently selected item's child. - */ - private View mSelectedChild; - - /** - * Whether to continuously callback on the item selected listener during a - * fling. - */ - private boolean mShouldCallbackDuringFling = true; - - /** - * Whether to callback when an item that is not selected is clicked. - */ - private boolean mShouldCallbackOnUnselectedItemClick = true; - - /** - * If true, do not callback to item selected listener. - */ - private boolean mSuppressSelectionChanged; - - /** - * If true, we have received the "invoke" (center or enter buttons) key - * down. This is checked before we action on the "invoke" key up, and is - * subsequently cleared. - */ - private boolean mReceivedInvokeKeyDown; - - private AdapterContextMenuInfo mContextMenuInfo; - - /** - * If true, this onScroll is the first for this user's drag (remember, a - * drag sends many onScrolls). - */ - private boolean mIsFirstScroll; - - /** - * If true, mFirstPosition is the position of the rightmost child, and the - * children are ordered right to left. - */ - private boolean mIsRtl = true; - - private boolean mScrollToChildAfterItemClickEnabled; - private boolean mRightSpacingEnabled; - - /** - * Constructor. - * - * @param context the context to inflate into - */ - public Gallery(final Context context) { - this(context, null); - } - - /** - * Constructor for XML inflation. - * - * @param context the context to inflate with - * @param attrs the xml attrs - */ - public Gallery(final Context context, final AttributeSet attrs) { - this(context, attrs, android.R.attr.galleryStyle); - } - - /** - * Constructor for XML inflation. - * - * @param context the context to inflate with - * @param attrs the XML attrs - * @param defStyle the default style resource id - */ - public Gallery(final Context context, final AttributeSet attrs, final int defStyle) { - super(context, attrs, defStyle); - - mGestureDetector = new GestureDetector(context, this); - mGestureDetector.setIsLongpressEnabled(true); - setScrollAfterItemClickEnabled(true); - setScrollRightSpacingEnabled(true); - } - - @Override - public boolean dispatchKeyEvent(final KeyEvent event) { - // Gallery steals all key events - return event.dispatch(this, null, null); - } - - @Override - public void dispatchSetSelected(final boolean selected) { - /* - * We don't want to pass the selected state given from its parent to its - * children since this widget itself has a selected state to give to its - * children. - */ - } - - @Override - public ViewGroup.LayoutParams generateLayoutParams(final AttributeSet attrs) { - return new LayoutParams(getContext(), attrs); - } - - @Override - public boolean onDown(final MotionEvent e) { - - // Kill any existing fling/scroll - mFlingRunnable.stop(false); - - // Get the item's view that was touched - mDownTouchPosition = pointToPosition((int) e.getX(), (int) e.getY()); - - if (mDownTouchPosition >= 0) { - mDownTouchView = getChildAt(mDownTouchPosition - mFirstPosition); - mDownTouchView.setPressed(true); - } - - // Reset the multiple-scroll tracking state - mIsFirstScroll = true; - - // Must return true to get matching events for this down event. - return true; - } - - @Override - public boolean onFling(final MotionEvent e1, final MotionEvent e2, final float velocityX, final float velocityY) { - - if (!mShouldCallbackDuringFling) { - // We want to suppress selection changes - - // Remove any future code to set mSuppressSelectionChanged = false - removeCallbacks(mDisableSuppressSelectionChangedRunnable); - - // This will get reset once we scroll into slots - if (!mSuppressSelectionChanged) { - mSuppressSelectionChanged = true; - } - } - - // Fling the Gallery! - mFlingRunnable.startUsingVelocity((int) -velocityX); - - return true; - } - - /** - * Handles left, right, and clicking. - * - * @see android.view.View#onKeyDown - */ - // CHECKSTYLE:OFF unmodified - @Override - public boolean onKeyDown(final int keyCode, final KeyEvent event) { - switch (keyCode) { - - case KeyEvent.KEYCODE_DPAD_LEFT: - if (movePrevious()) { - playSoundEffect(SoundEffectConstants.NAVIGATION_LEFT); - } - return true; - - case KeyEvent.KEYCODE_DPAD_RIGHT: - if (moveNext()) { - playSoundEffect(SoundEffectConstants.NAVIGATION_RIGHT); - } - return true; - - case KeyEvent.KEYCODE_DPAD_CENTER: - case KeyEvent.KEYCODE_ENTER: - mReceivedInvokeKeyDown = true; - // fallthrough to default handling - } - - return super.onKeyDown(keyCode, event); - } - - @Override - public boolean onKeyUp(final int keyCode, final KeyEvent event) { - switch (keyCode) { - - case KeyEvent.KEYCODE_DPAD_CENTER: - case KeyEvent.KEYCODE_ENTER: { - - if (mReceivedInvokeKeyDown) { - if (mItemCount > 0) { - - dispatchPress(mSelectedChild); - postDelayed(new Runnable() { - @Override - public void run() { - dispatchUnpress(); - } - }, ViewConfiguration.getPressedStateDuration()); - - final int selectedIndex = mSelectedPosition - mFirstPosition; - performItemClick(getChildAt(selectedIndex), mSelectedPosition, - mAdapter.getItemId(mSelectedPosition)); - } - } - - // Clear the flag - mReceivedInvokeKeyDown = false; - - return true; - } - } - - return super.onKeyUp(keyCode, event); - } - - @Override - public void onLongPress(final MotionEvent e) { - - if (mDownTouchPosition < 0) return; - - performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); - final long id = getItemIdAtPosition(mDownTouchPosition); - dispatchLongPress(mDownTouchView, mDownTouchPosition, id); - } - - @Override - public boolean onScroll(final MotionEvent e1, final MotionEvent e2, final float distanceX, final float distanceY) { - - /* - * Now's a good time to tell our parent to stop intercepting our events! - * The user has moved more than the slop amount, since GestureDetector - * ensures this before calling this method. Also, if a parent is more - * interested in this touch's events than we are, it would have - * intercepted them by now (for example, we can assume when a Gallery is - * in the ListView, a vertical scroll would not end up in this method - * since a ListView would have intercepted it by now). - */ - getParent().requestDisallowInterceptTouchEvent(true); - - /* - * As the user scrolls, we want to callback selection changes so - * related- info on the screen is up-to-date with the Gallery's - * selection - */ - if (!mShouldCallbackDuringFling) { - if (mIsFirstScroll) { - /* - * We're not notifying the client of selection changes during - * the fling, and this scroll could possibly be a fling. Don't - * do selection changes until we're sure it is not a fling. - */ - if (!mSuppressSelectionChanged) { - mSuppressSelectionChanged = true; - } - - postDelayed(mDisableSuppressSelectionChangedRunnable, SCROLL_TO_FLING_UNCERTAINTY_TIMEOUT); - } - } else { - if (mSuppressSelectionChanged) { - mSuppressSelectionChanged = false; - } - } - - // Track the motion - trackMotionScroll(-1 * (int) distanceX); - - mIsFirstScroll = false; - return true; - } - - @Override - public void onShowPress(final MotionEvent e) { - } - - @Override - public boolean onSingleTapUp(final MotionEvent e) { - - if (mDownTouchPosition >= 0) { - if (mScrollToChildAfterItemClickEnabled) { - // An item tap should make it selected, so scroll to this child. - scrollToChild(mDownTouchPosition - mFirstPosition); - } - - // Also pass the click so the client knows, if it wants to. - if (mShouldCallbackOnUnselectedItemClick || mDownTouchPosition == mSelectedPosition) { - performItemClick(mDownTouchView, mDownTouchPosition, mAdapter.getItemId(mDownTouchPosition)); - } - - return true; - } - - return false; - } - - @Override - public boolean onTouchEvent(final MotionEvent event) { - - if (!isEnabled()) return false; - - // Give everything to the gesture detector - final boolean retValue = mGestureDetector.onTouchEvent(event); - - final int action = event.getAction(); - if (action == MotionEvent.ACTION_UP) { - // Helper method for lifted finger - onUp(); - } else if (action == MotionEvent.ACTION_CANCEL) { - onCancel(); - } - - return retValue; - } - - /** - * Sets how long the transition animation should run when a child view - * changes position. Only relevant if animation is turned on. - * - * @param animationDurationMillis The duration of the transition, in - * milliseconds. - * - * @attr ref android.R.styleable#Gallery_animationDuration - */ - public void setAnimationDuration(final int animationDurationMillis) { - mAnimationDuration = animationDurationMillis; - } - - /** - * Whether or not to callback on any {@link #getOnItemSelectedListener()} - * while the items are being flinged. If false, only the final selected item - * will cause the callback. If true, all items between the first and the - * final will cause callbacks. - * - * @param shouldCallback Whether or not to callback on the listener while - * the items are being flinged. - */ - public void setCallbackDuringFling(final boolean shouldCallback) { - mShouldCallbackDuringFling = shouldCallback; - } - - /** - * Whether or not to callback when an item that is not selected is clicked. - * If false, the item will become selected (and re-centered). If true, the - * {@link #getOnItemClickListener()} will get the callback. - * - * @param shouldCallback Whether or not to callback on the listener when a - * item that is not selected is clicked. - * @hide - */ - public void setCallbackOnUnselectedItemClick(final boolean shouldCallback) { - mShouldCallbackOnUnselectedItemClick = shouldCallback; - } - - /** - * Describes how the child views are aligned. - * - * @param gravity the gravity to set - * - * @attr ref android.R.styleable#Gallery_gravity - */ - public void setGravity(final int gravity) { - if (mGravity != gravity) { - mGravity = gravity; - requestLayout(); - } - } - - public void setScrollAfterItemClickEnabled(final boolean enabled) { - mScrollToChildAfterItemClickEnabled = enabled; - } - - public void setScrollRightSpacingEnabled(final boolean enabled) { - mRightSpacingEnabled = enabled; - } - - /** - * Sets the spacing between items in a Gallery. - * - * @param spacing The spacing in pixels between items in the Gallery - * - * @attr ref android.R.styleable#Gallery_spacing - */ - public void setSpacing(final int spacing) { - mSpacing = spacing; - } - - /** - * Sets the alpha of items that are not selected in the Gallery. - * - * @param unselectedAlpha the alpha for the items that are not selected. - * - * @attr ref android.R.styleable#Gallery_unselectedAlpha - */ - public void setUnselectedAlpha(final float unselectedAlpha) { - mUnselectedAlpha = unselectedAlpha; - } - - @Override - public boolean showContextMenu() { - - if (isPressed() && mSelectedPosition >= 0) { - final int index = mSelectedPosition - mFirstPosition; - final View v = getChildAt(index); - return dispatchLongPress(v, mSelectedPosition, mSelectedRowId); - } - - return false; - } - - @Override - public boolean showContextMenuForChild(final View originalView) { - - final int longPressPosition = getPositionForView(originalView); - if (longPressPosition < 0) return false; - - final long longPressId = mAdapter.getItemId(longPressPosition); - return dispatchLongPress(originalView, longPressPosition, longPressId); - } - - @Override - protected boolean checkLayoutParams(final ViewGroup.LayoutParams p) { - return p instanceof LayoutParams; - } - - @Override - protected int computeHorizontalScrollExtent() { - // Only 1 item is considered to be selected - return 1; - } - - @Override - protected int computeHorizontalScrollOffset() { - // Current scroll position is the same as the selected position - return mSelectedPosition; - } - - @Override - protected int computeHorizontalScrollRange() { - // Scroll range is the same as the item count - return mItemCount; - } - - @Override - protected void dispatchSetPressed(final boolean pressed) { - - // Show the pressed state on the selected child - if (mSelectedChild != null) { - mSelectedChild.setPressed(pressed); - } - } - - @Override - protected ViewGroup.LayoutParams generateDefaultLayoutParams() { - /* - * Gallery expects Gallery.LayoutParams. - */ - return new Gallery.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); - } - - @Override - protected ViewGroup.LayoutParams generateLayoutParams(final ViewGroup.LayoutParams p) { - return new LayoutParams(p); - } - - // CHECKSTYLE:ON - - @Override - protected int getChildDrawingOrder(final int childCount, final int i) { - final int selectedIndex = mSelectedPosition - mFirstPosition; - - // Just to be safe - if (selectedIndex < 0) return i; - - if (i == childCount - 1) - // Draw the selected child last - return selectedIndex; - else if (i >= selectedIndex) // Move the children after the selected - // child earlier one - return i + 1; - else - // Keep the children before the selected child the same - return i; - } - - // CHECKSTYLE:OFF unchanged method - @Override - protected boolean getChildStaticTransformation(final View child, final Transformation t) { - - t.clear(); - t.setAlpha(child == mSelectedChild ? 1.0f : mUnselectedAlpha); - - return true; - } - - @Override - protected ContextMenuInfo getContextMenuInfo() { - return mContextMenuInfo; - } - - @Override - protected void onFocusChanged(final boolean gainFocus, final int direction, final Rect previouslyFocusedRect) { - super.onFocusChanged(gainFocus, direction, previouslyFocusedRect); - - /* - * The Gallery shows focus by focusing the selected item. So, give focus - * to our selected item instead. We steal keys from our selected item - * elsewhere. - */ - if (gainFocus && mSelectedChild != null) { - mSelectedChild.requestFocus(direction); - mSelectedChild.setSelected(true); - } - - } - - @Override - protected void onLayout(final boolean changed, final int l, final int t, final int r, final int b) { - super.onLayout(changed, l, t, r, b); - - /* - * Remember that we are in layout to prevent more layout request from - * being generated. - */ - mInLayout = true; - layout(0, false); - mInLayout = false; - } - - /** - * Figure out vertical placement based on mGravity. - * - * @param child Child to place - * @param duringLayout if this is being called during layout - * @return Where the top of the child should be - */ - private int calculateTop(final View child, final boolean duringLayout) { - // CHECKSTYLE:OFF unmodified - final int myHeight = duringLayout ? getMeasuredHeight() : getHeight(); - final int childHeight = duringLayout ? child.getMeasuredHeight() : child.getHeight(); - - int childTop = 0; - - switch (mGravity) { - case Gravity.TOP: - childTop = mSpinnerPadding.top; - break; - case Gravity.CENTER_VERTICAL: - final int availableSpace = myHeight - mSpinnerPadding.bottom - mSpinnerPadding.top - childHeight; - childTop = mSpinnerPadding.top + availableSpace / 2; - break; - case Gravity.BOTTOM: - childTop = myHeight - mSpinnerPadding.bottom - childHeight; - break; - } - return childTop; - // CHECKSTYLE:ON - } - - // CHECKSTYLE:ON - - /** - * Detaches children that are off the screen (i.e.: Gallery bounds). - * - * @param toLeft Whether to detach children to the left of the Gallery, or - * to the right. - */ - private void detachOffScreenChildren(final boolean toLeft) { - final int numChildren = getChildCount(); - final int firstPosition = mFirstPosition; - int start = 0; - int count = 0; - - if (toLeft) { - final int galleryLeft = getPaddingLeft(); - for (int i = 0; i < numChildren; i++) { - // CHECKSTYLE:OFF unmodified - final int n = mIsRtl ? numChildren - 1 - i : i; - // CHECKSTYLE:ON - final View child = getChildAt(n); - if (child.getRight() >= galleryLeft) { - break; - } else { - start = n; - count++; - mRecycler.put(firstPosition + n, child); - } - } - if (!mIsRtl) { - start = 0; - } - } else { - final int galleryRight = getWidth() - getPaddingRight(); - for (int i = numChildren - 1; i >= 0; i--) { - // CHECKSTYLE:OFF unmodified - final int n = mIsRtl ? numChildren - 1 - i : i; - // CHECKSTYLE:ON - final View child = getChildAt(n); - if (child.getLeft() <= galleryRight) { - break; - } else { - start = n; - count++; - mRecycler.put(firstPosition + n, child); - } - } - if (mIsRtl) { - start = 0; - } - } - - detachViewsFromParent(start, count); - - if (toLeft != mIsRtl) { - mFirstPosition += count; - } - } - - // CHECKSTYLE:OFF unmodified - private boolean dispatchLongPress(final View view, final int position, final long id) { - boolean handled = false; - - if (mOnItemLongClickListener != null) { - handled = mOnItemLongClickListener.onItemLongClick(this, mDownTouchView, mDownTouchPosition, id); - } - - if (!handled) { - mContextMenuInfo = new AdapterContextMenuInfo(view, position, id); - handled = super.showContextMenuForChild(this); - } - - if (handled) { - performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); - } - - return handled; - } - - // CHECKSTYLE:ON - - // CHECKSTYLE:OFF unmodified - private void dispatchPress(final View child) { - - if (child != null) { - child.setPressed(true); - } - - setPressed(true); - } - - private void dispatchUnpress() { - - for (int i = getChildCount() - 1; i >= 0; i--) { - getChildAt(i).setPressed(false); - } - - setPressed(false); - } - - // CHECKSTYLE:OFF unmodified - private void fillToGalleryLeft() { - if (mIsRtl) { - fillToGalleryLeftRtl(); - } else { - fillToGalleryLeftLtr(); - } - } - - private void fillToGalleryLeftLtr() { - final int itemSpacing = mSpacing; - final int galleryLeft = getPaddingLeft(); - - // Set state for initial iteration - View prevIterationView = getChildAt(0); - int curPosition; - int curRightEdge; - - if (prevIterationView != null) { - curPosition = mFirstPosition - 1; - curRightEdge = prevIterationView.getLeft() - itemSpacing; - } else { - // No children available! - curPosition = 0; - curRightEdge = getRight() - getLeft() - getPaddingRight(); - mShouldStopFling = true; - } - - while (curRightEdge > galleryLeft && curPosition >= 0) { - prevIterationView = makeAndAddView(curPosition, curPosition - mSelectedPosition, curRightEdge, false); - - // Remember some state - mFirstPosition = curPosition; - - // Set state for next iteration - curRightEdge = prevIterationView.getLeft() - itemSpacing; - curPosition--; - } - } - - private void fillToGalleryLeftRtl() { - final int itemSpacing = mSpacing; - final int galleryLeft = getPaddingLeft(); - final int numChildren = getChildCount(); - - // Set state for initial iteration - View prevIterationView = getChildAt(numChildren - 1); - int curPosition; - int curRightEdge; - - if (prevIterationView != null) { - curPosition = mFirstPosition + numChildren; - curRightEdge = prevIterationView.getLeft() - itemSpacing; - } else { - // No children available! - mFirstPosition = curPosition = mItemCount - 1; - curRightEdge = getRight() - getLeft() - getPaddingRight(); - mShouldStopFling = true; - } - - while (curRightEdge > galleryLeft && curPosition < mItemCount) { - prevIterationView = makeAndAddView(curPosition, curPosition - mSelectedPosition, curRightEdge, false); - - // Set state for next iteration - curRightEdge = prevIterationView.getLeft() - itemSpacing; - curPosition++; - } - } - - // CHECKSTYLE:ON - - // Unused methods from GestureDetector.OnGestureListener below - - private void fillToGalleryRight() { - if (mIsRtl) { - fillToGalleryRightRtl(); - } else { - fillToGalleryRightLtr(); - } - } - - // Unused methods from GestureDetector.OnGestureListener above - - private void fillToGalleryRightLtr() { - final int itemSpacing = mSpacing; - final int galleryRight = getRight() - getLeft() - getPaddingRight(); - final int numChildren = getChildCount(); - final int numItems = mItemCount; - - // Set state for initial iteration - View prevIterationView = getChildAt(numChildren - 1); - int curPosition; - int curLeftEdge; - - if (prevIterationView != null) { - curPosition = mFirstPosition + numChildren; - curLeftEdge = prevIterationView.getRight() + itemSpacing; - } else { - mFirstPosition = curPosition = mItemCount - 1; - curLeftEdge = getPaddingLeft(); - mShouldStopFling = true; - } - - while (curLeftEdge < galleryRight && curPosition < numItems) { - prevIterationView = makeAndAddView(curPosition, curPosition - mSelectedPosition, curLeftEdge, true); - - // Set state for next iteration - curLeftEdge = prevIterationView.getRight() + itemSpacing; - curPosition++; - } - } - - private void fillToGalleryRightRtl() { - final int itemSpacing = mSpacing; - final int GalleryRight = getRight() - getLeft() - getPaddingRight(); - - // Set state for initial iteration - View prevIterationView = getChildAt(0); - int curPosition; - int curLeftEdge; - - if (prevIterationView != null) { - curPosition = mFirstPosition - 1; - curLeftEdge = prevIterationView.getRight() + itemSpacing; - } else { - curPosition = 0; - curLeftEdge = getPaddingLeft(); - mShouldStopFling = true; - } - - while (curLeftEdge < GalleryRight && curPosition >= 0) { - prevIterationView = makeAndAddView(curPosition, curPosition - mSelectedPosition, curLeftEdge, true); - - // Remember some state - mFirstPosition = curPosition; - - // Set state for next iteration - curLeftEdge = prevIterationView.getRight() + itemSpacing; - curPosition--; - } - } - - /** - * Modified from getCenterOfGallery. This now gets the left of the view - * (plus padding). - * - * @return The left of this Gallery. - */ - private int getGalleryLockPoint() { - // Lock left of the view - return getPaddingLeft(); - } - - /** - * Obtain a view, either by pulling an existing view from the recycler or by - * getting a new one from the adapter. If we are animating, make sure there - * is enough information in the view's layout parameters to animate from the - * old to new positions. - * - * @param position Position in the Gallery for the view to obtain - * @param offset Offset from the selected position - * @param x X-coordinate indicating where this view should be placed. This - * will either be the left or right edge of the view, depending - * on the fromLeft parameter - * @param fromLeft Are we positioning views based on the left edge? (i.e., - * building from left to right)? - * @return A view that has been added to the Gallery - */ - private View makeAndAddView(final int position, final int offset, final int x, final boolean fromLeft) { - - View child; - if (!mDataChanged) { - child = mRecycler.get(position); - if (child != null) { - // Can reuse an existing view - final int childLeft = child.getLeft(); - - // Remember left and right edges of where views have been placed - mRightMost = Math.max(mRightMost, childLeft + child.getMeasuredWidth()); - mLeftMost = Math.min(mLeftMost, childLeft); - - // Position the view - setUpChild(child, offset, x, fromLeft); - - return child; - } - } - - // Nothing found in the recycler -- ask the adapter for a view - child = mAdapter.getView(position, null, this); - - // Position the view - setUpChild(child, offset, x, fromLeft); - - return child; - } - - // CHECKSTYLE:ON - - /** - * Offset the horizontal location of all children of this view by the - * specified number of pixels. - * - * @param offset the number of pixels to offset - */ - private void offsetChildrenLeftAndRight(final int offset) { - for (int i = getChildCount() - 1; i >= 0; i--) { - getChildAt(i).offsetLeftAndRight(offset); - } - } - - // CHECKSTYLE:OFF unmodified - private void onFinishedMovement() { - if (mSuppressSelectionChanged) { - mSuppressSelectionChanged = false; - - // We haven't been callbacking during the fling, so do it now - super.selectionChanged(); - } - invalidate(); - } - - /** - * Scrolls the items so that the selected item is in its 'slot' (its center - * is the Gallery's center). - * - * Note: modifed to snap the left of a view rather than the center - */ - private void scrollIntoSlots() { - if (getChildCount() == 0 || mSelectedChild == null) return; - - final int selectedCenter = getLeftOfView(mSelectedChild); - final int targetCenter = getGalleryLockPoint(); - - final int scrollAmount = targetCenter - selectedCenter; - if (scrollAmount != 0) { - mFlingRunnable.startUsingDistance(scrollAmount); - } else { - onFinishedMovement(); - } - } - - /** - * Scroll to the child at the position passed. - * - * @param childPosition the child's position - * @return if scrolling to the child is starting, false otherwise - */ - private boolean scrollToChild(final int childPosition) { - final View child = getChildAt(childPosition); - - if (child != null) { - final int distance = getGalleryLockPoint() - getLeftOfView(child); - mFlingRunnable.startUsingDistance(distance); - return true; - } - - return false; - } - - /** - * Looks for the child that is closest to the lock point of the gallery and - * sets it as the selected child. - * - * Note: modified from setSelectionToCenterChild to now select the the - * selected view to the child closest to the gallery's "lock point" (it's - * left). - */ - private void setSelectionToChildClosestToLockPoint() { - if (mSelectedChild == null) return; - - final int lockPoint = getGalleryLockPoint(); - - // TODO better search - int closestEdgeDistance = Integer.MAX_VALUE; - int newSelectedChildIndex = 0; - for (int i = getChildCount() - 1; i >= 0; i--) { - final View child = getChildAt(i); - - /* - * Note: Since we are locking on the left edge of the scroller, we - * want to put more emphasis on the closest edge calculations - * because the left edge being on the left of the screen puts - * unnecessary weight on the currently selected item. - */ - if (child.getLeft() == lockPoint && child.getRight() >= lockPoint) { - // This child is in the lock point - newSelectedChildIndex = i; - break; - } - - final int childClosestEdgeDistance = Math.min(Math.abs(child.getLeft() - lockPoint), - Math.abs(child.getRight() - lockPoint)); - if (childClosestEdgeDistance < closestEdgeDistance) { - closestEdgeDistance = childClosestEdgeDistance; - newSelectedChildIndex = i; - } - } - - final int newPos = mFirstPosition + newSelectedChildIndex; - - if (newPos != mSelectedPosition) { - setSelectedPositionInt(newPos); - setNextSelectedPositionInt(newPos); - checkSelectionChanged(); - } - } - - // CHECKSTYLE:ON - - /** - * Helper for makeAndAddView to set the position of a view and fill out its - * layout parameters. - * - * @param child The view to position - * @param offset Offset from the selected position - * @param x X-coordinate indicating where this view should be placed. This - * will either be the left or right edge of the view, depending - * on the fromLeft parameter - * @param fromLeft Are we positioning views based on the left edge? (i.e., - * building from left to right)? - */ - private void setUpChild(final View child, final int offset, final int x, final boolean fromLeft) { - - /* - * Respect layout params that are already in the view. Otherwise make - * some up... - */ - Gallery.LayoutParams lp = child.getLayoutParams(); - if (lp == null) { - lp = generateDefaultLayoutParams(); - } - - // CHECKSTYLE:OFF unmodified - addViewInLayout(child, fromLeft != mIsRtl ? -1 : 0, lp); - // CHECKSTYLE:ON - - child.setSelected(offset == 0); - - // Get measure specs - final int childHeightSpec = ViewGroup.getChildMeasureSpec(mHeightMeasureSpec, mSpinnerPadding.top - + mSpinnerPadding.bottom, lp.height); - final int childWidthSpec = ViewGroup.getChildMeasureSpec(mWidthMeasureSpec, mSpinnerPadding.left - + mSpinnerPadding.right, lp.width); - - // Measure child - child.measure(childWidthSpec, childHeightSpec); - - int childLeft; - int childRight; - - // Position vertically based on gravity setting - final int childTop = calculateTop(child, true); - final int childBottom = childTop + child.getMeasuredHeight(); - - final int width = child.getMeasuredWidth(); - if (fromLeft) { - childLeft = x; - childRight = childLeft + width; - } else { - childLeft = x - width; - childRight = x; - } - - child.layout(childLeft, childTop, childRight, childBottom); - } - - // CHECKSTYLE:OFF unmodified - private void updateSelectedItemMetadata() { - - final View oldSelectedChild = mSelectedChild; - - final View child = mSelectedChild = getChildAt(mSelectedPosition - mFirstPosition); - if (child == null) return; - - child.setSelected(true); - child.setFocusable(true); - - if (hasFocus()) { - child.requestFocus(); - } - - // We unfocus the old child down here so the above hasFocus check - // returns true - if (oldSelectedChild != null && oldSelectedChild != child) { - - // Make sure its drawable state doesn't contain 'selected' - oldSelectedChild.setSelected(false); - - /* - * Make sure it is not focusable anymore, since otherwise arrow keys - * can make this one be focused - */ - oldSelectedChild.setFocusable(false); - } - - } - - /** - * Gets the limit of the amount to scroll the view. Note: Modified from the - * android source to snap to the left of the view rather than the center. - * - * @param motionToLeft if the motion is to the left of the view - * @param deltaX the change in x - * @return the clamped value to scroll - */ - // TODO - int getLimitedMotionScrollAmount(final boolean motionToLeft, final int deltaX) { - // CHECKSTYLE:OFF unmodifed code - final int extremeItemPosition = motionToLeft != mIsRtl ? mItemCount - 1 : 0; - // CHECKSTYLE:ON - final View extremeChild = getChildAt(extremeItemPosition - mFirstPosition); - - if (extremeChild == null) return deltaX; - - final int extremeChildLeft = getLeftOfView(extremeChild); - final int galleryLockPoint = getGalleryLockPoint(); - - if (motionToLeft) { - if (!mRightSpacingEnabled && extremeChild.getRight() <= getRight()) return 0; - // The extreme child is past his boundary point! - if (extremeChildLeft <= galleryLockPoint) return 0; - } else { - // The extreme child is past his boundary point! - if (extremeChildLeft >= galleryLockPoint) return 0; - } - - final int centerDifference = galleryLockPoint - extremeChildLeft; - - // CHECKSTYLE:OFF unmodifed return - return motionToLeft ? Math.max(centerDifference, deltaX) : Math.min(centerDifference, deltaX); - // CHECKSTYLE:ON - } - - /** - * Creates and positions all views for this Gallery. - *

- * We layout rarely, most of the time {@link #trackMotionScroll(int)} takes - * care of repositioning, adding, and removing children. - * - * Note: modified to offset to the gallery lock point rather than based on - * the # of children. - * - * @param delta Change in the selected position. +1 means the selection is - * moving to the right, so views are scrolling to the left. -1 - * means the selection is moving to the left. - * @param animate if true, animate the view - */ - @Override - void layout(final int delta, final boolean animate) { - - mIsRtl = false; - - if (mDataChanged) { - handleDataChanged(); - } - - // Handle an empty Gallery by removing all views. - if (mItemCount == 0) { - resetList(); - return; - } - - // Update to the new selected position. - if (mNextSelectedPosition >= 0) { - setSelectedPositionInt(mNextSelectedPosition); - } - - // All views go in recycler while we are in layout - recycleAllViews(); - - // Clear out old views - detachAllViewsFromParent(); - - /* - * These will be used to give initial positions to views entering the - * Gallery as we scroll - */ - mRightMost = 0; - mLeftMost = 0; - - // Make selected view and move it to the lock point - - /* - * mFirstPosition will be decreased as we add views to the left later - * on. The 0 for x will be offset in a couple lines down. - */ - mFirstPosition = mSelectedPosition; - final View sel = makeAndAddView(mSelectedPosition, 0, 0, true); - - // Put the selected child at the lockPoint - sel.offsetLeftAndRight(getGalleryLockPoint()); - - fillToGalleryRight(); - fillToGalleryLeft(); - - // Flush any cached views that did not get reused above - mRecycler.clear(); - - invalidate(); - checkSelectionChanged(); - - mDataChanged = false; - mNeedSync = false; - setNextSelectedPositionInt(mSelectedPosition); - - updateSelectedItemMetadata(); - } - - // CHECKSTYLE:ON - - boolean moveNext() { - if (mItemCount > 0 && mSelectedPosition < mItemCount - 1) { - scrollToChild(mSelectedPosition - mFirstPosition + 1); - return true; - } else - return false; - } - - boolean movePrevious() { - if (mItemCount > 0 && mSelectedPosition > 0) { - /** - * used to be scrollToChild(mSelectedPosition - mFirstPosition - 1); - * Found that this did not work with trackball/keyboard navigation. - */ - setSelection(mSelectedPosition - 1); - return true; - } else - return false; - } - - /** - * Called when a touch event's action is MotionEvent.ACTION_CANCEL. - */ - void onCancel() { - onUp(); - } - - /** - * Called when a touch event's action is MotionEvent.ACTION_UP. - */ - void onUp() { - - if (mFlingRunnable.mScroller.isFinished()) { - scrollIntoSlots(); - } - - dispatchUnpress(); - } - - @Override - void selectionChanged() { - if (!mSuppressSelectionChanged) { - super.selectionChanged(); - } - } - - @Override - void setSelectedPositionInt(final int position) { - super.setSelectedPositionInt(position); - - // Updates any metadata we keep about the selected item. - updateSelectedItemMetadata(); - } - - /** - * Tracks a motion scroll. In reality, this is used to do just about any - * movement to items (touch scroll, arrow-key scroll, set an item as - * selected). - * - * @param deltaX Change in X from the previous event. - */ - void trackMotionScroll(final int deltaX) { - - if (getChildCount() == 0) return; - - final boolean toLeft = deltaX < 0; - - final int limitedDeltaX = getLimitedMotionScrollAmount(toLeft, deltaX); - if (limitedDeltaX != deltaX) { - // The above call returned a limited amount, so stop any - // scrolls/flings - mFlingRunnable.endFling(false); - onFinishedMovement(); - } - - offsetChildrenLeftAndRight(limitedDeltaX); - - detachOffScreenChildren(toLeft); - - if (toLeft) { - // If moved left, there will be empty space on the right - fillToGalleryRight(); - } else { - // Similarly, empty space on the left - fillToGalleryLeft(); - } - - // Clear unused views - mRecycler.clear(); - - setSelectionToChildClosestToLockPoint(); - - onScrollChanged(0, 0, 0, 0); // Dummy values, View's implementation does - // not use these. - - invalidate(); - } - - /** - * Modified from getCenterOfView to get the left of a view instead. - * - * @param view the view to get the left of - * @return The center of the given view. - */ - private static int getLeftOfView(final View view) { - return view.getLeft(); - } - - /** - * Responsible for fling behavior. Use {@link #startUsingVelocity(int)} to - * initiate a fling. Each frame of the fling is handled in {@link #run()}. A - * FlingRunnable will keep re-posting itself until the fling is done. - */ - private class FlingRunnable implements Runnable { - /** - * Tracks the decay of a fling scroll. - */ - private final Scroller mScroller; - - /** - * X value reported by mScroller on the previous fling. - */ - private int mLastFlingX; - - /** - * Constructor. - */ - public FlingRunnable() { - mScroller = new Scroller(getContext()); - } - - @Override - public void run() { - - if (mItemCount == 0) { - endFling(true); - return; - } - - mShouldStopFling = false; - - final Scroller scroller = mScroller; - final boolean more = scroller.computeScrollOffset(); - final int x = scroller.getCurrX(); - - // Flip sign to convert finger direction to list items direction - // (e.g. finger moving down means list is moving towards the top) - int delta = mLastFlingX - x; - - // Pretend that each frame of a fling scroll is a touch scroll - if (delta > 0) { - // Moving towards the left. Use leftmost view as - // mDownTouchPosition - mDownTouchPosition = mIsRtl ? mFirstPosition + getChildCount() - 1 : mFirstPosition; - - // Don't fling more than 1 screen - delta = Math.min(getWidth() - getPaddingLeft() - getPaddingRight() - 1, delta); - } else { - // Moving towards the right. Use rightmost view as - // mDownTouchPosition - mDownTouchPosition = mIsRtl ? mFirstPosition : mFirstPosition + getChildCount() - 1; - - // Don't fling more than 1 screen - delta = Math.max(-(getWidth() - getPaddingRight() - getPaddingLeft() - 1), delta); - } - - trackMotionScroll(delta); - - if (more && !mShouldStopFling) { - mLastFlingX = x; - post(this); - } else { - endFling(true); - } - } - - public void startUsingDistance(final int distance) { - if (distance == 0) return; - - startCommon(); - - mLastFlingX = 0; - mScroller.startScroll(0, 0, -distance, 0, mAnimationDuration); - post(this); - } - - public void startUsingVelocity(final int initialVelocity) { - if (initialVelocity == 0) return; - - startCommon(); - - final int initialX = initialVelocity < 0 ? Integer.MAX_VALUE : 0; - mLastFlingX = initialX; - mScroller.fling(initialX, 0, initialVelocity, 0, 0, Integer.MAX_VALUE, 0, Integer.MAX_VALUE); - post(this); - } - - public void stop(final boolean scrollIntoSlots) { - removeCallbacks(this); - endFling(scrollIntoSlots); - } - - private void endFling(final boolean scrollIntoSlots) { - /* - * Force the scroller's status to finished (without setting its - * position to the end) - */ - mScroller.forceFinished(true); - - if (scrollIntoSlots) { - scrollIntoSlots(); - } - } - - // CHECKSTYLE:OFF unmodified - private void startCommon() { - // Remove any pending flings - removeCallbacks(this); - } - - } -} diff --git a/twidere/src/main/java/org/mariotaku/gallery3d/ui/EdgeEffect.java b/twidere/src/main/java/org/mariotaku/gallery3d/ui/EdgeEffect.java index 6b9e3a1c6..5f9a6d15f 100644 --- a/twidere/src/main/java/org/mariotaku/gallery3d/ui/EdgeEffect.java +++ b/twidere/src/main/java/org/mariotaku/gallery3d/ui/EdgeEffect.java @@ -139,7 +139,7 @@ public class EdgeEffect { * for the EdgeEffect */ public EdgeEffect(final Context context) { - final int theme_color = ThemeUtils.getUserThemeColor(context); + final int theme_color = ThemeUtils.getUserAccentColor(context); mEdge = new Drawable(context, R.drawable.overscroll_edge); mEdge.setColorFilter(theme_color, PorterDuff.Mode.SRC_ATOP); mGlow = new Drawable(context, R.drawable.overscroll_glow); diff --git a/twidere/src/main/java/org/mariotaku/twidere/Constants.java b/twidere/src/main/java/org/mariotaku/twidere/Constants.java index 00930b42d..867628d10 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/Constants.java +++ b/twidere/src/main/java/org/mariotaku/twidere/Constants.java @@ -28,10 +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 = 67; - - public static final String GOOGLE_MAPS_API_KEY_RELEASE = "0kjPwJOe_zwYjzGc9uYak7vhm_Sf3eob-2L3Xzw"; - public static final String GOOGLE_MAPS_API_KEY_DEBUG = "0kjPwJOe_zwY9p6kT-kygu4mxwysyOOpfkaXqTA"; + public static final int DATABASES_VERSION = 68; public static final int MENU_GROUP_STATUS_EXTENSION = 10; public static final int MENU_GROUP_COMPOSE_EXTENSION = 11; diff --git a/twidere/src/main/java/org/mariotaku/twidere/activity/BaseActivity.java b/twidere/src/main/java/org/mariotaku/twidere/activity/BaseActivity.java index c1980dd98..51537b9f1 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/activity/BaseActivity.java +++ b/twidere/src/main/java/org/mariotaku/twidere/activity/BaseActivity.java @@ -20,7 +20,6 @@ package org.mariotaku.twidere.activity; import android.annotation.SuppressLint; -import android.content.res.Resources; import android.os.Bundle; import org.mariotaku.twidere.Constants; @@ -41,7 +40,7 @@ public class BaseActivity extends BaseThemedActivity implements Constants { @Override public int getThemeColor() { - return ThemeUtils.getUserThemeColor(this); + return ThemeUtils.getUserAccentColor(this); } @Override diff --git a/twidere/src/main/java/org/mariotaku/twidere/activity/MainActivity.java b/twidere/src/main/java/org/mariotaku/twidere/activity/MainActivity.java index 44811be2b..4989927ef 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/activity/MainActivity.java +++ b/twidere/src/main/java/org/mariotaku/twidere/activity/MainActivity.java @@ -54,7 +54,7 @@ public class MainActivity extends Activity implements Constants { protected void onResume() { super.onResume(); final int themeResource = ThemeUtils.getThemeResource(this); - final int accentColor = ThemeUtils.isColoredActionBar(themeResource) ? ThemeUtils.getUserThemeColor(this) : 0; + final int accentColor = ThemeUtils.isColoredActionBar(themeResource) ? ThemeUtils.getUserAccentColor(this) : 0; final int backgroundAlpha = ThemeUtils.isTransparentBackground(themeResource) ? ThemeUtils .getUserThemeBackgroundAlpha(this) : 0xFF; ThemeUtils.notifyStatusBarColorChanged(this, themeResource, accentColor, backgroundAlpha); diff --git a/twidere/src/main/java/org/mariotaku/twidere/activity/SettingsActivity.java b/twidere/src/main/java/org/mariotaku/twidere/activity/SettingsActivity.java index 036f874b8..8ee60d9c9 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/activity/SettingsActivity.java +++ b/twidere/src/main/java/org/mariotaku/twidere/activity/SettingsActivity.java @@ -179,7 +179,7 @@ public class SettingsActivity extends BasePreferenceActivity { mPreferences = getSharedPreferences(SHARED_PREFERENCES_NAME, MODE_PRIVATE); mCompactCards = mPreferences.getBoolean(KEY_COMPACT_CARDS, false); mPlainListStyle = mPreferences.getBoolean(KEY_PLAIN_LIST_STYLE, false); - mCurrentThemeColor = ThemeUtils.getUserThemeColor(this); + mCurrentThemeColor = ThemeUtils.getUserAccentColor(this); mCurrentThemeFontFamily = getThemeFontFamily(); mCurrentThemeBackgroundAlpha = getThemeBackgroundAlpha(); mCurrentIsDarkDrawerEnabled = isDarkDrawerEnabled(); @@ -198,7 +198,7 @@ public class SettingsActivity extends BasePreferenceActivity { return mCompactCards != mPreferences.getBoolean(KEY_COMPACT_CARDS, false) || mPlainListStyle != mPreferences.getBoolean(KEY_PLAIN_LIST_STYLE, false) || getThemeResourceId() != getCurrentThemeResourceId() - || ThemeUtils.getUserThemeColor(this) != mCurrentThemeColor + || ThemeUtils.getUserAccentColor(this) != mCurrentThemeColor || !CompareUtils.objectEquals(getThemeFontFamily(), mCurrentThemeFontFamily) || getThemeBackgroundAlpha() != mCurrentThemeBackgroundAlpha || isDarkDrawerEnabled() != mCurrentIsDarkDrawerEnabled; diff --git a/twidere/src/main/java/org/mariotaku/twidere/activity/support/AccountsManagerActivity.java b/twidere/src/main/java/org/mariotaku/twidere/activity/support/AccountsManagerActivity.java new file mode 100644 index 000000000..85c82a9fc --- /dev/null +++ b/twidere/src/main/java/org/mariotaku/twidere/activity/support/AccountsManagerActivity.java @@ -0,0 +1,54 @@ +package org.mariotaku.twidere.activity.support; + +import android.app.ActionBar; +import android.graphics.Rect; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentTransaction; +import android.view.MenuItem; + +import org.mariotaku.twidere.R; +import org.mariotaku.twidere.fragment.iface.IBaseFragment; +import org.mariotaku.twidere.fragment.support.AccountsManagerFragment; + +/** + * Created by mariotaku on 14/10/26. + */ +public class AccountsManagerActivity extends BaseSupportActivity { + + @Override + public boolean onOptionsItemSelected(final MenuItem item) { + switch (item.getItemId()) { + case MENU_HOME: { + onBackPressed(); + return true; + } + } + return super.onOptionsItemSelected(item); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + final ActionBar actionBar = getActionBar(); + if (actionBar != null) { + actionBar.setDisplayHomeAsUpEnabled(true); + } + setContentView(R.layout.activity_content_fragment); + final FragmentManager fm = getSupportFragmentManager(); + final FragmentTransaction ft = fm.beginTransaction(); + ft.replace(R.id.content_fragment, new AccountsManagerFragment()); + ft.commit(); + } + + @Override + public void fitSystemWindows(Rect insets) { + super.fitSystemWindows(insets); + final FragmentManager fm = getSupportFragmentManager(); + final Fragment f = fm.findFragmentById(R.id.content_fragment); + if (f instanceof IBaseFragment) { + ((IBaseFragment) f).requestFitSystemWindows(); + } + } +} diff --git a/twidere/src/main/java/org/mariotaku/twidere/activity/support/BaseSupportActivity.java b/twidere/src/main/java/org/mariotaku/twidere/activity/support/BaseSupportActivity.java index 088f55795..3b8f39c1c 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/activity/support/BaseSupportActivity.java +++ b/twidere/src/main/java/org/mariotaku/twidere/activity/support/BaseSupportActivity.java @@ -52,7 +52,7 @@ public class BaseSupportActivity extends BaseSupportThemedActivity implements Co @Override public int getThemeColor() { - return ThemeUtils.getUserThemeColor(this, getThemeResourceId()); + return ThemeUtils.getUserAccentColor(this, getThemeResourceId()); } @Override diff --git a/twidere/src/main/java/org/mariotaku/twidere/activity/support/BaseSupportThemedActivity.java b/twidere/src/main/java/org/mariotaku/twidere/activity/support/BaseSupportThemedActivity.java index c400475ea..26ea51663 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/activity/support/BaseSupportThemedActivity.java +++ b/twidere/src/main/java/org/mariotaku/twidere/activity/support/BaseSupportThemedActivity.java @@ -21,7 +21,6 @@ package org.mariotaku.twidere.activity.support; import android.app.ActionBar; import android.content.res.Resources; -import android.graphics.Color; import android.os.Bundle; import android.support.v4.app.FragmentActivity; import android.support.v4.app.NavUtils; @@ -153,11 +152,8 @@ public abstract class BaseSupportThemedActivity extends FragmentActivity impleme super.onTitleChanged(title, color); final int themeResId = getCurrentThemeResourceId(); final int themeColor = getThemeColor(), contrastColor = Utils.getContrastYIQ(themeColor, 192); - if (ThemeUtils.isColoredActionBar(themeResId)) { + if (!ThemeUtils.isDarkTheme(themeResId)) { builder.setSpan(new ForegroundColorSpan(contrastColor), 0, builder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - } else { - final int titleColor = ThemeUtils.isLightActionBar(themeResId) ? Color.BLACK : Color.WHITE; - builder.setSpan(new ForegroundColorSpan(titleColor), 0, builder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } } diff --git a/twidere/src/main/java/org/mariotaku/twidere/activity/support/ComposeActivity.java b/twidere/src/main/java/org/mariotaku/twidere/activity/support/ComposeActivity.java index 1e437bba9..7d14e860f 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/activity/support/ComposeActivity.java +++ b/twidere/src/main/java/org/mariotaku/twidere/activity/support/ComposeActivity.java @@ -46,6 +46,7 @@ import android.provider.MediaStore; import android.support.annotation.NonNull; import android.support.v4.app.DialogFragment; import android.support.v4.util.LongSparseArray; +import android.support.v7.widget.RecyclerView.ViewHolder; import android.text.Editable; import android.text.TextUtils; import android.text.TextWatcher; @@ -62,7 +63,6 @@ import android.view.ViewGroup; import android.widget.EditText; import android.widget.GridView; import android.widget.ImageView; -import android.widget.LinearLayout; import android.widget.ProgressBar; import android.widget.ScrollView; import android.widget.TextView; @@ -70,10 +70,6 @@ import android.widget.TextView.OnEditorActionListener; import android.widget.Toast; import com.nostra13.universalimageloader.utils.IoUtils; -import com.scvngr.levelup.views.gallery.AdapterView; -import com.scvngr.levelup.views.gallery.AdapterView.OnItemClickListener; -import com.scvngr.levelup.views.gallery.AdapterView.OnItemLongClickListener; -import com.scvngr.levelup.views.gallery.Gallery; import com.twitter.Extractor; import org.mariotaku.dynamicgridview.DraggableArrayAdapter; @@ -81,7 +77,7 @@ import org.mariotaku.menucomponent.widget.MenuBar; import org.mariotaku.menucomponent.widget.MenuBar.MenuBarListener; import org.mariotaku.menucomponent.widget.PopupMenu; import org.mariotaku.twidere.R; -import org.mariotaku.twidere.adapter.BaseArrayAdapter; +import org.mariotaku.twidere.adapter.ArrayRecyclerAdapter; import org.mariotaku.twidere.app.TwidereApplication; import org.mariotaku.twidere.fragment.support.BaseSupportDialogFragment; import org.mariotaku.twidere.model.Account; @@ -149,8 +145,7 @@ import static org.mariotaku.twidere.util.Utils.showErrorMessage; import static org.mariotaku.twidere.util.Utils.showMenuItemToast; public class ComposeActivity extends BaseSupportDialogActivity implements TextWatcher, LocationListener, - MenuBarListener, OnClickListener, OnEditorActionListener, OnItemClickListener, OnItemLongClickListener, - OnLongClickListener { + MenuBarListener, OnClickListener, OnEditorActionListener, OnLongClickListener { private static final String FAKE_IMAGE_LINK = "https://www.example.com/fake_image.jpg"; @@ -177,13 +172,11 @@ public class ComposeActivity extends BaseSupportDialogActivity implements TextWa private TextView mTitleView, mSubtitleView; private GridView mMediasPreviewGrid; - private MenuBar mBottomMenuBar, mActionMenuBar; + private MenuBar mMenuBar; private IColorLabelView mColorIndicator; private EditText mEditText; private ProgressBar mProgress; - private Gallery mAccountSelector; - private View mAccountSelectorDivider, mBottomSendDivider; - private View mBottomMenuContainer; + // private RecyclerView mAccountSelector; private View mSendView, mBottomSendView; private StatusTextCountView mSendTextCountView, mBottomSendTextCountView; @@ -219,7 +212,7 @@ public class ComposeActivity extends BaseSupportDialogActivity implements TextWa @Override public int getThemeColor() { - return ThemeUtils.getUserThemeColor(this); + return ThemeUtils.getUserAccentColor(this); } @Override @@ -433,13 +426,9 @@ public class ComposeActivity extends BaseSupportDialogActivity implements TextWa mTitleView = (TextView) findViewById(R.id.actionbar_title); mSubtitleView = (TextView) findViewById(R.id.actionbar_subtitle); mMediasPreviewGrid = (GridView) findViewById(R.id.medias_thumbnail_preview); - mBottomMenuBar = (MenuBar) findViewById(R.id.bottom_menu); - mBottomMenuContainer = findViewById(R.id.bottom_menu_container); - mActionMenuBar = (MenuBar) findViewById(R.id.action_menu); + mMenuBar = (MenuBar) findViewById(R.id.menu_bar); mProgress = (ProgressBar) findViewById(R.id.actionbar_progress_indeterminate); - mAccountSelectorDivider = findViewById(R.id.account_selector_divider); - mBottomSendDivider = findViewById(R.id.bottom_send_divider); - mAccountSelector = (Gallery) findViewById(R.id.account_selector); +// mAccountSelector = (RecyclerView) findViewById(R.id.account_selector); final View composeActionBar = findViewById(R.id.compose_actionbar); final View composeBottomBar = findViewById(R.id.compose_bottombar); mSendView = composeActionBar.findViewById(R.id.send); @@ -462,23 +451,23 @@ public class ComposeActivity extends BaseSupportDialogActivity implements TextWa return false; } - @Override - public void onItemClick(final AdapterView parent, final View view, final int position, final long id) { - if (isSingleAccount()) return; - final boolean selected = !view.isActivated(); - final Account account = mAccountSelectorAdapter.getItem(position); - mAccountSelectorAdapter.setAccountSelected(account.account_id, selected); - mSendAccountIds = mAccountSelectorAdapter.getSelectedAccountIds(); - updateAccountSelection(); - } - - @Override - public boolean onItemLongClick(final AdapterView parent, final View view, final int position, final long id) { - final Account account = mAccountSelectorAdapter.getItem(position); - final String displayName = getDisplayName(this, account.account_id, account.name, account.screen_name); - showMenuItemToast(view, displayName, true); - return true; - } +// @Override +// public void onItemClick(final AdapterView parent, final View view, final int position, final long id) { +// if (isSingleAccount()) return; +// final boolean selected = !view.isActivated(); +// final Account account = mAccountSelectorAdapter.getItem(position); +// mAccountSelectorAdapter.setAccountSelected(account.account_id, selected); +// mSendAccountIds = mAccountSelectorAdapter.getSelectedAccountIds(); +// updateAccountSelection(); +// } +// +// @Override +// public boolean onItemLongClick(final AdapterView parent, final View view, final int position, final long id) { +// final Account account = mAccountSelectorAdapter.getItem(position); +// final String displayName = getDisplayName(this, account.account_id, account.name, account.screen_name); +// showMenuItemToast(view, displayName, true); +// return true; +// } @Override public void onLocationChanged(final Location location) { @@ -595,17 +584,15 @@ public class ComposeActivity extends BaseSupportDialogActivity implements TextWa finish(); return; } - mBottomMenuBar.setIsBottomBar(true); - mBottomMenuBar.setMenuBarListener(this); - mActionMenuBar.setMenuBarListener(this); + mMenuBar.setIsBottomBar(true); + mMenuBar.setMenuBarListener(this); mEditText.setOnEditorActionListener(mPreferences.getBoolean(KEY_QUICK_SEND, false) ? this : null); mEditText.addTextChangedListener(this); mAccountSelectorAdapter = new AccountSelectorAdapter(this); - mAccountSelector.setAdapter(mAccountSelectorAdapter); - mAccountSelector.setOnItemClickListener(this); - mAccountSelector.setOnItemLongClickListener(this); - mAccountSelector.setScrollAfterItemClickEnabled(false); - mAccountSelector.setScrollRightSpacingEnabled(false); +// mAccountSelector.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)); +// mAccountSelector.setAdapter(mAccountSelectorAdapter); +// mAccountSelector.setOnItemClickListener(this); +// mAccountSelector.setOnItemLongClickListener(this); mMediaPreviewAdapter = new MediaPreviewAdapter(this); mMediasPreviewGrid.setAdapter(mMediaPreviewAdapter); @@ -638,9 +625,9 @@ public class ComposeActivity extends BaseSupportDialogActivity implements TextWa handleDefaultIntent(intent); } if (mSendAccountIds == null || mSendAccountIds.length == 0) { - final long[] ids_in_prefs = ArrayUtils.parseLongArray( + final long[] idsInPrefs = ArrayUtils.parseLongArray( mPreferences.getString(KEY_COMPOSE_ACCOUNTS, null), ','); - final long[] intersection = ArrayUtils.intersection(ids_in_prefs, mAccountIds); + final long[] intersection = ArrayUtils.intersection(idsInPrefs, mAccountIds); mSendAccountIds = intersection.length > 0 ? intersection : mAccountIds; } mOriginalText = ParseUtils.parseString(mEditText.getText()); @@ -649,52 +636,18 @@ public class ComposeActivity extends BaseSupportDialogActivity implements TextWa setTitle(R.string.compose); } - final boolean useBottomMenu = isSingleAccount() || !mBottomSendButton; - if (useBottomMenu) { - mBottomMenuBar.inflate(R.menu.menu_compose); - } else { - mActionMenuBar.inflate(R.menu.menu_compose); - } - mBottomMenuBar.setVisibility(useBottomMenu ? View.VISIBLE : View.GONE); - mActionMenuBar.setVisibility(useBottomMenu ? View.GONE : View.VISIBLE); + mMenuBar.inflate(R.menu.menu_compose); mSendView.setVisibility(mBottomSendButton ? View.GONE : View.VISIBLE); - mBottomSendDivider.setVisibility(mBottomSendButton ? View.VISIBLE : View.GONE); mBottomSendView.setVisibility(mBottomSendButton ? View.VISIBLE : View.GONE); mSendView.setOnClickListener(this); mBottomSendView.setOnClickListener(this); mSendView.setOnLongClickListener(this); mBottomSendView.setOnLongClickListener(this); - final Menu menu = mBottomMenuBar.getMenu(), actionBarMenu = mActionMenuBar.getMenu(); - final Menu showingMenu = mBottomSendButton ? actionBarMenu : menu; - if (showingMenu != null) { - final Intent compose_extensions_intent = new Intent(INTENT_ACTION_EXTENSION_COMPOSE); - addIntentToMenu(this, showingMenu, compose_extensions_intent, MENU_GROUP_COMPOSE_EXTENSION); - final Intent image_extensions_intent = new Intent(INTENT_ACTION_EXTENSION_EDIT_IMAGE); - addIntentToMenu(this, showingMenu, image_extensions_intent, MENU_GROUP_IMAGE_EXTENSION); - } - final LinearLayout.LayoutParams bottomMenuContainerParams = (LinearLayout.LayoutParams) mBottomMenuContainer - .getLayoutParams(); - final LinearLayout.LayoutParams accountSelectorParams = (LinearLayout.LayoutParams) mAccountSelector - .getLayoutParams(); - final int maxItemsShown; - final Resources res = getResources(); - if (isSingleAccount()) { - accountSelectorParams.weight = 0; - accountSelectorParams.width = ViewGroup.LayoutParams.WRAP_CONTENT; - bottomMenuContainerParams.weight = 1; - bottomMenuContainerParams.width = ViewGroup.LayoutParams.MATCH_PARENT; - maxItemsShown = res.getInteger(R.integer.max_compose_menu_buttons_bottom_singleaccount); - mAccountSelectorDivider.setVisibility(View.VISIBLE); - } else { - accountSelectorParams.weight = 1; - accountSelectorParams.width = ViewGroup.LayoutParams.MATCH_PARENT; - bottomMenuContainerParams.weight = 0; - bottomMenuContainerParams.width = ViewGroup.LayoutParams.WRAP_CONTENT; - maxItemsShown = res.getInteger(R.integer.max_compose_menu_buttons_bottom); - mAccountSelectorDivider.setVisibility(mBottomSendButton ? View.GONE : View.VISIBLE); - } - mBottomMenuContainer.setLayoutParams(bottomMenuContainerParams); - mBottomMenuBar.setMaxItemsShown(maxItemsShown); + final Menu menu = mMenuBar.getMenu(); + final Intent composeExtensionsIntent = new Intent(INTENT_ACTION_EXTENSION_COMPOSE); + addIntentToMenu(this, menu, composeExtensionsIntent, MENU_GROUP_COMPOSE_EXTENSION); + final Intent imageExtensionsIntent = new Intent(INTENT_ACTION_EXTENSION_EDIT_IMAGE); + addIntentToMenu(this, menu, imageExtensionsIntent, MENU_GROUP_IMAGE_EXTENSION); setMenu(); updateAccountSelection(); updateMediasPreview(); @@ -833,26 +786,32 @@ public class ComposeActivity extends BaseSupportDialogActivity implements TextWa mMentionUser = intent.getParcelableExtra(EXTRA_USER); mInReplyToStatus = intent.getParcelableExtra(EXTRA_STATUS); mInReplyToStatusId = mInReplyToStatus != null ? mInReplyToStatus.id : -1; - if (INTENT_ACTION_REPLY.equals(action)) - return handleReplyIntent(mInReplyToStatus); - else if (INTENT_ACTION_QUOTE.equals(action)) - return handleQuoteIntent(mInReplyToStatus); - else if (INTENT_ACTION_EDIT_DRAFT.equals(action)) { - mDraftItem = intent.getParcelableExtra(EXTRA_DRAFT); - return handleEditDraftIntent(mDraftItem); - } else if (INTENT_ACTION_MENTION.equals(action)) - return handleMentionIntent(mMentionUser); - else if (INTENT_ACTION_REPLY_MULTIPLE.equals(action)) { - final String[] screenNames = intent.getStringArrayExtra(EXTRA_SCREEN_NAMES); - final long accountId = intent.getLongExtra(EXTRA_ACCOUNT_ID, -1); - final long inReplyToUserId = intent.getLongExtra(EXTRA_IN_REPLY_TO_ID, -1); - return handleReplyMultipleIntent(screenNames, accountId, inReplyToUserId); - } else if (INTENT_ACTION_COMPOSE_TAKE_PHOTO.equals(action)) { - takePhoto(); - return true; - } else if (INTENT_ACTION_COMPOSE_PICK_IMAGE.equals(action)) { - pickImage(); - return true; + switch (action) { + case INTENT_ACTION_REPLY: { + return handleReplyIntent(mInReplyToStatus); + } + case INTENT_ACTION_QUOTE: { + return handleQuoteIntent(mInReplyToStatus); + } + case INTENT_ACTION_EDIT_DRAFT: { + mDraftItem = intent.getParcelableExtra(EXTRA_DRAFT); + return handleEditDraftIntent(mDraftItem); + } + case INTENT_ACTION_MENTION: { + return handleMentionIntent(mMentionUser); + } + case INTENT_ACTION_REPLY_MULTIPLE: { + final String[] screenNames = intent.getStringArrayExtra(EXTRA_SCREEN_NAMES); + final long accountId = intent.getLongExtra(EXTRA_ACCOUNT_ID, -1); + final long inReplyToUserId = intent.getLongExtra(EXTRA_IN_REPLY_TO_ID, -1); + return handleReplyMultipleIntent(screenNames, accountId, inReplyToUserId); + } + case INTENT_ACTION_COMPOSE_TAKE_PHOTO: { + return takePhoto(); + } + case INTENT_ACTION_COMPOSE_PICK_IMAGE: { + return pickImage(); + } } // Unknown action or no intent extras return false; @@ -928,10 +887,6 @@ public class ComposeActivity extends BaseSupportDialogActivity implements TextWa return false; } - private boolean isSingleAccount() { - return mAccountIds != null && mAccountIds.length == 1; - } - private boolean noReplyContent(final String text) { if (text == null) return true; final String action = getIntent().getAction(); @@ -955,7 +910,7 @@ public class ComposeActivity extends BaseSupportDialogActivity implements TextWa return true; } - private void pickImage() { + private boolean pickImage() { final Intent intent = new Intent(Intent.ACTION_PICK); intent.setType("image/*"); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); @@ -963,7 +918,9 @@ public class ComposeActivity extends BaseSupportDialogActivity implements TextWa startActivityForResult(intent, REQUEST_PICK_IMAGE); } catch (final ActivityNotFoundException e) { showErrorMessage(this, null, e, false); + return false; } + return true; } private void setCommonMenu(final Menu menu) { @@ -986,7 +943,7 @@ public class ComposeActivity extends BaseSupportDialogActivity implements TextWa itemAttachLocation.setChecked(true); } else { setProgressVisibility(false); - mPreferences.edit().putBoolean(KEY_ATTACH_LOCATION, false).commit(); + mPreferences.edit().putBoolean(KEY_ATTACH_LOCATION, false).apply(); itemAttachLocation.setChecked(false); } } @@ -1037,31 +994,30 @@ public class ComposeActivity extends BaseSupportDialogActivity implements TextWa } private void setMenu() { - if (mBottomMenuBar == null || mActionMenuBar == null) return; - final Menu bottomMenu = mBottomMenuBar.getMenu(), actionMenu = mActionMenuBar.getMenu(); + if (mMenuBar == null) return; + final Menu bottomMenu = mMenuBar.getMenu(); setCommonMenu(bottomMenu); - setCommonMenu(actionMenu); - mActionMenuBar.show(); - mBottomMenuBar.show(); + mMenuBar.show(); } private void setProgressVisibility(final boolean visible) { mProgress.setVisibility(visible ? View.VISIBLE : View.GONE); } - private void takePhoto() { + private boolean takePhoto() { final Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); - if (getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { - final File cache_dir = getExternalCacheDir(); - final File file = new File(cache_dir, "tmp_photo_" + System.currentTimeMillis()); - mTempPhotoUri = Uri.fromFile(file); - intent.putExtra(MediaStore.EXTRA_OUTPUT, mTempPhotoUri); - try { - startActivityForResult(intent, REQUEST_TAKE_PHOTO); - } catch (final ActivityNotFoundException e) { - showErrorMessage(this, null, e, false); - } + if (!getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) return false; + final File cache_dir = getExternalCacheDir(); + final File file = new File(cache_dir, "tmp_photo_" + System.currentTimeMillis()); + mTempPhotoUri = Uri.fromFile(file); + intent.putExtra(MediaStore.EXTRA_OUTPUT, mTempPhotoUri); + try { + startActivityForResult(intent, REQUEST_TAKE_PHOTO); + } catch (final ActivityNotFoundException e) { + showErrorMessage(this, null, e, false); + return false; } + return true; } private void updateAccountSelection() { @@ -1069,7 +1025,7 @@ public class ComposeActivity extends BaseSupportDialogActivity implements TextWa if (mShouldSaveAccounts) { final SharedPreferences.Editor editor = mPreferences.edit(); editor.putString(KEY_COMPOSE_ACCOUNTS, ArrayUtils.toString(mSendAccountIds, ',', false)); - editor.commit(); + editor.apply(); } mAccountSelectorAdapter.clearAccountSelection(); for (final long accountId : mSendAccountIds) { @@ -1312,12 +1268,16 @@ public class ComposeActivity extends BaseSupportDialogActivity implements TextWa } - private static class AccountSelectorAdapter extends BaseArrayAdapter { + private static class AccountSelectorAdapter extends ArrayRecyclerAdapter { - private final LongSparseArray mAccountSelectStates = new LongSparseArray(); + private final LongSparseArray mAccountSelectStates = new LongSparseArray<>(); + + private final LayoutInflater mInflater; + private final ImageLoaderWrapper mImageLoader; public AccountSelectorAdapter(final Context context) { - super(context, R.layout.gallery_item_compose_account, Account.getAccountsList(context, false)); + mInflater = LayoutInflater.from(context); + mImageLoader = TwidereApplication.getInstance(context).getImageLoaderWrapper(); } public void clearAccountSelection() { @@ -1327,7 +1287,7 @@ public class ComposeActivity extends BaseSupportDialogActivity implements TextWa public long[] getSelectedAccountIds() { final ArrayList list = new ArrayList(); - for (int i = 0, j = getCount(); i < j; i++) { + for (int i = 0, j = getItemCount(); i < j; i++) { final Account account = getItem(i); if (mAccountSelectStates.get(account.account_id, false)) { list.add(account.account_id); @@ -1336,22 +1296,38 @@ public class ComposeActivity extends BaseSupportDialogActivity implements TextWa return ArrayUtils.fromList(list); } - @Override - public View getView(final int position, final View convertView, final ViewGroup parent) { - final View view = super.getView(position, convertView, parent); - final Account account = getItem(position); - final ImageLoaderWrapper loader = getImageLoader(); - final ImageView icon = (ImageView) view.findViewById(android.R.id.icon); - loader.displayProfileImage(icon, account.profile_image_url); - view.setActivated(mAccountSelectStates.get(account.account_id, false)); - return view; - } - public void setAccountSelected(final long accountId, final boolean selected) { mAccountSelectStates.put(accountId, selected); notifyDataSetChanged(); } + @Override + public void onBindViewHolder(AccountAvatarHolder holder, int position, Account item) { + holder.setAccount(mImageLoader, item, mAccountSelectStates); + } + + @Override + public AccountAvatarHolder onCreateViewHolder(ViewGroup parent, int viewType) { + return new AccountAvatarHolder(mInflater.inflate(R.layout.gallery_item_compose_account, parent, false)); + } + + + } + + + private static class AccountAvatarHolder extends ViewHolder { + + private final ImageView icon; + + public AccountAvatarHolder(View itemView) { + super(itemView); + icon = (ImageView) itemView.findViewById(android.R.id.icon); + } + + public void setAccount(ImageLoaderWrapper loader, Account account, LongSparseArray states) { + loader.displayProfileImage(icon, account.profile_image_url); + states.get(account.account_id, false); + } } private static class AddBitmapTask extends AddMediaTask { @@ -1411,9 +1387,13 @@ public class ComposeActivity extends BaseSupportDialogActivity implements TextWa copyStream(is, os); os.close(); if (ContentResolver.SCHEME_FILE.equals(src.getScheme()) && delete_src) { - new File(src.getPath()).delete(); + final File file = new File(src.getPath()); + if (!file.delete()) { + Log.d(LOGTAG, String.format("Unable to delete %s", file)); + } } - } catch (final Exception e) { + } catch (final IOException e) { + Log.w(LOGTAG, e); return false; } return true; @@ -1451,9 +1431,13 @@ public class ComposeActivity extends BaseSupportDialogActivity implements TextWa if (medias == null) return false; try { for (final ParcelableMediaUpdate media : medias) { - final Uri target = Uri.parse(media.uri); - if (ContentResolver.SCHEME_FILE.equals(target.getScheme())) { - new File(target.getPath()).delete(); + if (media.uri == null) continue; + final Uri uri = Uri.parse(media.uri); + if (ContentResolver.SCHEME_FILE.equals(uri.getScheme())) { + final File file = new File(uri.getPath()); + if (!file.delete()) { + Log.d(LOGTAG, String.format("Unable to delete %s", file)); + } } } } catch (final Exception e) { @@ -1488,15 +1472,15 @@ public class ComposeActivity extends BaseSupportDialogActivity implements TextWa @Override protected Void doInBackground(final Void... params) { - try { - for (final ParcelableMediaUpdate media : activity.getMediasList()) { - final Uri uri = Uri.parse(media.uri); - if (uri == null) return null; - if (ContentResolver.SCHEME_FILE.equals(uri.getScheme())) { - new File(uri.getPath()).delete(); + for (final ParcelableMediaUpdate media : activity.getMediasList()) { + if (media.uri == null) continue; + final Uri uri = Uri.parse(media.uri); + if (ContentResolver.SCHEME_FILE.equals(uri.getScheme())) { + final File file = new File(uri.getPath()); + if (!file.delete()) { + Log.d(LOGTAG, String.format("Unable to delete %s", file)); } } - } catch (final Exception e) { } return null; } diff --git a/twidere/src/main/java/org/mariotaku/twidere/activity/support/DraftsActivity.java b/twidere/src/main/java/org/mariotaku/twidere/activity/support/DraftsActivity.java index 769ab9ac9..80831594f 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/activity/support/DraftsActivity.java +++ b/twidere/src/main/java/org/mariotaku/twidere/activity/support/DraftsActivity.java @@ -169,7 +169,7 @@ public class DraftsActivity extends BaseSupportActivity implements LoaderCallbac switch (item.getItemId()) { case MENU_HOME: { onBackPressed(); - break; + return true; } } return super.onOptionsItemSelected(item); diff --git a/twidere/src/main/java/org/mariotaku/twidere/activity/support/HomeActivity.java b/twidere/src/main/java/org/mariotaku/twidere/activity/support/HomeActivity.java index e3507d562..6a8eeb801 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/activity/support/HomeActivity.java +++ b/twidere/src/main/java/org/mariotaku/twidere/activity/support/HomeActivity.java @@ -32,7 +32,7 @@ import android.content.SharedPreferences; import android.content.pm.ActivityInfo; import android.database.ContentObserver; import android.graphics.Canvas; -import android.graphics.Color; +import android.graphics.PorterDuff.Mode; import android.graphics.Rect; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; @@ -537,12 +537,9 @@ public class HomeActivity extends BaseSupportActivity implements OnClickListener } mActionsButton.setOnClickListener(this); mActionsButton.setOnLongClickListener(this); - initTabs(); - final boolean tabsNotEmpty = mPagerAdapter.getCount() > 0; - mEmptyTabHint.setVisibility(tabsNotEmpty ? View.GONE : View.VISIBLE); - mViewPager.setVisibility(tabsNotEmpty ? View.VISIBLE : View.GONE); setTabPosition(initialTabPosition); setupSlidingMenu(); + setupBars(); showDataProfilingRequest(); initUnreadCount(); updateActionsButton(); @@ -558,24 +555,34 @@ public class HomeActivity extends BaseSupportActivity implements OnClickListener } } mPagerPosition = Float.NaN; - final int themeColor = getThemeColor(), contrastColor = Utils.getContrastYIQ(themeColor, 192); + setupHomeTabs(); + } + + private void setupBars() { + final int themeColor = getThemeColor(); final int themeResId = getCurrentThemeResourceId(); final boolean isTransparent = ThemeUtils.isTransparentBackground(themeResId); final int actionBarAlpha = isTransparent ? ThemeUtils.getUserThemeBackgroundAlpha(this) : 0xFF; + final IHomeActionButton homeActionButton = (IHomeActionButton) mActionsButton; + mTabIndicator.setItemContext(ThemeUtils.getActionBarContext(this)); if (ThemeUtils.isColoredActionBar(themeResId)) { + final int contrastColor = Utils.getContrastYIQ(themeColor, 192); ViewAccessor.setBackground(mTabIndicator, new ColorDrawable(themeColor)); + homeActionButton.setButtonColor(themeColor); + homeActionButton.setIconColor(contrastColor, Mode.SRC_ATOP); mTabIndicator.setStripColor(contrastColor); mTabIndicator.setIconColor(contrastColor); } else { - ViewAccessor.setBackground(mTabIndicator, ThemeUtils.getActionBarBackground(this, false)); + final int backgroundColor = ThemeUtils.getThemeBackgroundColor(mTabIndicator.getItemContext()); + final int foregroundColor = ThemeUtils.getThemeForegroundColor(mTabIndicator.getItemContext()); + ViewAccessor.setBackground(mTabIndicator, ThemeUtils.getActionBarBackground(this, themeResId)); + homeActionButton.setButtonColor(backgroundColor); + homeActionButton.setIconColor(foregroundColor, Mode.SRC_ATOP); mTabIndicator.setStripColor(themeColor); - mTabIndicator.setIconColor(ThemeUtils.isLightActionBar(themeResId) ? Color.BLACK : Color.WHITE); + mTabIndicator.setIconColor(foregroundColor); } mTabIndicator.setAlpha(actionBarAlpha / 255f); - if (mActionsButton instanceof IHomeActionButton) { - ((IHomeActionButton) mActionsButton).setColor(themeColor); - mActionsButton.setAlpha(actionBarAlpha / 255f); - } + mActionsButton.setAlpha(actionBarAlpha / 255f); ViewAccessor.setBackground(mActionBarOverlay, ThemeUtils.getWindowContentOverlay(this)); } @@ -701,12 +708,14 @@ public class HomeActivity extends BaseSupportActivity implements OnClickListener return mTwitterWrapper.hasActivatedTask(); } - private void initTabs() { + private void setupHomeTabs() { final List tabs = getHomeTabs(this); mCustomTabs.clear(); mCustomTabs.addAll(tabs); mPagerAdapter.clear(); mPagerAdapter.addTabs(tabs); + mEmptyTabHint.setVisibility(tabs.isEmpty() ? View.VISIBLE : View.GONE); + mViewPager.setVisibility(tabs.isEmpty() ? View.GONE : View.VISIBLE); } private void initUnreadCount() { diff --git a/twidere/src/main/java/org/mariotaku/twidere/activity/support/LinkHandlerActivity.java b/twidere/src/main/java/org/mariotaku/twidere/activity/support/LinkHandlerActivity.java index 9344b9d43..599a11035 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/activity/support/LinkHandlerActivity.java +++ b/twidere/src/main/java/org/mariotaku/twidere/activity/support/LinkHandlerActivity.java @@ -124,7 +124,7 @@ public class LinkHandlerActivity extends BaseSupportActivity implements OnClickL if (actionBar != null) { actionBar.setDisplayHomeAsUpEnabled(true); } - setContentView(R.layout.layout_link_handler); + setContentView(R.layout.activity_content_fragment); setProgressBarIndeterminateVisibility(false); if (data == null || !showFragment(data)) { finish(); diff --git a/twidere/src/main/java/org/mariotaku/twidere/activity/support/MenuDialogFragment.java b/twidere/src/main/java/org/mariotaku/twidere/activity/support/MenuDialogFragment.java index 9343d336d..e5fac17cf 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/activity/support/MenuDialogFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/activity/support/MenuDialogFragment.java @@ -3,9 +3,9 @@ package org.mariotaku.twidere.activity.support; import android.app.AlertDialog; import android.app.Dialog; import android.content.Context; +import android.graphics.PorterDuff.Mode; import android.os.Bundle; import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentActivity; import android.view.Menu; import android.view.MenuItem; import android.view.MenuItem.OnMenuItemClickListener; @@ -16,29 +16,12 @@ import android.widget.ListView; import org.mariotaku.menucomponent.internal.menu.MenuAdapter; import org.mariotaku.menucomponent.internal.menu.MenuUtils; -import org.mariotaku.twidere.activity.iface.IThemedActivity; import org.mariotaku.twidere.fragment.support.BaseSupportDialogFragment; import org.mariotaku.twidere.menu.TwidereMenuInflater; import org.mariotaku.twidere.util.ThemeUtils; public abstract class MenuDialogFragment extends BaseSupportDialogFragment implements OnItemClickListener { - private Context mThemedContext; - - public Context getThemedContext() { - if (mThemedContext != null) return mThemedContext; - final FragmentActivity activity = getActivity(); - final int themeRes, accentColor; - if (activity instanceof IThemedActivity) { - themeRes = ((IThemedActivity) activity).getThemeResourceId(); - accentColor = ((IThemedActivity) activity).getThemeColor(); - } else { - themeRes = ThemeUtils.getSettingsThemeResource(activity); - accentColor = ThemeUtils.getUserThemeColor(activity); - } - return mThemedContext = ThemeUtils.getThemedContextForActionIcons(activity, themeRes, accentColor); - } - @Override public Dialog onCreateDialog(final Bundle savedInstanceState) { final Context context = getThemedContext(); @@ -50,10 +33,17 @@ public abstract class MenuDialogFragment extends BaseSupportDialogFragment imple builder.setView(listView); final Menu menu = MenuUtils.createMenu(context); onCreateMenu(new TwidereMenuInflater(context), menu); + final int itemColor = ThemeUtils.getThemeForegroundColor(context); + final int highlightColor = ThemeUtils.getUserAccentColor(context); + ThemeUtils.applyColorFilterToMenuIcon(menu, itemColor, highlightColor, Mode.SRC_ATOP); adapter.setMenu(menu); return builder.create(); } + public Context getThemedContext() { + return getActivity(); + } + @Override public void onItemClick(final AdapterView parent, final View view, final int position, final long id) { final Fragment parentFragment = getParentFragment(); diff --git a/twidere/src/main/java/org/mariotaku/twidere/adapter/AccountsAdapter.java b/twidere/src/main/java/org/mariotaku/twidere/adapter/AccountsAdapter.java index 15d85985a..bd041615b 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/adapter/AccountsAdapter.java +++ b/twidere/src/main/java/org/mariotaku/twidere/adapter/AccountsAdapter.java @@ -25,7 +25,8 @@ import android.database.Cursor; import android.view.View; import android.view.ViewGroup; import android.widget.ListView; -import android.widget.SimpleCursorAdapter; + +import com.mobeta.android.dslv.SimpleDragSortCursorAdapter; import org.mariotaku.twidere.Constants; import org.mariotaku.twidere.R; @@ -34,91 +35,90 @@ import org.mariotaku.twidere.provider.TweetStore.Accounts; import org.mariotaku.twidere.util.ImageLoaderWrapper; import org.mariotaku.twidere.view.holder.AccountViewHolder; -public class AccountsAdapter extends SimpleCursorAdapter implements Constants { +public class AccountsAdapter extends SimpleDragSortCursorAdapter implements Constants { - private final ImageLoaderWrapper mImageLoader; - private final SharedPreferences mPreferences; + private final ImageLoaderWrapper mImageLoader; + private final SharedPreferences mPreferences; - private int mUserColorIdx, mProfileImageIdx, mScreenNameIdx, mAccountIdIdx; - private long mDefaultAccountId; + private int mUserColorIdx, mProfileImageIdx, mScreenNameIdx, mAccountIdIdx; + private long mDefaultAccountId; - private boolean mDisplayProfileImage; - private int mChoiceMode; + private boolean mDisplayProfileImage; + private int mChoiceMode; - public AccountsAdapter(final Context context) { - super(context, R.layout.list_item_account, null, new String[] { Accounts.NAME }, - new int[] { android.R.id.text1 }, 0); - final TwidereApplication application = TwidereApplication.getInstance(context); - mImageLoader = application.getImageLoaderWrapper(); - mPreferences = context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE); - } + public AccountsAdapter(final Context context) { + super(context, R.layout.list_item_account, null, new String[]{Accounts.NAME}, + new int[]{android.R.id.text1}, 0); + final TwidereApplication application = TwidereApplication.getInstance(context); + mImageLoader = application.getImageLoaderWrapper(); + mPreferences = context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE); + } - @Override - public void bindView(final View view, final Context context, final Cursor cursor) { - final int color = cursor.getInt(mUserColorIdx); - final AccountViewHolder holder = (AccountViewHolder) view.getTag(); - holder.screen_name.setText("@" + cursor.getString(mScreenNameIdx)); - holder.setAccountColor(color); - holder.setIsDefault(mDefaultAccountId != -1 && mDefaultAccountId == cursor.getLong(mAccountIdIdx)); - if (mDisplayProfileImage) { - mImageLoader.displayProfileImage(holder.profile_image, cursor.getString(mProfileImageIdx)); - } else { + @Override + public void bindView(final View view, final Context context, final Cursor cursor) { + final int color = cursor.getInt(mUserColorIdx); + final AccountViewHolder holder = (AccountViewHolder) view.getTag(); + holder.screen_name.setText("@" + cursor.getString(mScreenNameIdx)); + holder.setAccountColor(color); + holder.setIsDefault(mDefaultAccountId != -1 && mDefaultAccountId == cursor.getLong(mAccountIdIdx)); + if (mDisplayProfileImage) { + mImageLoader.displayProfileImage(holder.profile_image, cursor.getString(mProfileImageIdx)); + } else { mImageLoader.cancelDisplayTask(holder.profile_image); - holder.profile_image.setImageResource(R.drawable.ic_profile_image_default); - } - final boolean isMultipleChoice = mChoiceMode == ListView.CHOICE_MODE_MULTIPLE - || mChoiceMode == ListView.CHOICE_MODE_MULTIPLE_MODAL; - holder.checkbox.setVisibility(isMultipleChoice ? View.VISIBLE : View.GONE); - super.bindView(view, context, cursor); - } + holder.profile_image.setImageResource(R.drawable.ic_profile_image_default); + } + final boolean isMultipleChoice = mChoiceMode == ListView.CHOICE_MODE_MULTIPLE + || mChoiceMode == ListView.CHOICE_MODE_MULTIPLE_MODAL; + holder.checkbox.setVisibility(isMultipleChoice ? View.VISIBLE : View.GONE); + super.bindView(view, context, cursor); + } - @Override - public long getItemId(final int position) { - final Cursor c = getCursor(); - if (c == null || c.isClosed()) return -1; - c.moveToPosition(position); - return c.getLong(mAccountIdIdx); - } + @Override + public long getItemId(final int position) { + final Cursor c = getCursor(); + if (c == null || c.isClosed()) return -1; + c.moveToPosition(position); + return c.getLong(mAccountIdIdx); + } - @Override - public boolean hasStableIds() { - return true; - } + @Override + public boolean hasStableIds() { + return true; + } - @Override - public View newView(final Context context, final Cursor cursor, final ViewGroup parent) { + @Override + public View newView(final Context context, final Cursor cursor, final ViewGroup parent) { + final View view = super.newView(context, cursor, parent); + final AccountViewHolder holder = new AccountViewHolder(view); + view.setTag(holder); + return view; + } - final View view = super.newView(context, cursor, parent); - final AccountViewHolder viewholder = new AccountViewHolder(view); - view.setTag(viewholder); - return view; - } + @Override + public void notifyDataSetChanged() { + mDefaultAccountId = mPreferences.getLong(KEY_DEFAULT_ACCOUNT_ID, -1); + super.notifyDataSetChanged(); + } - @Override - public void notifyDataSetChanged() { - mDefaultAccountId = mPreferences.getLong(KEY_DEFAULT_ACCOUNT_ID, -1); - super.notifyDataSetChanged(); - } + public void setChoiceMode(final int mode) { + if (mChoiceMode == mode) return; + mChoiceMode = mode; + notifyDataSetChanged(); + } - public void setChoiceMode(final int mode) { - if (mChoiceMode == mode) return; - mChoiceMode = mode; - notifyDataSetChanged(); - } + public void setDisplayProfileImage(final boolean display) { + mDisplayProfileImage = display; + notifyDataSetChanged(); + } - public void setDisplayProfileImage(final boolean display) { - mDisplayProfileImage = display; - notifyDataSetChanged(); - } - - @Override - public Cursor swapCursor(final Cursor cursor) { - if (cursor != null) { - mAccountIdIdx = cursor.getColumnIndex(Accounts.ACCOUNT_ID); - mUserColorIdx = cursor.getColumnIndex(Accounts.COLOR); - mProfileImageIdx = cursor.getColumnIndex(Accounts.PROFILE_IMAGE_URL); - mScreenNameIdx = cursor.getColumnIndex(Accounts.SCREEN_NAME); - } - return super.swapCursor(cursor); - } + @Override + public Cursor swapCursor(final Cursor cursor) { + if (cursor != null) { + mAccountIdIdx = cursor.getColumnIndex(Accounts.ACCOUNT_ID); + mUserColorIdx = cursor.getColumnIndex(Accounts.COLOR); + mProfileImageIdx = cursor.getColumnIndex(Accounts.PROFILE_IMAGE_URL); + mScreenNameIdx = cursor.getColumnIndex(Accounts.SCREEN_NAME); + } + return super.swapCursor(cursor); + } } diff --git a/twidere/src/main/java/org/mariotaku/twidere/adapter/ArrayRecyclerAdapter.java b/twidere/src/main/java/org/mariotaku/twidere/adapter/ArrayRecyclerAdapter.java new file mode 100644 index 000000000..e28e65b54 --- /dev/null +++ b/twidere/src/main/java/org/mariotaku/twidere/adapter/ArrayRecyclerAdapter.java @@ -0,0 +1,67 @@ +package org.mariotaku.twidere.adapter; + +import android.support.v7.widget.RecyclerView.Adapter; +import android.support.v7.widget.RecyclerView.ViewHolder; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +/** + * Created by mariotaku on 14/10/27. + */ +public abstract class ArrayRecyclerAdapter extends Adapter { + + protected final ArrayList mData = new ArrayList(); + + @Override + public final void onBindViewHolder(H holder, int position) { + onBindViewHolder(holder, position, getItem(position)); + } + + public abstract void onBindViewHolder(H holder, int position, T item); + + + public void add(final T item) { + if (item == null) return; + mData.add(item); + notifyDataSetChanged(); + } + + public void addAll(final Collection collection) { + mData.addAll(collection); + notifyDataSetChanged(); + } + + public void clear() { + mData.clear(); + notifyDataSetChanged(); + } + + @Override + public int getItemCount() { + return mData.size(); + } + + public T getItem(final int position) { + return mData.get(position); + } + + public boolean remove(final int position) { + final boolean ret = mData.remove(position) != null; + notifyDataSetChanged(); + return ret; + } + + public void removeAll(final List collection) { + mData.removeAll(collection); + notifyDataSetChanged(); + } + + public void sort(final Comparator comparator) { + Collections.sort(mData, comparator); + notifyDataSetChanged(); + } +} diff --git a/twidere/src/main/java/org/mariotaku/twidere/adapter/UserHashtagAutoCompleteAdapter.java b/twidere/src/main/java/org/mariotaku/twidere/adapter/UserHashtagAutoCompleteAdapter.java index 4a79deaa6..906068aec 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/adapter/UserHashtagAutoCompleteAdapter.java +++ b/twidere/src/main/java/org/mariotaku/twidere/adapter/UserHashtagAutoCompleteAdapter.java @@ -98,7 +98,7 @@ public class UserHashtagAutoCompleteAdapter extends SimpleCursorAdapter implemen accentColor = ((IThemedActivity) context).getThemeColor(); } else { themeRes = ThemeUtils.getThemeResource(context); - accentColor = ThemeUtils.getUserThemeColor(context); + accentColor = ThemeUtils.getUserAccentColor(context); } mResources = ThemeUtils.getThemedResourcesForActionIcons(context, themeRes, accentColor); } diff --git a/twidere/src/main/java/org/mariotaku/twidere/dialog/ColorPickerDialog.java b/twidere/src/main/java/org/mariotaku/twidere/dialog/ColorPickerDialog.java index 28fb75fd7..4385d15f9 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/dialog/ColorPickerDialog.java +++ b/twidere/src/main/java/org/mariotaku/twidere/dialog/ColorPickerDialog.java @@ -30,173 +30,185 @@ import android.graphics.Paint; import android.graphics.PixelFormat; import android.graphics.Rect; import android.graphics.drawable.BitmapDrawable; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.RecyclerView.ViewHolder; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import com.scvngr.levelup.views.gallery.AdapterView; -import com.scvngr.levelup.views.gallery.AdapterView.OnItemClickListener; -import com.scvngr.levelup.views.gallery.Gallery; - import org.mariotaku.twidere.Constants; import org.mariotaku.twidere.R; -import org.mariotaku.twidere.adapter.ArrayAdapter; +import org.mariotaku.twidere.adapter.ArrayRecyclerAdapter; import org.mariotaku.twidere.view.ColorPickerView; import org.mariotaku.twidere.view.ColorPickerView.OnColorChangedListener; import org.mariotaku.twidere.view.ForegroundColorView; -public final class ColorPickerDialog extends AlertDialog implements OnItemClickListener, OnColorChangedListener, - Constants { +public final class ColorPickerDialog extends AlertDialog implements Constants, OnColorChangedListener { - private final static int[] COLORS = { HOLO_RED_DARK, HOLO_RED_LIGHT, HOLO_ORANGE_DARK, HOLO_ORANGE_LIGHT, - HOLO_GREEN_LIGHT, HOLO_GREEN_DARK, HOLO_BLUE_LIGHT, HOLO_BLUE_DARK, HOLO_PURPLE_DARK, HOLO_PURPLE_LIGHT, - Color.WHITE }; + private final static int[] COLORS = {HOLO_RED_DARK, HOLO_RED_LIGHT, HOLO_ORANGE_DARK, HOLO_ORANGE_LIGHT, + HOLO_GREEN_LIGHT, HOLO_GREEN_DARK, HOLO_BLUE_LIGHT, HOLO_BLUE_DARK, HOLO_PURPLE_DARK, HOLO_PURPLE_LIGHT, + Color.WHITE}; - private final ColorsAdapter mColorsAdapter; + private final ColorsAdapter mColorsAdapter; - private ColorPickerView mColorPicker; - private Gallery mColorPresets; + private ColorPickerView mColorPicker; + private RecyclerView mColorPresets; - private final Resources mResources; + private final Resources mResources; - private final Bitmap mTempBitmap; - private final Canvas mCanvas; + private final Bitmap mTempBitmap; + private final Canvas mCanvas; - private final int mIconWidth, mIconHeight; - private final int mRectrangleSize, mNumRectanglesHorizontal, mNumRectanglesVertical; + private final int mIconWidth, mIconHeight; + private final int mRectrangleSize, mNumRectanglesHorizontal, mNumRectanglesVertical; - public ColorPickerDialog(final Context context, final int initialColor, final boolean showAlphaSlider) { - super(context); - mColorsAdapter = new ColorsAdapter(context); - mResources = context.getResources(); - final float density = mResources.getDisplayMetrics().density; - mIconWidth = (int) (32 * density); - mIconHeight = (int) (32 * density); - mRectrangleSize = (int) (density * 5); - mNumRectanglesHorizontal = (int) Math.ceil(mIconWidth / mRectrangleSize); - mNumRectanglesVertical = (int) Math.ceil(mIconHeight / mRectrangleSize); - mTempBitmap = Bitmap.createBitmap(mIconWidth, mIconHeight, Config.ARGB_8888); - mCanvas = new Canvas(mTempBitmap); - init(context, initialColor, showAlphaSlider); - initColors(); - mColorsAdapter.setCurrentColor(initialColor); - } + public ColorPickerDialog(final Context context, final int initialColor, final boolean showAlphaSlider) { + super(context); + mColorsAdapter = new ColorsAdapter(context); + mResources = context.getResources(); + final float density = mResources.getDisplayMetrics().density; + mIconWidth = (int) (32 * density); + mIconHeight = (int) (32 * density); + mRectrangleSize = (int) (density * 5); + mNumRectanglesHorizontal = (int) Math.ceil(mIconWidth / mRectrangleSize); + mNumRectanglesVertical = (int) Math.ceil(mIconHeight / mRectrangleSize); + mTempBitmap = Bitmap.createBitmap(mIconWidth, mIconHeight, Config.ARGB_8888); + mCanvas = new Canvas(mTempBitmap); + init(context, initialColor, showAlphaSlider); + initColors(); + mColorsAdapter.setCurrentColor(initialColor); + } - public int getColor() { - return mColorPicker.getColor(); - } + public int getColor() { + return mColorPicker.getColor(); + } - @Override - public void onColorChanged(final int color) { - mColorsAdapter.setCurrentColor(color); - updateColorPreviewBitmap(color); - setIcon(new BitmapDrawable(mResources, mTempBitmap)); - } + @Override + public void onColorChanged(final int color) { + mColorsAdapter.setCurrentColor(color); + updateColorPreviewBitmap(color); + setIcon(new BitmapDrawable(mResources, mTempBitmap)); + } - @Override - public void onItemClick(final AdapterView parent, final View view, final int position, final long id) { - final int color = mColorsAdapter.getItem(position); - if (mColorPicker == null) return; - mColorPicker.setColor(color, true); - } +// @Override +// public void onItemClick(final AdapterView parent, final View view, final int position, final long id) { +// final int color = mColorsAdapter.getItem(position); +// if (mColorPicker == null) return; +// mColorPicker.setColor(color, true); +// } - public final void setAlphaSliderVisible(final boolean visible) { - mColorPicker.setAlphaSliderVisible(visible); - } + public final void setAlphaSliderVisible(final boolean visible) { + mColorPicker.setAlphaSliderVisible(visible); + } - public final void setColor(final int color) { - mColorPicker.setColor(color); - } + public final void setColor(final int color) { + mColorPicker.setColor(color); + } - public final void setColor(final int color, final boolean callback) { - mColorPicker.setColor(color, callback); - } + public final void setColor(final int color, final boolean callback) { + mColorPicker.setColor(color, callback); + } - private void init(final Context context, final int color, final boolean showAlphaSlider) { + private void init(final Context context, final int color, final boolean showAlphaSlider) { - // To fight color branding. - getWindow().setFormat(PixelFormat.RGBA_8888); + // To fight color branding. + getWindow().setFormat(PixelFormat.RGBA_8888); - final LayoutInflater inflater = LayoutInflater.from(getContext()); - final View dialogView = inflater.inflate(R.layout.dialog_color_picker, null); + final LayoutInflater inflater = LayoutInflater.from(getContext()); + final View dialogView = inflater.inflate(R.layout.dialog_color_picker, null); - mColorPicker = (ColorPickerView) dialogView.findViewById(R.id.color_picker); - mColorPresets = (Gallery) dialogView.findViewById(R.id.color_presets); + mColorPicker = (ColorPickerView) dialogView.findViewById(R.id.color_picker); + mColorPresets = (RecyclerView) dialogView.findViewById(R.id.color_presets); - mColorPicker.setOnColorChangedListener(this); - mColorPresets.setAdapter(mColorsAdapter); - mColorPresets.setOnItemClickListener(this); - mColorPresets.setScrollAfterItemClickEnabled(false); - mColorPresets.setScrollRightSpacingEnabled(false); + mColorPicker.setOnColorChangedListener(this); + mColorPresets.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)); + mColorPresets.setAdapter(mColorsAdapter); +// mColorPresets.setOnItemClickListener(this); - setColor(color, true); - setAlphaSliderVisible(showAlphaSlider); + setColor(color, true); + setAlphaSliderVisible(showAlphaSlider); - setView(dialogView); - setTitle(R.string.pick_color); - } + setView(dialogView); + setTitle(R.string.pick_color); + } - private void initColors() { - for (final int color : COLORS) { - mColorsAdapter.add(color); - } - } + private void initColors() { + for (final int color : COLORS) { + mColorsAdapter.add(color); + } + } - private void updateColorPreviewBitmap(final int color) { - final Rect r = new Rect(); - boolean verticalStartWhite = true; - for (int i = 0; i <= mNumRectanglesVertical; i++) { + private void updateColorPreviewBitmap(final int color) { + final Rect r = new Rect(); + boolean verticalStartWhite = true; + for (int i = 0; i <= mNumRectanglesVertical; i++) { - boolean isWhite = verticalStartWhite; - for (int j = 0; j <= mNumRectanglesHorizontal; j++) { + boolean isWhite = verticalStartWhite; + for (int j = 0; j <= mNumRectanglesHorizontal; j++) { - r.top = i * mRectrangleSize; - r.left = j * mRectrangleSize; - r.bottom = r.top + mRectrangleSize; - r.right = r.left + mRectrangleSize; - final Paint paint = new Paint(); - paint.setColor(isWhite ? Color.WHITE : Color.GRAY); + r.top = i * mRectrangleSize; + r.left = j * mRectrangleSize; + r.bottom = r.top + mRectrangleSize; + r.right = r.left + mRectrangleSize; + final Paint paint = new Paint(); + paint.setColor(isWhite ? Color.WHITE : Color.GRAY); - mCanvas.drawRect(r, paint); + mCanvas.drawRect(r, paint); - isWhite = !isWhite; - } + isWhite = !isWhite; + } - verticalStartWhite = !verticalStartWhite; + verticalStartWhite = !verticalStartWhite; - } - mCanvas.drawColor(color); - final Paint paint = new Paint(); - paint.setColor(Color.WHITE); - paint.setStrokeWidth(2.0f); - final float[] points = new float[] { 0, 0, mIconWidth, 0, 0, 0, 0, mIconHeight, mIconWidth, 0, mIconWidth, - mIconHeight, 0, mIconHeight, mIconWidth, mIconHeight }; - mCanvas.drawLines(points, paint); + } + mCanvas.drawColor(color); + final Paint paint = new Paint(); + paint.setColor(Color.WHITE); + paint.setStrokeWidth(2.0f); + final float[] points = new float[]{0, 0, mIconWidth, 0, 0, 0, 0, mIconHeight, mIconWidth, 0, mIconWidth, + mIconHeight, 0, mIconHeight, mIconWidth, mIconHeight}; + mCanvas.drawLines(points, paint); - } + } - public static class ColorsAdapter extends ArrayAdapter { + public static class ColorsAdapter extends ArrayRecyclerAdapter { - private int mCurrentColor; + private final LayoutInflater mInflater; + private int mCurrentColor; - public ColorsAdapter(final Context context) { - super(context, R.layout.gallery_item_color_picker_preset); - } + public ColorsAdapter(final Context context) { + mInflater = LayoutInflater.from(context); + } - @Override - public View getView(final int position, final View convertView, final ViewGroup parent) { - final View view = super.getView(position, convertView, parent); - final ForegroundColorView colorView = (ForegroundColorView) view.findViewById(R.id.color); - final int color = getItem(position); - colorView.setColor(color); - colorView.setActivated(mCurrentColor == color); - return view; - } + public void setCurrentColor(final int color) { + mCurrentColor = color; + notifyDataSetChanged(); + } - public void setCurrentColor(final int color) { - mCurrentColor = color; - notifyDataSetChanged(); - } + @Override + public void onBindViewHolder(ColorViewHolder holder, int position, Integer item) { + holder.setColor(item, mCurrentColor == item); + } - } + @Override + public ColorViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + return new ColorViewHolder(mInflater.inflate(R.layout.gallery_item_color_picker_preset, parent, false)); + } + } + + public static class ColorViewHolder extends ViewHolder { + + private final ForegroundColorView colorView; + + public ColorViewHolder(View itemView) { + super(itemView); + colorView = (ForegroundColorView) itemView.findViewById(R.id.color); + } + + public void setColor(int color, boolean activated) { + colorView.setColor(color); + colorView.setActivated(activated); + } + } } diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/AccountsDrawerFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/AccountsDrawerFragment.java index 3d54d6c24..eeecb8bd5 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/AccountsDrawerFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/AccountsDrawerFragment.java @@ -56,10 +56,10 @@ import org.mariotaku.twidere.R; import org.mariotaku.twidere.activity.FiltersActivity; import org.mariotaku.twidere.activity.SettingsActivity; import org.mariotaku.twidere.activity.iface.IThemedActivity; +import org.mariotaku.twidere.activity.support.AccountsManagerActivity; import org.mariotaku.twidere.activity.support.ColorPickerDialogActivity; import org.mariotaku.twidere.activity.support.DraftsActivity; import org.mariotaku.twidere.activity.support.HomeActivity; -import org.mariotaku.twidere.activity.support.SignInActivity; import org.mariotaku.twidere.activity.support.UserProfileEditorActivity; import org.mariotaku.twidere.adapter.ArrayAdapter; import org.mariotaku.twidere.app.TwidereApplication; @@ -266,10 +266,8 @@ public class AccountsDrawerFragment extends BaseSupportListFragment implements L if (!(item instanceof OptionItem)) return; final OptionItem option = (OptionItem) item; switch (option.id) { - case MENU_ACCOUNTS: - case MENU_ADD_ACCOUNT: { - final Intent intent = new Intent(INTENT_ACTION_TWITTER_LOGIN); - intent.setClass(getActivity(), SignInActivity.class); + case MENU_ACCOUNTS: { + final Intent intent = new Intent(getActivity(), AccountsManagerActivity.class); startActivity(intent); break; } @@ -355,7 +353,7 @@ public class AccountsDrawerFragment extends BaseSupportListFragment implements L if (!ThemeUtils.isDarkDrawerEnabled(context)) return mThemedContext = ThemeUtils.getThemedContextForActionIcons(context); final int themeResource = ThemeUtils.getDrawerThemeResource(context); - final int accentColor = ThemeUtils.getUserThemeColor(context); + final int accentColor = ThemeUtils.getUserAccentColor(context); return mThemedContext = new TwidereContextThemeWrapper(context, themeResource, accentColor); } @@ -481,6 +479,7 @@ public class AccountsDrawerFragment extends BaseSupportListFragment implements L OnCheckedChangeListener { private final ImageLoaderWrapper mImageLoader; + private final int mActivatedColor; private Account.Indices mIndices; private long mSelectedAccountId, mDefaultAccountId; @@ -491,6 +490,7 @@ public class AccountsDrawerFragment extends BaseSupportListFragment implements L super(context, R.layout.list_item_drawer_accounts, null, new String[0], new int[0], 0); final TwidereApplication app = TwidereApplication.getInstance(context); mImageLoader = app.getImageLoaderWrapper(); + mActivatedColor = ThemeUtils.getUserAccentColor(context); } @Override @@ -498,19 +498,21 @@ public class AccountsDrawerFragment extends BaseSupportListFragment implements L super.bindView(view, context, cursor); final CompoundButton toggle = (CompoundButton) view.findViewById(R.id.toggle); final TextView name = (TextView) view.findViewById(R.id.name); - final TextView screen_name = (TextView) view.findViewById(R.id.screen_name); - final TextView default_indicator = (TextView) view.findViewById(R.id.default_indicator); - final ImageView profile_image = (ImageView) view.findViewById(R.id.profile_image); + final TextView screenNameView = (TextView) view.findViewById(R.id.screen_name); + final TextView defaultIndicatorView = (TextView) view.findViewById(R.id.default_indicator); + final ImageView profileImageView = (ImageView) view.findViewById(R.id.profile_image); final Account account = new Account(cursor, mIndices); name.setText(account.name); - screen_name.setText(String.format("@%s", account.screen_name)); - default_indicator.setVisibility(account.account_id == mDefaultAccountId ? View.VISIBLE : View.GONE); - mImageLoader.displayProfileImage(profile_image, account.profile_image_url); + screenNameView.setText(String.format("@%s", account.screen_name)); + defaultIndicatorView.setVisibility(account.account_id == mDefaultAccountId ? View.VISIBLE : View.GONE); + mImageLoader.displayProfileImage(profileImageView, account.profile_image_url); toggle.setChecked(account.is_activated); toggle.setTag(account); toggle.setOnCheckedChangeListener(this); view.setActivated(account.account_id == mSelectedAccountId); - ((IColorLabelView) view).drawEnd(account.color); + final IColorLabelView colorLabelView = (IColorLabelView) view; + colorLabelView.drawStart(account.account_id == mSelectedAccountId ? mActivatedColor : 0); + colorLabelView.drawEnd(account.color); } public long getDefaultAccountId() { @@ -620,8 +622,11 @@ public class AccountsDrawerFragment extends BaseSupportListFragment implements L private static abstract class OptionItemsAdapter extends ArrayAdapter { + private final int mMenuIconColor; + public OptionItemsAdapter(final Context context) { super(context, R.layout.list_item_menu); + mMenuIconColor = ThemeUtils.getThemeForegroundColor(context); } @Override @@ -631,7 +636,8 @@ public class AccountsDrawerFragment extends BaseSupportListFragment implements L final TextView text1 = (TextView) view.findViewById(android.R.id.text1); final ImageView icon = (ImageView) view.findViewById(android.R.id.icon); text1.setText(option.name); - icon.setImageDrawable(getContext().getResources().getDrawable(option.icon)); + icon.setImageDrawable(icon.getResources().getDrawable(option.icon)); + icon.setColorFilter(mMenuIconColor); return view; } diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/AccountsManagerFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/AccountsManagerFragment.java new file mode 100644 index 000000000..d081d8e56 --- /dev/null +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/AccountsManagerFragment.java @@ -0,0 +1,82 @@ +package org.mariotaku.twidere.fragment.support; + +import android.content.Intent; +import android.database.Cursor; +import android.net.Uri; +import android.os.Bundle; +import android.support.v4.app.LoaderManager.LoaderCallbacks; +import android.support.v4.content.CursorLoader; +import android.support.v4.content.Loader; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ListView; + +import org.mariotaku.twidere.R; +import org.mariotaku.twidere.activity.support.SignInActivity; +import org.mariotaku.twidere.adapter.AccountsAdapter; +import org.mariotaku.twidere.menu.TwidereMenuInflater; +import org.mariotaku.twidere.provider.TweetStore.Accounts; + +/** + * Created by mariotaku on 14/10/26. + */ +public class AccountsManagerFragment extends BaseSupportListFragment implements LoaderCallbacks { + + private AccountsAdapter mAdapter; + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case MENU_ADD_ACCOUNT: { + final Intent intent = new Intent(INTENT_ACTION_TWITTER_LOGIN); + intent.setClass(getActivity(), SignInActivity.class); + startActivity(intent); + break; + } + } + return super.onOptionsItemSelected(item); + } + + @Override + public void onCreateOptionsMenu(Menu menu, TwidereMenuInflater inflater) { + inflater.inflate(R.menu.menu_accounts_manager, menu); + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + setHasOptionsMenu(true); + mAdapter = new AccountsAdapter(getActivity()); + setListAdapter(mAdapter); + getLoaderManager().initLoader(0, null, this); + } + + @Override + public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) { + final View view = inflater.inflate(android.R.layout.list_content, null, false); + final ListView originalList = (ListView) view.findViewById(android.R.id.list); + final ViewGroup listContainer = (ViewGroup) originalList.getParent(); + listContainer.removeView(originalList); + inflater.inflate(R.layout.fragment_custom_tabs, listContainer, true); + return view; + } + + @Override + public Loader onCreateLoader(int id, Bundle args) { + final Uri uri = Accounts.CONTENT_URI; + return new CursorLoader(getActivity(), uri, Accounts.COLUMNS, null, null, Accounts.SORT_POSITION); + } + + @Override + public void onLoadFinished(Loader loader, Cursor cursor) { + mAdapter.changeCursor(cursor); + } + + @Override + public void onLoaderReset(Loader loader) { + mAdapter.changeCursor(null); + } +} diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/QuickMenuFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/QuickMenuFragment.java index cf4d8c836..87ad49e20 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/QuickMenuFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/QuickMenuFragment.java @@ -112,7 +112,7 @@ public class QuickMenuFragment extends BaseSupportFragment { } else { themeResource = ThemeUtils.getDrawerThemeResource(currentThemeResource); } - final int accentColor = ThemeUtils.getUserThemeColor(context); + final int accentColor = ThemeUtils.getUserAccentColor(context); return mThemedContext = new TwidereContextThemeWrapper(context, themeResource, accentColor); } diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/UserProfileFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/UserProfileFragment.java index f5cb48603..0edfe227d 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/UserProfileFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/UserProfileFragment.java @@ -888,7 +888,7 @@ public class UserProfileFragment extends BaseSupportListFragment implements OnCl final ParcelableUser user = mUser; final Relationship relationship = mRelationship; if (twitter == null || user == null) return; - final int activatedColor = ThemeUtils.getUserThemeColor(getActivity()); + final int activatedColor = ThemeUtils.getUserAccentColor(getActivity()); final boolean isMyself = user.account_id == user.id; final boolean isFollowing = relationship != null && relationship.isSourceFollowingTarget(); final boolean isProtected = user.is_protected; diff --git a/twidere/src/main/java/org/mariotaku/twidere/preference/ThemePreviewPreference.java b/twidere/src/main/java/org/mariotaku/twidere/preference/ThemePreviewPreference.java index 2d51da3ea..569c8dde1 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/preference/ThemePreviewPreference.java +++ b/twidere/src/main/java/org/mariotaku/twidere/preference/ThemePreviewPreference.java @@ -72,7 +72,7 @@ public class ThemePreviewPreference extends Preference implements Constants, OnS protected View onCreateView(final ViewGroup parent) { final Context context = getContext(); final int themeResource = ThemeUtils.getThemeResource(context); - final int accentColor = ThemeUtils.getUserThemeColor(context); + final int accentColor = ThemeUtils.getUserAccentColor(context); final Context theme = new TwidereContextThemeWrapper(context, themeResource, accentColor); final LayoutInflater inflater = LayoutInflater.from(theme); final View view = inflater.inflate(R.layout.theme_preview, parent, false); diff --git a/twidere/src/main/java/org/mariotaku/twidere/provider/TweetStore.java b/twidere/src/main/java/org/mariotaku/twidere/provider/TweetStore.java index cc192d5dd..5632f086b 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/provider/TweetStore.java +++ b/twidere/src/main/java/org/mariotaku/twidere/provider/TweetStore.java @@ -123,6 +123,8 @@ public interface TweetStore { public static final String CONSUMER_SECRET = "consumer_secret"; + public static final String SORT_POSITION = "sort_position"; + /** * User's profile image URL of the status.
* Type: TEXT @@ -140,11 +142,11 @@ public interface TweetStore { public static final String[] COLUMNS = new String[]{_ID, NAME, SCREEN_NAME, ACCOUNT_ID, AUTH_TYPE, BASIC_AUTH_USERNAME, BASIC_AUTH_PASSWORD, OAUTH_TOKEN, OAUTH_TOKEN_SECRET, CONSUMER_KEY, CONSUMER_SECRET, API_URL_FORMAT, SAME_OAUTH_SIGNING_URL, NO_VERSION_SUFFIX, PROFILE_IMAGE_URL, PROFILE_BANNER_URL, COLOR, - IS_ACTIVATED}; + IS_ACTIVATED, SORT_POSITION}; public static final String[] TYPES = new String[]{TYPE_PRIMARY_KEY, TYPE_TEXT_NOT_NULL, TYPE_TEXT_NOT_NULL, TYPE_INT_UNIQUE, TYPE_INT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, - TYPE_BOOLEAN, TYPE_BOOLEAN, TYPE_TEXT, TYPE_TEXT, TYPE_INT, TYPE_BOOLEAN}; + TYPE_BOOLEAN, TYPE_BOOLEAN, TYPE_TEXT, TYPE_TEXT, TYPE_INT, TYPE_BOOLEAN, TYPE_INT}; } diff --git a/twidere/src/main/java/org/mariotaku/twidere/util/ThemeUtils.java b/twidere/src/main/java/org/mariotaku/twidere/util/ThemeUtils.java index 961f180ef..f21581dbd 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/util/ThemeUtils.java +++ b/twidere/src/main/java/org/mariotaku/twidere/util/ThemeUtils.java @@ -27,6 +27,7 @@ import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Color; import android.graphics.PorterDuff; +import android.graphics.PorterDuff.Mode; import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.graphics.drawable.LayerDrawable; @@ -41,6 +42,7 @@ import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; +import android.widget.TextView; import org.mariotaku.menucomponent.widget.MenuBar.MenuBarMenuInfo; import org.mariotaku.refreshnow.widget.RefreshNowConfig; @@ -51,6 +53,7 @@ import org.mariotaku.twidere.activity.iface.IThemedActivity; import org.mariotaku.twidere.content.TwidereContextThemeWrapper; import org.mariotaku.twidere.content.TwidereContextWrapper; import org.mariotaku.twidere.content.iface.ITwidereContextWrapper; +import org.mariotaku.twidere.util.menu.StatusMenuInfo; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; @@ -91,7 +94,7 @@ public class ThemeUtils implements Constants { public static void applyBackground(final View view) { if (view == null) return; - applyBackground(view, getUserThemeColor(view.getContext())); + applyBackground(view, getUserAccentColor(view.getContext())); } public static void applyBackground(final View view, final int color) { @@ -118,23 +121,40 @@ public class ThemeUtils implements Constants { d.setAlpha(getUserThemeBackgroundAlpha(context)); } - public static void applyColorFilterToMenuIcon(Menu menu, int color, int popupColor, PorterDuff.Mode mode, int... excludedGroups) { + public static void applyColorFilterToMenuIcon(final Menu menu, final int color, + final int highlightColor, final Mode mode, + final int... excludedGroups) { + applyColorFilterToMenuIcon(menu, color, color, highlightColor, mode, excludedGroups); + } + + public static void applyColorFilterToMenuIcon(final Menu menu, final int color, final int popupColor, + final int highlightColor, final Mode mode, + final int... excludedGroups) { for (int i = 0, j = menu.size(); i < j; i++) { final MenuItem item = menu.getItem(i); final Drawable icon = item.getIcon(); final ContextMenuInfo info = item.getMenuInfo(); - if (icon != null) { - if (ArrayUtils.contains(excludedGroups, item.getGroupId())) { - icon.mutate().clearColorFilter(); - } else if (info instanceof MenuBarMenuInfo) { - final boolean inPopup = ((MenuBarMenuInfo) info).isInPopup(); - icon.mutate().setColorFilter(inPopup ? popupColor : color, mode); + if (icon != null && !ArrayUtils.contains(excludedGroups, item.getGroupId())) { + icon.mutate(); + if (info instanceof MenuBarMenuInfo) { + final MenuBarMenuInfo mbInfo = (MenuBarMenuInfo) info; + final boolean inPopup = mbInfo.isInPopup(); + if (mbInfo.getMenuInfo() instanceof StatusMenuInfo) { + final StatusMenuInfo sInfo = (StatusMenuInfo) mbInfo.getMenuInfo(); + icon.setColorFilter(sInfo.isHighlight() ? highlightColor + : (inPopup ? popupColor : color), mode); + } else { + icon.setColorFilter(inPopup ? popupColor : color, mode); + } + } else if (info instanceof StatusMenuInfo) { + final StatusMenuInfo sInfo = (StatusMenuInfo) info; + icon.setColorFilter(sInfo.isHighlight() ? highlightColor : color, mode); } else { - icon.mutate().setColorFilter(color, mode); + icon.setColorFilter(color, mode); } } if (item.hasSubMenu()) { - applyColorFilterToMenuIcon(item.getSubMenu(), color, popupColor, mode, excludedGroups); + applyColorFilterToMenuIcon(item.getSubMenu(), color, popupColor, highlightColor, mode, excludedGroups); } } } @@ -143,7 +163,7 @@ public class ThemeUtils implements Constants { final IndicatorConfig.Builder builder = new IndicatorConfig.Builder(context); final Resources res = context.getResources(); final float width = 3 * res.getDisplayMetrics().density; - final int themeColor = getUserThemeColor(context); + final int themeColor = getUserAccentColor(context); builder.progressColor(themeColor); builder.indeterminateColor(themeColor); builder.progressStrokeWidth(width); @@ -202,7 +222,7 @@ public class ThemeUtils implements Constants { a.recycle(); } if (resId == 0) return new TwidereContextWrapper(context); - return new TwidereContextThemeWrapper(context, resId, getUserThemeColor(context)); + return new TwidereContextThemeWrapper(context, resId, getUserAccentColor(context)); } @Deprecated @@ -250,22 +270,10 @@ public class ThemeUtils implements Constants { case R.style.Theme_Twidere_Light_Transparent: case R.style.Theme_Twidere_Light_Compose: case R.style.Theme_Twidere_Light_Dialog: - case R.style.Theme_Twidere_Colored: - case R.style.Theme_Twidere_Colored_SolidBackground: - case R.style.Theme_Twidere_Colored_Transparent: - case R.style.Theme_Twidere_Colored_Compose: case R.style.Theme_Twidere_ActionBar_Colored_Light: case R.style.Theme_Twidere_Settings_Light: case R.style.Theme_Twidere_Drawer_Light: case R.style.Theme_Twidere_Drawer_Light_Transparent: - case R.style.Theme_Twidere_Light_DarkActionBar_DarkIcon: - case R.style.Theme_Twidere_Light_DarkActionBar_SolidBackground_DarkIcon: - case R.style.Theme_Twidere_Light_DarkActionBar_Transparent_DarkIcon: - case R.style.Theme_Twidere_Light_DarkActionBar_Compose_DarkIcon: - case R.style.Theme_Twidere_Colored_DarkActionBar_DarkIcon: - case R.style.Theme_Twidere_Colored_DarkActionBar_SolidBackground_DarkIcon: - case R.style.Theme_Twidere_Colored_DarkActionBar_Transparent_DarkIcon: - case R.style.Theme_Twidere_Colored_DarkActionBar_Compose_DarkIcon: case R.style.Theme_Twidere_Settings_Light_DarkActionBar_DarkIcon: return 0x99333333; } @@ -301,14 +309,8 @@ public class ThemeUtils implements Constants { } public static int getComposeThemeResource(final String name, final boolean darkActionBar) { - if (VALUE_THEME_NAME_TWIDERE.equals(name)) - return darkActionBar ? R.style.Theme_Twidere_Colored_DarkActionBar_Compose - : R.style.Theme_Twidere_Colored_Compose; - else if (VALUE_THEME_NAME_LIGHT.equals(name)) - return darkActionBar ? R.style.Theme_Twidere_Light_DarkActionBar_Compose - : R.style.Theme_Twidere_Light_Compose; - else if (VALUE_THEME_NAME_DARK.equals(name)) return R.style.Theme_Twidere_Dark_Compose; - return R.style.Theme_Twidere_Colored_Compose; + if (VALUE_THEME_NAME_DARK.equals(name)) return R.style.Theme_Twidere_Dark_Compose; + return R.style.Theme_Twidere_Light_Compose; } public static boolean getDarkActionBarOption(final Context context) { @@ -338,9 +340,6 @@ public class ThemeUtils implements Constants { switch (themeRes) { case R.style.Theme_Twidere_Dark_Transparent: case R.style.Theme_Twidere_Light_Transparent: - case R.style.Theme_Twidere_Light_DarkActionBar_Transparent: - case R.style.Theme_Twidere_Colored_DarkActionBar_Transparent: - case R.style.Theme_Twidere_Colored_Transparent: return R.style.Theme_Twidere_Drawer_Dark_Transparent; } return R.style.Theme_Twidere_Drawer_Dark; @@ -353,9 +352,6 @@ public class ThemeUtils implements Constants { public static int getLightDrawerThemeResource(final int themeRes) { switch (themeRes) { case R.style.Theme_Twidere_Light_Transparent: - case R.style.Theme_Twidere_Light_DarkActionBar_Transparent: - case R.style.Theme_Twidere_Colored_DarkActionBar_Transparent: - case R.style.Theme_Twidere_Colored_Transparent: return R.style.Theme_Twidere_Drawer_Light_Transparent; } return R.style.Theme_Twidere_Drawer_Light; @@ -390,20 +386,8 @@ public class ThemeUtils implements Constants { case R.style.Theme_Twidere_Light_Transparent: case R.style.Theme_Twidere_Light_Compose: case R.style.Theme_Twidere_Light_Dialog: - case R.style.Theme_Twidere_Colored: - case R.style.Theme_Twidere_Colored_SolidBackground: - case R.style.Theme_Twidere_Colored_Transparent: - case R.style.Theme_Twidere_Colored_Compose: case R.style.Theme_Twidere_ActionBar_Colored_Light: case R.style.Theme_Twidere_Settings_Light: - case R.style.Theme_Twidere_Light_DarkActionBar_DarkIcon: - case R.style.Theme_Twidere_Light_DarkActionBar_SolidBackground_DarkIcon: - case R.style.Theme_Twidere_Light_DarkActionBar_Transparent_DarkIcon: - case R.style.Theme_Twidere_Light_DarkActionBar_Compose_DarkIcon: - case R.style.Theme_Twidere_Colored_DarkActionBar_DarkIcon: - case R.style.Theme_Twidere_Colored_DarkActionBar_SolidBackground_DarkIcon: - case R.style.Theme_Twidere_Colored_DarkActionBar_Transparent_DarkIcon: - case R.style.Theme_Twidere_Colored_DarkActionBar_Compose_DarkIcon: case R.style.Theme_Twidere_Settings_Light_DarkActionBar_DarkIcon: return 0x99333333; } @@ -486,9 +470,6 @@ public class ThemeUtils implements Constants { switch (themeRes) { case R.style.Theme_Twidere_Dark_Transparent: case R.style.Theme_Twidere_Light_Transparent: - case R.style.Theme_Twidere_Light_DarkActionBar_Transparent: - case R.style.Theme_Twidere_Colored_Transparent: - case R.style.Theme_Twidere_Colored_DarkActionBar_Transparent: return 0xa0; } return 0xff; @@ -526,7 +507,7 @@ public class ThemeUtils implements Constants { accentColor = ((IThemedActivity) context).getThemeColor(); } else { themeRes = getSettingsThemeResource(context); - accentColor = getUserThemeColor(context, themeRes); + accentColor = getUserAccentColor(context, themeRes); } return new TwidereContextThemeWrapper(context, getThemeResActionIcons(themeRes), accentColor); } @@ -547,7 +528,7 @@ public class ThemeUtils implements Constants { accentColor = ((IThemedActivity) context).getThemeColor(); } else { themeRes = getSettingsThemeResource(context); - accentColor = getUserThemeColor(context); + accentColor = getUserAccentColor(context); } final Context theme = getThemedContextForActionIcons(context, themeRes, accentColor); return LayoutInflater.from(theme); @@ -561,6 +542,17 @@ public class ThemeUtils implements Constants { return VALUE_THEME_FONT_FAMILY_REGULAR; } + public static int getThemeBackgroundColor(final Context context) { + final Resources res = getResources(context); + final Context wrapped = getThemedContext(context, res); + final TypedArray a = wrapped.obtainStyledAttributes(new int[]{android.R.attr.colorBackground}); + try { + return a.getColor(0, Color.GRAY); + } finally { + a.recycle(); + } + } + public static int getThemeForegroundColor(final Context context) { final Resources res = getResources(context); final Context wrapped = getThemedContext(context, res); @@ -587,30 +579,6 @@ public class ThemeUtils implements Constants { public static int getThemeResActionIcons(final int baseThemeRes) { switch (baseThemeRes) { - case R.style.Theme_Twidere_Light_DarkActionBar: { - return R.style.Theme_Twidere_Light_DarkActionBar_DarkIcon; - } - case R.style.Theme_Twidere_Light_DarkActionBar_SolidBackground: { - return R.style.Theme_Twidere_Light_DarkActionBar_SolidBackground_DarkIcon; - } - case R.style.Theme_Twidere_Light_DarkActionBar_Transparent: { - return R.style.Theme_Twidere_Light_DarkActionBar_Transparent_DarkIcon; - } - case R.style.Theme_Twidere_Light_DarkActionBar_Compose: { - return R.style.Theme_Twidere_Light_DarkActionBar_Compose_DarkIcon; - } - case R.style.Theme_Twidere_Colored_DarkActionBar: { - return R.style.Theme_Twidere_Colored_DarkActionBar_DarkIcon; - } - case R.style.Theme_Twidere_Colored_DarkActionBar_SolidBackground: { - return R.style.Theme_Twidere_Colored_DarkActionBar_SolidBackground_DarkIcon; - } - case R.style.Theme_Twidere_Colored_DarkActionBar_Transparent: { - return R.style.Theme_Twidere_Colored_DarkActionBar_Transparent_DarkIcon; - } - case R.style.Theme_Twidere_Colored_DarkActionBar_Compose: { - return R.style.Theme_Twidere_Colored_DarkActionBar_Compose_DarkIcon; - } case R.style.Theme_Twidere_Settings_Light_DarkActionBar: { return R.style.Theme_Twidere_Settings_Light_DarkActionBar_DarkIcon; } @@ -624,22 +592,12 @@ public class ThemeUtils implements Constants { } public static int getThemeResource(final String name, final String background, final boolean darkActionBar) { - if (VALUE_THEME_NAME_TWIDERE.equals(name)) { + if (VALUE_THEME_NAME_LIGHT.equals(name)) { if (VALUE_THEME_BACKGROUND_SOLID.equals(background)) - return darkActionBar ? R.style.Theme_Twidere_Colored_DarkActionBar_SolidBackground - : R.style.Theme_Twidere_Colored_SolidBackground; + return R.style.Theme_Twidere_Light_SolidBackground; else if (VALUE_THEME_BACKGROUND_TRANSPARENT.equals(background)) - return darkActionBar ? R.style.Theme_Twidere_Colored_DarkActionBar_Transparent - : R.style.Theme_Twidere_Colored_Transparent; - return darkActionBar ? R.style.Theme_Twidere_Colored_DarkActionBar : R.style.Theme_Twidere_Colored; - } else if (VALUE_THEME_NAME_LIGHT.equals(name)) { - if (VALUE_THEME_BACKGROUND_SOLID.equals(background)) - return darkActionBar ? R.style.Theme_Twidere_Light_DarkActionBar_SolidBackground - : R.style.Theme_Twidere_Light_SolidBackground; - else if (VALUE_THEME_BACKGROUND_TRANSPARENT.equals(background)) - return darkActionBar ? R.style.Theme_Twidere_Light_DarkActionBar_Transparent - : R.style.Theme_Twidere_Light_Transparent; - return darkActionBar ? R.style.Theme_Twidere_Light_DarkActionBar : R.style.Theme_Twidere_Light; + return R.style.Theme_Twidere_Light_Transparent; + return R.style.Theme_Twidere_Light; } else if (VALUE_THEME_NAME_DARK.equals(name)) { if (VALUE_THEME_BACKGROUND_SOLID.equals(background)) @@ -648,7 +606,7 @@ public class ThemeUtils implements Constants { return R.style.Theme_Twidere_Dark_Transparent; return R.style.Theme_Twidere_Dark; } - return R.style.Theme_Twidere_Colored_DarkActionBar; + return R.style.Theme_Twidere_Light; } public static int getTitleTextAppearance(final Context context) { @@ -667,7 +625,7 @@ public class ThemeUtils implements Constants { public static int getUserLinkTextColor(final Context context) { if (context == null) return new TextPaint().linkColor; - final int themeColor = getUserThemeColor(context); + final int themeColor = getUserAccentColor(context); final float[] hsv = new float[3]; Color.colorToHSV(themeColor, hsv); if (isDarkTheme(context)) { @@ -684,7 +642,7 @@ public class ThemeUtils implements Constants { return pref.getInt(KEY_THEME_BACKGROUND_ALPHA, DEFAULT_THEME_BACKGROUND_ALPHA); } - public static int getUserThemeColor(final Context context) { + public static int getUserAccentColor(final Context context) { if (context == null) return Color.TRANSPARENT; final Resources res = getResources(context); final SharedPreferencesWrapper pref = getSharedPreferencesWrapper(context); @@ -692,7 +650,7 @@ public class ThemeUtils implements Constants { return pref.getInt(KEY_THEME_COLOR, def); } - public static int getUserThemeColor(final Context context, int themeRes) { + public static int getUserAccentColor(final Context context, int themeRes) { if (context == null) return Color.TRANSPARENT; final int defThemeColor = getThemeColor(context, themeRes); final SharedPreferencesWrapper pref = getSharedPreferencesWrapper(context); @@ -747,25 +705,6 @@ public class ThemeUtils implements Constants { return getWindowContentOverlay(new ContextThemeWrapper(context, themeRes)); } - public static boolean isColoredActionBar(final Context context) { - return isColoredActionBar(getThemeResource(context)); - } - - public static boolean isColoredActionBar(final int themeRes) { - switch (themeRes) { - case R.style.Theme_Twidere_Colored: - case R.style.Theme_Twidere_Colored_SolidBackground: - case R.style.Theme_Twidere_Colored_Compose: - case R.style.Theme_Twidere_Colored_Transparent: - case R.style.Theme_Twidere_Colored_DarkActionBar: - case R.style.Theme_Twidere_Colored_DarkActionBar_SolidBackground: - case R.style.Theme_Twidere_Colored_DarkActionBar_Transparent: - case R.style.Theme_Twidere_Colored_DarkActionBar_Compose: - return true; - } - return false; - } - public static boolean isDarkDrawerEnabled(final Context context) { final SharedPreferencesWrapper prefs = SharedPreferencesWrapper.getInstance(context, SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE); @@ -799,26 +738,6 @@ public class ThemeUtils implements Constants { return b; } - public static boolean isLightActionBar(final Context context) { - return isLightActionBar(getThemeResource(context)); - } - - public static boolean isLightActionBar(final int themeRes) { - switch (themeRes) { - case R.style.Theme_Twidere_Light: - case R.style.Theme_Twidere_Light_SolidBackground: - case R.style.Theme_Twidere_Light_Transparent: - case R.style.Theme_Twidere_Light_Compose: - case R.style.Theme_Twidere_Colored: - case R.style.Theme_Twidere_Colored_SolidBackground: - case R.style.Theme_Twidere_Colored_Transparent: - case R.style.Theme_Twidere_Colored_Compose: - case R.style.Theme_Twidere_Settings_Light: - return true; - } - return false; - } - public static boolean isSolidBackground(final Context context) { return VALUE_THEME_BACKGROUND_SOLID.equals(getThemeBackgroundOption(context)); } @@ -829,13 +748,8 @@ public class ThemeUtils implements Constants { public static boolean isTransparentBackground(final int themeRes) { switch (themeRes) { - case R.style.Theme_Twidere_Colored_Transparent: - case R.style.Theme_Twidere_Colored_DarkActionBar_Transparent: - case R.style.Theme_Twidere_Colored_DarkActionBar_Transparent_DarkIcon: case R.style.Theme_Twidere_Dark_Transparent: case R.style.Theme_Twidere_Light_Transparent: - case R.style.Theme_Twidere_Light_DarkActionBar_Transparent: - case R.style.Theme_Twidere_Light_DarkActionBar_Transparent_DarkIcon: case R.style.Theme_Twidere_Viewer_Transparent: return true; } @@ -845,20 +759,20 @@ public class ThemeUtils implements Constants { public static void notifyStatusBarColorChanged(final Context context, final int themeResource, final int accentColor, final int backgroundAlpha) { final Intent intent = new Intent("com.mohammadag.colouredstatusbar.ChangeStatusBarColor"); - if (isColoredActionBar(themeResource)) { - intent.putExtra("status_bar_color", backgroundAlpha << 24 | accentColor); - } else { - if (isLightActionBar(themeResource)) { - intent.putExtra("status_bar_color", backgroundAlpha << 24 | 0xFFDDDDDD); - } else { - intent.putExtra("status_bar_color", backgroundAlpha << 24 | 0xFF222222); - } - } - if (isLightActionBar(themeResource)) { - intent.putExtra("status_bar_icons_color", Color.DKGRAY); - } else { - intent.putExtra("status_bar_icons_color", Color.WHITE); - } +// if (isColoredActionBar(themeResource)) { +// intent.putExtra("status_bar_color", backgroundAlpha << 24 | accentColor); +// } else { +// if (isLightActionBar(themeResource)) { +// intent.putExtra("status_bar_color", backgroundAlpha << 24 | 0xFFDDDDDD); +// } else { +// intent.putExtra("status_bar_color", backgroundAlpha << 24 | 0xFF222222); +// } +// } +// if (isLightActionBar(themeResource)) { +// intent.putExtra("status_bar_icons_color", Color.DKGRAY); +// } else { +// intent.putExtra("status_bar_icons_color", Color.WHITE); +// } // Please note that these are not yet implemented!!! // You're free to include them in your code so that when they // are implemented, your app will work out of the box. @@ -905,24 +819,6 @@ public class ThemeUtils implements Constants { activity.overridePendingTransition(activityCloseEnterAnimation, activityCloseExitAnimation); } - public static boolean shouldApplyColorFilter(final Context context) { - return shouldApplyColorFilter(getThemeResource(context)); - } - - public static boolean shouldApplyColorFilter(final int res) { - switch (res) { - case R.style.Theme_Twidere_Colored: - case R.style.Theme_Twidere_Colored_SolidBackground: - case R.style.Theme_Twidere_Colored_Compose: - case R.style.Theme_Twidere_Colored_Transparent: - case R.style.Theme_Twidere_Colored_DarkActionBar: - case R.style.Theme_Twidere_Colored_DarkActionBar_SolidBackground: - case R.style.Theme_Twidere_Colored_DarkActionBar_Compose: - case R.style.Theme_Twidere_Colored_DarkActionBar_Transparent: - return false; - } - return true; - } public static boolean shouldApplyColorFilterToActionIcons(final Context context) { return false; @@ -938,7 +834,7 @@ public class ThemeUtils implements Constants { if (d instanceof LayerDrawable) { final Drawable colorLayer = ((LayerDrawable) d).findDrawableByLayerId(R.id.color_layer); if (colorLayer != null) { - final int color = getUserThemeColor(context); + final int color = getUserAccentColor(context); colorLayer.setColorFilter(color, PorterDuff.Mode.MULTIPLY); } } @@ -979,4 +875,16 @@ public class ThemeUtils implements Constants { a.recycle(); } } + + public static boolean isColoredActionBar(int themeRes) { + return !isDarkTheme(themeRes); + } + + public static void initTextView(TextView view) { + if (view.isInEditMode()) return; + final Context context = view.getContext(); + view.setLinkTextColor(ThemeUtils.getUserLinkTextColor(context)); + view.setHighlightColor(ThemeUtils.getUserHighlightColor(context)); + view.setTypeface(ThemeUtils.getUserTypeface(context, view.getTypeface())); + } } diff --git a/twidere/src/main/java/org/mariotaku/twidere/util/Utils.java b/twidere/src/main/java/org/mariotaku/twidere/util/Utils.java index 18f4ac61f..8afe28d8c 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/util/Utils.java +++ b/twidere/src/main/java/org/mariotaku/twidere/util/Utils.java @@ -42,7 +42,6 @@ import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.PorterDuff; -import android.graphics.PorterDuff.Mode; import android.graphics.Rect; import android.graphics.Typeface; import android.graphics.drawable.BitmapDrawable; @@ -98,6 +97,7 @@ import org.apache.http.NameValuePair; import org.json.JSONException; import org.mariotaku.gallery3d.ImageViewerGLActivity; import org.mariotaku.jsonserializer.JSONSerializer; +import org.mariotaku.menucomponent.internal.menu.MenuUtils; import org.mariotaku.querybuilder.AllColumns; import org.mariotaku.querybuilder.Columns; import org.mariotaku.querybuilder.Columns.Column; @@ -173,6 +173,7 @@ import org.mariotaku.twidere.provider.TweetStore.Tabs; import org.mariotaku.twidere.provider.TweetStore.UnreadCounts; import org.mariotaku.twidere.service.RefreshService; import org.mariotaku.twidere.util.content.ContentResolverUtils; +import org.mariotaku.twidere.util.menu.StatusMenuInfo; import org.mariotaku.twidere.util.net.TwidereHostResolverFactory; import org.mariotaku.twidere.util.net.TwidereHttpClientFactory; @@ -3428,7 +3429,7 @@ public final class Utils implements Constants, TwitterConstants { public static void setMenuForStatus(final Context context, final Menu menu, final ParcelableStatus status) { if (context == null || menu == null || status == null) return; - final int activatedColor = ThemeUtils.getUserThemeColor(context); + final int activatedColor = ThemeUtils.getUserAccentColor(context); final boolean isMyRetweet = isMyRetweet(status); final MenuItem delete = menu.findItem(MENU_DELETE); if (delete != null) { @@ -3436,35 +3437,18 @@ public final class Utils implements Constants, TwitterConstants { } final MenuItem retweet = menu.findItem(MENU_RETWEET); if (retweet != null) { - final Drawable icon = retweet.getIcon().mutate(); retweet.setVisible(!status.user_is_protected || isMyRetweet); - if (isMyRetweet) { - icon.setColorFilter(activatedColor, Mode.SRC_ATOP); - retweet.setTitle(R.string.cancel_retweet); - } else { - icon.clearColorFilter(); - retweet.setTitle(R.string.retweet); - } + MenuUtils.setMenuInfo(retweet, new StatusMenuInfo(isMyRetweet)); + retweet.setTitle(isMyRetweet ? R.string.cancel_retweet : R.string.retweet); } - final MenuItem itemRetweetSubmenu = menu.findItem(R.id.retweet_submenu); - if (itemRetweetSubmenu != null) { - final Drawable icon = itemRetweetSubmenu.getIcon().mutate(); - if (isMyRetweet) { - icon.setColorFilter(activatedColor, Mode.SRC_ATOP); - } else { - icon.clearColorFilter(); - } + final MenuItem retweetSubItem = menu.findItem(R.id.retweet_submenu); + if (retweetSubItem != null) { + MenuUtils.setMenuInfo(retweetSubItem, new StatusMenuInfo(isMyRetweet)); } final MenuItem favorite = menu.findItem(MENU_FAVORITE); if (favorite != null) { - final Drawable icon = favorite.getIcon().mutate(); - if (status.is_favorite) { - icon.setColorFilter(activatedColor, Mode.SRC_ATOP); - favorite.setTitle(R.string.unfavorite); - } else { - icon.clearColorFilter(); - favorite.setTitle(R.string.favorite); - } + MenuUtils.setMenuInfo(favorite, new StatusMenuInfo(status.is_favorite)); + favorite.setTitle(status.is_favorite ? R.string.unfavorite : R.string.favorite); } final MenuItem translate = menu.findItem(MENU_TRANSLATE); if (translate != null) { diff --git a/twidere/src/main/java/org/mariotaku/twidere/util/menu/StatusMenuInfo.java b/twidere/src/main/java/org/mariotaku/twidere/util/menu/StatusMenuInfo.java new file mode 100644 index 000000000..4d7f2164c --- /dev/null +++ b/twidere/src/main/java/org/mariotaku/twidere/util/menu/StatusMenuInfo.java @@ -0,0 +1,18 @@ +package org.mariotaku.twidere.util.menu; + +import android.view.ContextMenu.ContextMenuInfo; + +/** + * Created by mariotaku on 14/10/27. + */ +public class StatusMenuInfo implements ContextMenuInfo { + private final boolean highlight; + + public StatusMenuInfo(boolean highlight) { + this.highlight = highlight; + } + + public boolean isHighlight() { + return highlight; + } +} diff --git a/twidere/src/main/java/org/mariotaku/twidere/view/HomeActionButton.java b/twidere/src/main/java/org/mariotaku/twidere/view/HomeActionButton.java index f62982df0..1a5e16112 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/view/HomeActionButton.java +++ b/twidere/src/main/java/org/mariotaku/twidere/view/HomeActionButton.java @@ -23,8 +23,10 @@ import android.annotation.TargetApi; import android.content.Context; import android.content.res.ColorStateList; import android.graphics.Bitmap; +import android.graphics.Color; import android.graphics.Outline; import android.graphics.PorterDuff.Mode; +import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.os.Build; import android.util.AttributeSet; @@ -35,7 +37,8 @@ import android.widget.ImageView; import android.widget.ProgressBar; import org.mariotaku.twidere.R; -import org.mariotaku.twidere.util.Utils; +import org.mariotaku.twidere.util.ThemeUtils; +import org.mariotaku.twidere.util.accessor.ViewAccessor; import org.mariotaku.twidere.view.iface.IHomeActionButton; @TargetApi(Build.VERSION_CODES.LOLLIPOP) @@ -54,22 +57,23 @@ public class HomeActionButton extends FrameLayout implements IHomeActionButton { public HomeActionButton(final Context context, final AttributeSet attrs, final int defStyle) { super(context, attrs, defStyle); - inflate(context, R.layout.action_item_home_actions, this); + inflate(ThemeUtils.getActionBarContext(context), R.layout.action_item_home_actions, this); mIconView = (ImageView) findViewById(android.R.id.icon); mProgressBar = (ProgressBar) findViewById(android.R.id.progress); setOutlineProvider(new HomeActionButtonOutlineProvider()); setClipToOutline(true); + setButtonColor(Color.WHITE); } @Override - public void setColor(int color) { - final Drawable drawable = getBackground(); - if (drawable != null) { - drawable.setColorFilter(color, Mode.MULTIPLY); - } - final int contrastColor = Utils.getContrastYIQ(color, 192); - mIconView.setColorFilter(contrastColor, Mode.SRC_ATOP); - mProgressBar.setIndeterminateTintList(ColorStateList.valueOf(contrastColor)); + public void setButtonColor(int color) { + ViewAccessor.setBackground(this, new ColorDrawable(color)); + } + + @Override + public void setIconColor(int color, Mode mode) { + mIconView.setColorFilter(color, mode); + mProgressBar.setIndeterminateTintList(ColorStateList.valueOf(color)); } @Override diff --git a/twidere/src/main/java/org/mariotaku/twidere/view/HomeActionButtonCompat.java b/twidere/src/main/java/org/mariotaku/twidere/view/HomeActionButtonCompat.java index 579c22e39..2ed5e205e 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/view/HomeActionButtonCompat.java +++ b/twidere/src/main/java/org/mariotaku/twidere/view/HomeActionButtonCompat.java @@ -31,7 +31,7 @@ import android.widget.ImageView; import android.widget.ProgressBar; import org.mariotaku.twidere.R; -import org.mariotaku.twidere.util.Utils; +import org.mariotaku.twidere.util.ThemeUtils; import org.mariotaku.twidere.view.iface.IHomeActionButton; public class HomeActionButtonCompat extends FrameLayout implements IHomeActionButton { @@ -49,13 +49,13 @@ public class HomeActionButtonCompat extends FrameLayout implements IHomeActionBu public HomeActionButtonCompat(final Context context, final AttributeSet attrs, final int defStyle) { super(context, attrs, defStyle); - inflate(context, R.layout.action_item_home_actions, this); + inflate(ThemeUtils.getActionBarContext(context), R.layout.action_item_home_actions_compat, this); mIconView = (ImageView) findViewById(android.R.id.icon); mProgressBar = (ProgressBar) findViewById(android.R.id.progress); } @Override - public void setColor(int color) { + public void setButtonColor(int color) { final Drawable drawable = getBackground(); if (drawable instanceof LayerDrawable) { final Drawable layer = ((LayerDrawable) drawable).findDrawableByLayerId(R.id.color_layer); @@ -63,7 +63,11 @@ public class HomeActionButtonCompat extends FrameLayout implements IHomeActionBu layer.setColorFilter(color, Mode.SRC_ATOP); } } - mIconView.setColorFilter(Utils.getContrastYIQ(color), Mode.SRC_ATOP); + } + + @Override + public void setIconColor(int color, Mode mode) { + mIconView.setColorFilter(color, mode); } public void setIcon(final Bitmap bm) { diff --git a/twidere/src/main/java/org/mariotaku/twidere/view/ListMenuOverflowButton.java b/twidere/src/main/java/org/mariotaku/twidere/view/ListMenuOverflowButton.java index 74e9d3f20..a17c03165 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/view/ListMenuOverflowButton.java +++ b/twidere/src/main/java/org/mariotaku/twidere/view/ListMenuOverflowButton.java @@ -46,7 +46,7 @@ public class ListMenuOverflowButton extends ImageView { public ListMenuOverflowButton(final Context context, final AttributeSet attrs, final int defStyle) { super(context, attrs, defStyle); setScaleType(ScaleType.CENTER_INSIDE); - mHighlightColor = isInEditMode() ? 0 : ThemeUtils.getUserThemeColor(context); + mHighlightColor = isInEditMode() ? 0 : ThemeUtils.getUserAccentColor(context); mRect = new Rect(); final TypedArray a = context.obtainStyledAttributes(attrs, new int[] { android.R.attr.src }); if (!a.hasValue(0)) { diff --git a/twidere/src/main/java/org/mariotaku/twidere/view/NavigationArrowButton.java b/twidere/src/main/java/org/mariotaku/twidere/view/NavigationArrowButton.java index c054d1ac1..735be59c3 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/view/NavigationArrowButton.java +++ b/twidere/src/main/java/org/mariotaku/twidere/view/NavigationArrowButton.java @@ -41,7 +41,7 @@ public class NavigationArrowButton extends ImageButton { public NavigationArrowButton(final Context context, final AttributeSet attrs, final int defStyle) { super(context, attrs, defStyle); - mHighlightColor = isInEditMode() ? 0 : ThemeUtils.getUserThemeColor(context); + mHighlightColor = isInEditMode() ? 0 : ThemeUtils.getUserAccentColor(context); } @Override diff --git a/twidere/src/main/java/org/mariotaku/twidere/view/TabPagerIndicator.java b/twidere/src/main/java/org/mariotaku/twidere/view/TabPagerIndicator.java index 5f069dfea..963c22554 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/view/TabPagerIndicator.java +++ b/twidere/src/main/java/org/mariotaku/twidere/view/TabPagerIndicator.java @@ -129,17 +129,25 @@ public class TabPagerIndicator extends RecyclerView implements PagerIndicator { mIndicatorAdapter.setIconColor(color); } + public Context getItemContext() { + return mIndicatorAdapter.getItemContext(); + } + + public void setItemContext(Context context) { + mIndicatorAdapter.setItemContext(context); + } + private static class TabPagerIndicatorAdapter extends Adapter implements OnClickListener, OnLongClickListener { private final TabPagerIndicator mIndicator; - private final LayoutInflater mInflater; + private Context mItemContext; + private LayoutInflater mInflater; private TabProvider mTabProvider; private int mStripColor, mIconColor; public TabPagerIndicatorAdapter(TabPagerIndicator indicator) { mIndicator = indicator; - mInflater = LayoutInflater.from(indicator.getContext()); } @Override @@ -197,6 +205,15 @@ public class TabPagerIndicator extends RecyclerView implements PagerIndicator { mIconColor = color; notifyDataSetChanged(); } + + public void setItemContext(Context itemContext) { + mItemContext = itemContext; + mInflater = LayoutInflater.from(itemContext); + } + + public Context getItemContext() { + return mItemContext; + } } private void dispatchTabClick(int position) { diff --git a/twidere/src/main/java/org/mariotaku/twidere/view/TwidereMenuBar.java b/twidere/src/main/java/org/mariotaku/twidere/view/TwidereMenuBar.java index 47748c9cc..d203f8b07 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/view/TwidereMenuBar.java +++ b/twidere/src/main/java/org/mariotaku/twidere/view/TwidereMenuBar.java @@ -33,9 +33,10 @@ public class TwidereMenuBar extends MenuBar implements MenuBarListener, Constant @Override public void onPreShowMenu(Menu menu) { - final int color = ThemeUtils.getTextColorPrimary(getItemViewContext()); - final int popupColor = ThemeUtils.getTextColorPrimary(getPopupContext()); - ThemeUtils.applyColorFilterToMenuIcon(menu, color, popupColor, Mode.SRC_ATOP, + final int color = ThemeUtils.getThemeForegroundColor(getItemViewContext()); + final int popupColor = ThemeUtils.getThemeForegroundColor(getPopupContext()); + final int highlightColor = ThemeUtils.getUserAccentColor(getContext()); + ThemeUtils.applyColorFilterToMenuIcon(menu, color, popupColor, highlightColor, Mode.SRC_ATOP, MENU_GROUP_STATUS_SHARE, MENU_GROUP_STATUS_EXTENSION); } diff --git a/twidere/src/main/java/org/mariotaku/twidere/view/iface/ICardItemView.java b/twidere/src/main/java/org/mariotaku/twidere/view/iface/ICardItemView.java index d8a73c1f5..cac120f53 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/view/iface/ICardItemView.java +++ b/twidere/src/main/java/org/mariotaku/twidere/view/iface/ICardItemView.java @@ -98,7 +98,7 @@ public interface ICardItemView extends IColorLabelView { mGapTextPaint.setColor(a.getColor(R.styleable.CardItemView_cardGapTextColor, Color.GRAY)); mGapTextPaint.setTextSize(a.getDimensionPixelSize(R.styleable.CardItemView_cardGapTextSize, 18)); mGapTextPaint.setTypeface(Typeface.DEFAULT_BOLD); - mThemeColor = ThemeUtils.getUserThemeColor(context); + mThemeColor = ThemeUtils.getUserAccentColor(context); mOverflowIconGestureDetector = new GestureDetector(context, new OverflowIconGestureListener(this)); mFakeOverflowButton = new FakeOverflowButton(this); mBackgroundAlpha = a.getFraction(R.styleable.CardItemView_cardBackgroundAlpha, 1, 1, 1.0f); diff --git a/twidere/src/main/java/org/mariotaku/twidere/view/iface/IHomeActionButton.java b/twidere/src/main/java/org/mariotaku/twidere/view/iface/IHomeActionButton.java index 890a98020..235f51d83 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/view/iface/IHomeActionButton.java +++ b/twidere/src/main/java/org/mariotaku/twidere/view/iface/IHomeActionButton.java @@ -1,13 +1,16 @@ package org.mariotaku.twidere.view.iface; import android.graphics.Bitmap; +import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; /** * Created by mariotaku on 14/10/23. */ public interface IHomeActionButton { - void setColor(int color); + void setButtonColor(int color); + + void setIconColor(int color, PorterDuff.Mode mode); void setIcon(Bitmap bm); diff --git a/twidere/src/main/java/org/mariotaku/twidere/view/themed/ThemedAutoCompleteTextView.java b/twidere/src/main/java/org/mariotaku/twidere/view/themed/ThemedAutoCompleteTextView.java index 52299b595..724ce01e4 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/view/themed/ThemedAutoCompleteTextView.java +++ b/twidere/src/main/java/org/mariotaku/twidere/view/themed/ThemedAutoCompleteTextView.java @@ -37,10 +37,7 @@ public class ThemedAutoCompleteTextView extends AutoCompleteTextView { public ThemedAutoCompleteTextView(final Context context, final AttributeSet attrs, final int defStyle) { super(context, attrs, defStyle); - if (!isInEditMode()) { - setLinkTextColor(ThemeUtils.getUserLinkTextColor(context)); - setHighlightColor(ThemeUtils.getUserHighlightColor(context)); - } + ThemeUtils.initTextView(this); } } diff --git a/twidere/src/main/java/org/mariotaku/twidere/view/themed/ThemedCheckBox.java b/twidere/src/main/java/org/mariotaku/twidere/view/themed/ThemedCheckBox.java index 2d0f09139..ec72e8fb8 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/view/themed/ThemedCheckBox.java +++ b/twidere/src/main/java/org/mariotaku/twidere/view/themed/ThemedCheckBox.java @@ -37,11 +37,7 @@ public class ThemedCheckBox extends CheckBox { public ThemedCheckBox(final Context context, final AttributeSet attrs, final int defStyle) { super(context, attrs, defStyle); - if (!isInEditMode()) { - setLinkTextColor(ThemeUtils.getUserLinkTextColor(context)); - setHighlightColor(ThemeUtils.getUserHighlightColor(context)); - setTypeface(ThemeUtils.getUserTypeface(context, getTypeface())); - } + ThemeUtils.initTextView(this); } } diff --git a/twidere/src/main/java/org/mariotaku/twidere/view/themed/ThemedEditText.java b/twidere/src/main/java/org/mariotaku/twidere/view/themed/ThemedEditText.java index e9876e228..3b2e417fc 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/view/themed/ThemedEditText.java +++ b/twidere/src/main/java/org/mariotaku/twidere/view/themed/ThemedEditText.java @@ -37,10 +37,7 @@ public class ThemedEditText extends EditText { public ThemedEditText(final Context context, final AttributeSet attrs, final int defStyle) { super(context, attrs, defStyle); - if (!isInEditMode()) { - setLinkTextColor(ThemeUtils.getUserLinkTextColor(context)); - setHighlightColor(ThemeUtils.getUserHighlightColor(context)); - } + ThemeUtils.initTextView(this); } } diff --git a/twidere/src/main/java/org/mariotaku/twidere/view/themed/ThemedMultiAutoCompleteTextView.java b/twidere/src/main/java/org/mariotaku/twidere/view/themed/ThemedMultiAutoCompleteTextView.java index 8d3e93ba8..e9e8ed942 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/view/themed/ThemedMultiAutoCompleteTextView.java +++ b/twidere/src/main/java/org/mariotaku/twidere/view/themed/ThemedMultiAutoCompleteTextView.java @@ -37,10 +37,7 @@ public class ThemedMultiAutoCompleteTextView extends MultiAutoCompleteTextView { public ThemedMultiAutoCompleteTextView(final Context context, final AttributeSet attrs, final int defStyle) { super(context, attrs, defStyle); - if (!isInEditMode()) { - setLinkTextColor(ThemeUtils.getUserLinkTextColor(context)); - setHighlightColor(ThemeUtils.getUserHighlightColor(context)); - } + ThemeUtils.initTextView(this); } } diff --git a/twidere/src/main/java/org/mariotaku/twidere/view/themed/ThemedRadioButton.java b/twidere/src/main/java/org/mariotaku/twidere/view/themed/ThemedRadioButton.java index 968aa51ed..b5c806ac3 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/view/themed/ThemedRadioButton.java +++ b/twidere/src/main/java/org/mariotaku/twidere/view/themed/ThemedRadioButton.java @@ -27,21 +27,17 @@ import org.mariotaku.twidere.util.ThemeUtils; public class ThemedRadioButton extends RadioButton { - public ThemedRadioButton(final Context context) { - this(context, null); - } + public ThemedRadioButton(final Context context) { + this(context, null); + } - public ThemedRadioButton(final Context context, final AttributeSet attrs) { - this(context, attrs, android.R.attr.checkboxStyle); - } + public ThemedRadioButton(final Context context, final AttributeSet attrs) { + this(context, attrs, android.R.attr.checkboxStyle); + } - public ThemedRadioButton(final Context context, final AttributeSet attrs, final int defStyle) { - super(context, attrs, defStyle); - if (!isInEditMode()) { - setLinkTextColor(ThemeUtils.getUserLinkTextColor(context)); - setHighlightColor(ThemeUtils.getUserHighlightColor(context)); - setTypeface(ThemeUtils.getUserTypeface(context, getTypeface())); - } - } + public ThemedRadioButton(final Context context, final AttributeSet attrs, final int defStyle) { + super(context, attrs, defStyle); + ThemeUtils.initTextView(this); + } } diff --git a/twidere/src/main/java/org/mariotaku/twidere/view/themed/ThemedSwitch.java b/twidere/src/main/java/org/mariotaku/twidere/view/themed/ThemedSwitch.java index 0368782c6..e596ac67a 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/view/themed/ThemedSwitch.java +++ b/twidere/src/main/java/org/mariotaku/twidere/view/themed/ThemedSwitch.java @@ -33,11 +33,7 @@ public class ThemedSwitch extends Switch { public ThemedSwitch(final Context context, final AttributeSet attrs) { super(context, attrs); - if (!isInEditMode()) { - setLinkTextColor(ThemeUtils.getUserLinkTextColor(context)); - setHighlightColor(ThemeUtils.getUserHighlightColor(context)); - setTypeface(ThemeUtils.getUserTypeface(context, getTypeface())); - } + ThemeUtils.initTextView(this); } } diff --git a/twidere/src/main/java/org/mariotaku/twidere/view/themed/ThemedTextView.java b/twidere/src/main/java/org/mariotaku/twidere/view/themed/ThemedTextView.java index 090159d6b..a96ee9658 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/view/themed/ThemedTextView.java +++ b/twidere/src/main/java/org/mariotaku/twidere/view/themed/ThemedTextView.java @@ -37,11 +37,7 @@ public class ThemedTextView extends TextView { public ThemedTextView(final Context context, final AttributeSet attrs, final int defStyle) { super(context, attrs, defStyle); - if (!isInEditMode()) { - setLinkTextColor(ThemeUtils.getUserLinkTextColor(context)); - setHighlightColor(ThemeUtils.getUserHighlightColor(context)); - setTypeface(ThemeUtils.getUserTypeface(context, getTypeface())); - } + ThemeUtils.initTextView(this); } } diff --git a/twidere/src/main/res/drawable-v21/btn_home_actions.xml b/twidere/src/main/res/drawable-v21/btn_home_actions.xml deleted file mode 100644 index 882aeeb0d..000000000 --- a/twidere/src/main/res/drawable-v21/btn_home_actions.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/twidere/src/main/res/layout-v21/layout_home_actions_button.xml b/twidere/src/main/res/layout-v21/layout_home_actions_button.xml index cb32fef3a..73f456854 100644 --- a/twidere/src/main/res/layout-v21/layout_home_actions_button.xml +++ b/twidere/src/main/res/layout-v21/layout_home_actions_button.xml @@ -6,6 +6,5 @@ android:layout_height="@dimen/float_action_button_size" android:layout_gravity="bottom|right" android:layout_margin="@dimen/element_spacing_large" - android:background="@drawable/btn_home_actions" android:elevation="@dimen/element_spacing_small" android:visibility="visible"/> \ No newline at end of file diff --git a/twidere/src/main/res/layout/action_item_compose.xml b/twidere/src/main/res/layout/action_item_compose.xml index 162b2dd2b..ff870dc61 100644 --- a/twidere/src/main/res/layout/action_item_compose.xml +++ b/twidere/src/main/res/layout/action_item_compose.xml @@ -1,10 +1,11 @@ - + android:textAppearance="?android:textAppearanceSmall"/> + android:src="@drawable/ic_action_send"/> \ No newline at end of file diff --git a/twidere/src/main/res/layout/action_item_home_actions.xml b/twidere/src/main/res/layout/action_item_home_actions.xml index 29bc300c3..840027fc6 100644 --- a/twidere/src/main/res/layout/action_item_home_actions.xml +++ b/twidere/src/main/res/layout/action_item_home_actions.xml @@ -1,22 +1,28 @@ - + - + android:layout_margin="@dimen/element_spacing_normal" + android:visibility="gone"/> + + \ No newline at end of file diff --git a/twidere/src/main/res/layout/action_item_home_actions_compat.xml b/twidere/src/main/res/layout/action_item_home_actions_compat.xml new file mode 100644 index 000000000..29bc300c3 --- /dev/null +++ b/twidere/src/main/res/layout/action_item_home_actions_compat.xml @@ -0,0 +1,22 @@ + + + + + + + + \ No newline at end of file diff --git a/twidere/src/main/res/layout/activity_compose_actionbar.xml b/twidere/src/main/res/layout/activity_compose_actionbar.xml index b52f0ee98..ab13949e9 100644 --- a/twidere/src/main/res/layout/activity_compose_actionbar.xml +++ b/twidere/src/main/res/layout/activity_compose_actionbar.xml @@ -1,6 +1,6 @@ - + android:layout_height="match_parent"/> + android:singleLine="true"/> + android:visibility="gone"/> @@ -62,16 +62,8 @@ android:layout_weight="0" android:indeterminateOnly="true" android:padding="2dp" - android:visibility="gone" /> + android:visibility="gone"/> - - - + \ No newline at end of file diff --git a/twidere/src/main/res/layout/activity_compose_bottombar.xml b/twidere/src/main/res/layout/activity_compose_bottombar.xml index d4966b6fe..ac3021ec0 100644 --- a/twidere/src/main/res/layout/activity_compose_bottombar.xml +++ b/twidere/src/main/res/layout/activity_compose_bottombar.xml @@ -1,41 +1,28 @@ - - - - - + + android:max="@integer/max_action_buttons_bottom"/> diff --git a/twidere/src/main/res/layout/activity_home_content.xml b/twidere/src/main/res/layout/activity_home_content.xml index 039920a39..3b65da8d0 100644 --- a/twidere/src/main/res/layout/activity_home_content.xml +++ b/twidere/src/main/res/layout/activity_home_content.xml @@ -11,8 +11,6 @@ - - + + \ No newline at end of file diff --git a/twidere/src/main/res/layout/dialog_color_picker.xml b/twidere/src/main/res/layout/dialog_color_picker.xml index d1fa2ff4f..6c11f124b 100644 --- a/twidere/src/main/res/layout/dialog_color_picker.xml +++ b/twidere/src/main/res/layout/dialog_color_picker.xml @@ -12,7 +12,7 @@ android:layout_height="wrap_content" android:layout_weight="1"/> - + diff --git a/twidere/src/main/res/layout/gallery_item_compose_account.xml b/twidere/src/main/res/layout/gallery_item_compose_account.xml index ac83cbf3b..0c8067a8e 100644 --- a/twidere/src/main/res/layout/gallery_item_compose_account.xml +++ b/twidere/src/main/res/layout/gallery_item_compose_account.xml @@ -1,26 +1,18 @@ - + - - + \ No newline at end of file diff --git a/twidere/src/main/res/layout/list_item_account.xml b/twidere/src/main/res/layout/list_item_account.xml index 9d43df336..e2aa997b4 100644 --- a/twidere/src/main/res/layout/list_item_account.xml +++ b/twidere/src/main/res/layout/list_item_account.xml @@ -15,68 +15,81 @@ limitations under the License. --> - + - - + + android:background="@drawable/list_drag_handle"/> - - + - + - + + + + + + + + \ No newline at end of file diff --git a/twidere/src/main/res/layout/list_item_custom_tab.xml b/twidere/src/main/res/layout/list_item_custom_tab.xml index 4fdcba8d8..59e4ee701 100644 --- a/twidere/src/main/res/layout/list_item_custom_tab.xml +++ b/twidere/src/main/res/layout/list_item_custom_tab.xml @@ -1,52 +1,54 @@ - + - + - + - + - + - - + + \ No newline at end of file diff --git a/twidere/src/main/res/layout/list_item_drawer_accounts.xml b/twidere/src/main/res/layout/list_item_drawer_accounts.xml index 0d1890d1e..d25e49313 100644 --- a/twidere/src/main/res/layout/list_item_drawer_accounts.xml +++ b/twidere/src/main/res/layout/list_item_drawer_accounts.xml @@ -1,106 +1,106 @@ - + - + - + - + - + - + - - + + - - - + + + - + - + - + - - + + \ No newline at end of file diff --git a/twidere/src/main/res/menu/menu_accounts_manager.xml b/twidere/src/main/res/menu/menu_accounts_manager.xml new file mode 100644 index 000000000..5abcf63c8 --- /dev/null +++ b/twidere/src/main/res/menu/menu_accounts_manager.xml @@ -0,0 +1,9 @@ + + +

+ + \ No newline at end of file diff --git a/twidere/src/main/res/values/themes.xml b/twidere/src/main/res/values/themes.xml index 4223eec5d..dd1d6b54d 100644 --- a/twidere/src/main/res/values/themes.xml +++ b/twidere/src/main/res/values/themes.xml @@ -19,11 +19,11 @@ - - - - - - - - - - - @@ -201,35 +116,10 @@ @null - @color/bg_color_transparent_light + true - - - - - - - - @@ -341,49 +223,6 @@ @android:dimen/dialog_min_width_minor - - - - - - @@ -481,10 +320,11 @@ @style/Animation.Twidere.Activity - @color/bg_color_dark + - @android:style/Widget.Holo.ActionBar.Solid + @android:style/Widget.DeviceDefault.ActionBar.Solid + @style/Widget.TabPageIndicator.TabItem @@ -518,7 +358,7 @@ @style/Animation.Twidere.Activity - @color/bg_color_light + @style/Widget.TabPageIndicator.TabItem @@ -548,11 +388,11 @@