From 1ed722d283832190c53ba7341118fe746530b101 Mon Sep 17 00:00:00 2001 From: Mariotaku Lee Date: Sun, 18 Nov 2012 14:27:27 +0800 Subject: [PATCH] sliding pane feature finished. removed some unused resources. --- AndroidManifest.xml | 8 +- res/drawable-hdpi/right_pane_shadow.9.png | Bin 188 -> 0 bytes res/drawable-hdpi/shadow_holo.9.png | Bin 0 -> 368 bytes res/drawable-mdpi/right_pane_shadow.9.png | Bin 178 -> 0 bytes res/drawable-mdpi/shadow_holo.9.png | Bin 0 -> 293 bytes res/drawable-xhdpi/right_pane_shadow.9.png | Bin 196 -> 0 bytes res/drawable-xhdpi/shadow_holo.9.png | Bin 0 -> 538 bytes res/layout-land/base_dual_pane.xml | 25 +- res/layout-land/home_dual_pane.xml | 26 +- res/layout-land/search_dual_pane.xml | 31 + res/layout/base_dual_pane.xml | 42 +- res/layout/base_pane_left_content.xml | 16 + res/layout/base_pane_right_content.xml | 5 + res/layout/filters.xml | 26 +- res/layout/home_dual_pane.xml | 42 +- res/layout/home_pane_left_content.xml | 16 + res/layout/search_dual_pane.xml | 52 +- res/layout/search_pane_left_content.xml | 23 + res/values-land/dimens.xml | 1 + res/values-land/integers.xml | 8 +- res/values-large-land/dimens.xml | 2 +- res/values-large/dimens.xml | 2 +- res/values/attrs.xml | 43 +- res/values/bools.xml | 10 +- res/values/dimens.xml | 7 +- res/values/integers.xml | 10 +- res/values/strings_donttranslate.xml | 2 +- src/edu/ucdavis/earlybird/UCDService.java | 7 +- src/org/mariotaku/twidere/Constants.java | 1 - .../twidere/activity/ComposeActivity.java | 2 +- .../twidere/activity/DualPaneActivity.java | 82 +- .../twidere/activity/FiltersActivity.java | 19 +- .../twidere/activity/LinkHandlerActivity.java | 1 + .../twidere/activity/SettingsActivity.java | 2 +- .../twidere/fragment/StatusFragment.java | 3 +- .../util/ExtendedViewGroupInterface.java | 2 +- .../twidere/util/ExtendedViewInterface.java | 1 - .../twidere/view/ExtendedFrameLayout.java | 5 +- .../twidere/view/ExtendedLinearLayout.java | 4 +- .../twidere/view/SlidingPaneView.java | 824 ++++++++++++++++++ .../mariotaku/twidere/view/SlidingPanel.java | 163 ---- .../twidere/view/TabPageIndicator.java | 13 +- 42 files changed, 1098 insertions(+), 428 deletions(-) delete mode 100644 res/drawable-hdpi/right_pane_shadow.9.png create mode 100644 res/drawable-hdpi/shadow_holo.9.png delete mode 100644 res/drawable-mdpi/right_pane_shadow.9.png create mode 100644 res/drawable-mdpi/shadow_holo.9.png delete mode 100644 res/drawable-xhdpi/right_pane_shadow.9.png create mode 100644 res/drawable-xhdpi/shadow_holo.9.png create mode 100644 res/layout-land/search_dual_pane.xml create mode 100644 res/layout/base_pane_left_content.xml create mode 100644 res/layout/base_pane_right_content.xml create mode 100644 res/layout/home_pane_left_content.xml create mode 100644 res/layout/search_pane_left_content.xml create mode 100644 src/org/mariotaku/twidere/view/SlidingPaneView.java delete mode 100644 src/org/mariotaku/twidere/view/SlidingPanel.java diff --git a/AndroidManifest.xml b/AndroidManifest.xml index f4b0a421..6ab3c512 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -2,7 +2,7 @@ + android:theme="@style/Theme.Twidere.Light.Dialog" + android:windowSoftInputMode="adjustResize"> @@ -460,4 +460,4 @@ - + \ No newline at end of file diff --git a/res/drawable-hdpi/right_pane_shadow.9.png b/res/drawable-hdpi/right_pane_shadow.9.png deleted file mode 100644 index ca703f565a380343262fec2f7bee34b9c7bda9e7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 188 zcmeAS@N?(olHy`uVBq!ia0vp^{6Ngi!3HFKL_!UL6k~CayA#8@b22Z19JVBHcNd2L zAh=-f^2tCE&H|6fVg?4T*C5Q;)Xf_O6l5>)^mS#w!@)2>eZk44ofy`glX(f`uqAoByDx`7I;J!Gca%qgD@k*tT_@uLG}_)Usv`!+(Impl6SfazXF9MOI#yLobz*Y zQ}ap~oQqNuOHxx5$}>wc6x=<11Hv2m#DR)Vd%8G=L>zt_;mCJbfu~sF@Bhi04_kb> zuxg@Dn!l9Lst_)&ZG}$E^QV2tG7JxJ)H7i?b2Xl!@9P}#zwiE5+PELjEAJ_1nZ|$V z#G#rJ#bb-EwMl&Tm7W@HW@aT`F8qJ;u}!b+@7qmXdSLeo9;JekAkXvRH(Gm6t=P4D zaeri2eAkRrq5FkKsh%?H9!*yW+sN%{du*Q9%wtZjOV`FmsDDhjSf;af>DL)=ejN+h zVDx;up2)}LpThGV^&Csl^nCV5)kP#EY*NXzgyx6mADY{oF`mBR^XXSWZ!vhf`njxg HN@xNA6X}rM literal 0 HcmV?d00001 diff --git a/res/drawable-mdpi/right_pane_shadow.9.png b/res/drawable-mdpi/right_pane_shadow.9.png deleted file mode 100644 index 2962dc6c55a4072f31a9e5c4cdc3c27a347b391e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 178 zcmeAS@N?(olHy`uVBq!ia0vp^+(69C!3HE<|9|xcQjEnx?oJHr&dIz4a@dl*-CY>| zgW!U_%O?XxI14-?iy0WWUV|`WQ#WrEP>{XE)7O>#4hJifj_$=bdYgbkMxHK?AspAI zp4rIDARxkU@w+#(#!;Vd@~tgQw%22dEzK@77an5JyjX4K#{25Yt_43W^>?1-{J$YV RcNtJOgQu&X%Q~loCIB;mHgo_0 diff --git a/res/drawable-mdpi/shadow_holo.9.png b/res/drawable-mdpi/shadow_holo.9.png new file mode 100644 index 0000000000000000000000000000000000000000..4e33627f705287f461b7ebc14eccc08978d5d7ce GIT binary patch literal 293 zcmeAS@N?(olHy`uVBq!ia0vp^QXtI11|(N{`J4k%jKx9jP7LeL$-D$|*pj^6T^Rm@ z;DWu&Cj&(|3p^r=85p>QL70(Y)*K0-AbW|YuPgf7<@A}+b2MfL*s#4(zwqVvw?+6Tk e+i`{c6U$*~mFf+;=jDNJVeoYIb6Mw<&;$V9Dq)`h literal 0 HcmV?d00001 diff --git a/res/drawable-xhdpi/right_pane_shadow.9.png b/res/drawable-xhdpi/right_pane_shadow.9.png deleted file mode 100644 index ac031d25eed159cb6c10c224eabfc70525545bea..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 196 zcmeAS@N?(olHy`uVBq!ia0vp^!a&T-!3HD?+f2fN6k~CayA#8@b22Z19JVBHcNd2L zAh=-f^2tCE&H|6fVg?4T*C5Q;)Xf_O6l5>)^mS#w!!E-k#`afjwJT7_#nZ(xgyZ_! za|bya3h~wJ)Ka5F8NIuGGSwreiAMPXaTm>>-*=@1c^_Pa6pM0X%%HxVc jr&ijmqM}FJKD}WTKEU_?SWfPx#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iyx1 z1QR6*3g!3!00EjwL_t(&-rZTjal8T{m1bPzViy`BYmZgLrS2i)_1u)OxcDA zK%@kFUbMe`;bCSx&l6^5$8oqv(#-JY-nMOKW?yF3e*W)%o|wBhm>FC56#Rm9iPbY7 zb~7jMU-@!1QD$GW5gj~C?WQK{zVFc?RK&@FbYw&VwpF{0>Os}i;<7+0KwJY^Z)s#7 z5KQ?n`E<1+fg=DKD{F-L)S9Cg%%v8}vr(rJ=gK}o?1Qi9sI??uXWDPHI7H-`GhNGD zuA|2^X4|iKmN`zXTv{=UuGM9{tjTH%W+T$Sqe|@R{(Xd6>;*xm$Y-tW=vmplwu_ZD z;{8C5=%}RZe( - - - - + - + android:layout_width="@dimen/default_slidingpane_shadow_width" + android:layout_height="match_parent" + android:layout_gravity="right" + android:background="@drawable/shadow_holo"/> + - + \ No newline at end of file diff --git a/res/layout-land/home_dual_pane.xml b/res/layout-land/home_dual_pane.xml index 82a256da..0882858b 100644 --- a/res/layout-land/home_dual_pane.xml +++ b/res/layout-land/home_dual_pane.xml @@ -2,31 +2,25 @@ - - - - + - + android:layout_width="@dimen/default_slidingpane_shadow_width" + android:layout_height="match_parent" + android:layout_gravity="right" + android:background="@drawable/shadow_holo"/> + + - + \ No newline at end of file diff --git a/res/layout-land/search_dual_pane.xml b/res/layout-land/search_dual_pane.xml new file mode 100644 index 00000000..82f9a3ec --- /dev/null +++ b/res/layout-land/search_dual_pane.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/res/layout/base_dual_pane.xml b/res/layout/base_dual_pane.xml index 434c6261..6e7cc5d2 100644 --- a/res/layout/base_dual_pane.xml +++ b/res/layout/base_dual_pane.xml @@ -2,38 +2,16 @@ - + twidere:fadeType="left" + twidere:layoutLeft="@layout/base_pane_left_content" + twidere:layoutRight="@layout/base_pane_right_content" + twidere:shadowDrawable="@drawable/shadow_holo" + twidere:shadowWidth="@dimen/default_slidingpane_shadow_width" + twidere:spacingLeft="@dimen/pane_spacing_right" + twidere:spacingRight="@dimen/pane_spacing_right"/> - - - - - - - - - - - - - + \ No newline at end of file diff --git a/res/layout/base_pane_left_content.xml b/res/layout/base_pane_left_content.xml new file mode 100644 index 00000000..bbf52d56 --- /dev/null +++ b/res/layout/base_pane_left_content.xml @@ -0,0 +1,16 @@ + + + + + + + + \ No newline at end of file diff --git a/res/layout/base_pane_right_content.xml b/res/layout/base_pane_right_content.xml new file mode 100644 index 00000000..0aeea96d --- /dev/null +++ b/res/layout/base_pane_right_content.xml @@ -0,0 +1,5 @@ + + diff --git a/res/layout/filters.xml b/res/layout/filters.xml index 22bfea86..d048f0af 100644 --- a/res/layout/filters.xml +++ b/res/layout/filters.xml @@ -1,13 +1,21 @@ - + android:layout_height="match_parent" + android:orientation="vertical"> - + - + + + \ No newline at end of file diff --git a/res/layout/home_dual_pane.xml b/res/layout/home_dual_pane.xml index f9253be7..0907dd7e 100644 --- a/res/layout/home_dual_pane.xml +++ b/res/layout/home_dual_pane.xml @@ -2,39 +2,17 @@ - - - - - - - - - - - - - + twidere:fadeType="left" + twidere:layoutLeft="@layout/home_pane_left_content" + twidere:layoutRight="@layout/base_pane_right_content" + twidere:shadowDrawable="@drawable/shadow_holo" + twidere:shadowWidth="@dimen/default_slidingpane_shadow_width" + twidere:spacingLeft="@dimen/pane_spacing_right" + twidere:spacingRight="@dimen/pane_spacing_right"/> - + \ No newline at end of file diff --git a/res/layout/home_pane_left_content.xml b/res/layout/home_pane_left_content.xml new file mode 100644 index 00000000..8029d66c --- /dev/null +++ b/res/layout/home_pane_left_content.xml @@ -0,0 +1,16 @@ + + + + + + + + \ No newline at end of file diff --git a/res/layout/search_dual_pane.xml b/res/layout/search_dual_pane.xml index 69885b5d..f9c6972f 100644 --- a/res/layout/search_dual_pane.xml +++ b/res/layout/search_dual_pane.xml @@ -2,46 +2,16 @@ - - - - - - - - - - - - - - - - - - - + twidere:fadeType="left" + twidere:layoutLeft="@layout/search_pane_left_content" + twidere:layoutRight="@layout/base_pane_right_content" + twidere:shadowDrawable="@drawable/shadow_holo" + twidere:shadowWidth="@dimen/default_slidingpane_shadow_width" + twidere:spacingLeft="@dimen/pane_spacing_right" + twidere:spacingRight="@dimen/pane_spacing_right"/> + + \ No newline at end of file diff --git a/res/layout/search_pane_left_content.xml b/res/layout/search_pane_left_content.xml new file mode 100644 index 00000000..b2238967 --- /dev/null +++ b/res/layout/search_pane_left_content.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/res/values-land/dimens.xml b/res/values-land/dimens.xml index f7299816..9fb8839f 100644 --- a/res/values-land/dimens.xml +++ b/res/values-land/dimens.xml @@ -2,5 +2,6 @@ 180dp + 200dp \ No newline at end of file diff --git a/res/values-land/integers.xml b/res/values-land/integers.xml index bd2d9592..8234051a 100644 --- a/res/values-land/integers.xml +++ b/res/values-land/integers.xml @@ -1,9 +1,9 @@ - 4 - 5 - 5 - 4 + 4 + 5 + 5 + 4 \ No newline at end of file diff --git a/res/values-large-land/dimens.xml b/res/values-large-land/dimens.xml index d2eafc0d..b96f7818 100644 --- a/res/values-large-land/dimens.xml +++ b/res/values-large-land/dimens.xml @@ -1,6 +1,6 @@ - 420dp + 420dp diff --git a/res/values-large/dimens.xml b/res/values-large/dimens.xml index 7d06e548..23ba2b27 100644 --- a/res/values-large/dimens.xml +++ b/res/values-large/dimens.xml @@ -2,6 +2,6 @@ 375dp - 150dp + 150dp diff --git a/res/values/attrs.xml b/res/values/attrs.xml index 3f7fe9bd..173470b9 100644 --- a/res/values/attrs.xml +++ b/res/values/attrs.xml @@ -11,11 +11,40 @@ - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/res/values/bools.xml b/res/values/bools.xml index 44fdea45..ee2f1ba5 100644 --- a/res/values/bools.xml +++ b/res/values/bools.xml @@ -1,10 +1,10 @@ - false - false - false - false - false + false + false + false + false + false diff --git a/res/values/dimens.xml b/res/values/dimens.xml index fab27311..eb203e12 100644 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -11,6 +11,9 @@ 64dp 300dp - 120dp + 120dp + @dimen/pane_spacing_right + @dimen/pane_spacing_right + 56dp - + \ No newline at end of file diff --git a/res/values/integers.xml b/res/values/integers.xml index 8df9bc67..9de5afcf 100644 --- a/res/values/integers.xml +++ b/res/values/integers.xml @@ -1,9 +1,11 @@ - 5 - 3 - 5 - 3 + 5 + 3 + 5 + 3 + 128 + 900 \ No newline at end of file diff --git a/res/values/strings_donttranslate.xml b/res/values/strings_donttranslate.xml index 1d4a19bf..7d866b68 100644 --- a/res/values/strings_donttranslate.xml +++ b/res/values/strings_donttranslate.xml @@ -1,6 +1,6 @@ - 0.2.2.5 + 0.2.3 diff --git a/src/edu/ucdavis/earlybird/UCDService.java b/src/edu/ucdavis/earlybird/UCDService.java index e50f1418..3bfa8052 100644 --- a/src/edu/ucdavis/earlybird/UCDService.java +++ b/src/edu/ucdavis/earlybird/UCDService.java @@ -9,7 +9,6 @@ import android.content.IntentFilter; import android.location.Location; import android.location.LocationManager; -import android.os.Bundle; import android.os.IBinder; /** @@ -68,14 +67,14 @@ private final class LocationUpdateReceiver extends BroadcastReceiver { public void onReceive(final Context context, final Intent intent) { if (mLocationManager == null) return; ProfilingUtil.log("AlarmReceiver"); - final String provider = LocationManager.NETWORK_PROVIDER; + final String provider = LocationManager.NETWORK_PROVIDER; if (mLocationManager.isProviderEnabled(provider)) { final Location location = mLocationManager.getLastKnownLocation(provider); if (location != null) { ProfilingUtil.profiling(UCDService.this, ProfilingUtil.FILE_NAME_LOCATION, location.getTime() + "," + location.getLatitude() + "," + location.getLongitude() + "," + location.getProvider()); - ProfilingUtil.log(location.getTime() + "," + location.getLatitude() + "," + location.getLongitude() + "," - + location.getProvider()); + ProfilingUtil.log(location.getTime() + "," + location.getLatitude() + "," + location.getLongitude() + + "," + location.getProvider()); } } } diff --git a/src/org/mariotaku/twidere/Constants.java b/src/org/mariotaku/twidere/Constants.java index f976b0e1..39ab6717 100644 --- a/src/org/mariotaku/twidere/Constants.java +++ b/src/org/mariotaku/twidere/Constants.java @@ -473,7 +473,6 @@ public interface Constants extends TwitterConstants { public static final int PANE_LEFT = R.id.fragment_container_left; public static final int PANE_RIGHT = R.id.fragment_container_right; - public static final int PANE_RIGHT_CONTAINER = R.id.right_pane_container; public static final int NOTIFICATION_ID_HOME_TIMELINE = 1; public static final int NOTIFICATION_ID_MENTIONS = 2; diff --git a/src/org/mariotaku/twidere/activity/ComposeActivity.java b/src/org/mariotaku/twidere/activity/ComposeActivity.java index bf1672c7..21b86014 100644 --- a/src/org/mariotaku/twidere/activity/ComposeActivity.java +++ b/src/org/mariotaku/twidere/activity/ComposeActivity.java @@ -475,7 +475,7 @@ public void onLoadFinished(final Loader loader, final Bitmap data) { /** Sets the mRecentLocation object to the current location of the device **/ @Override public void onLocationChanged(final Location location) { - if (mRecentLocation == null) { + if (mRecentLocation == null) { mRecentLocation = location != null ? new ParcelableLocation(location) : null; setSupportProgressBarIndeterminateVisibility(false); } diff --git a/src/org/mariotaku/twidere/activity/DualPaneActivity.java b/src/org/mariotaku/twidere/activity/DualPaneActivity.java index 5f9b8e6d..70583bef 100644 --- a/src/org/mariotaku/twidere/activity/DualPaneActivity.java +++ b/src/org/mariotaku/twidere/activity/DualPaneActivity.java @@ -21,7 +21,7 @@ import org.mariotaku.twidere.R; import org.mariotaku.twidere.model.Panes; -import org.mariotaku.twidere.view.ExtendedFrameLayout; +import org.mariotaku.twidere.view.SlidingPaneView; import android.annotation.SuppressLint; import android.content.Context; @@ -36,72 +36,20 @@ import android.support.v4.app.FragmentManager.OnBackStackChangedListener; import android.support.v4.app.FragmentManagerTrojan; import android.support.v4.app.FragmentTransaction; -import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; -import android.widget.FrameLayout; -import org.mariotaku.twidere.util.ExtendedViewGroupInterface; -import org.mariotaku.twidere.view.SlidingPanel; @SuppressLint("Registered") public class DualPaneActivity extends BaseActivity implements OnBackStackChangedListener { private SharedPreferences mPreferences; - private SlidingPanel mSlidingPanel; - private FrameLayout mFragmentContainerLeft; - private ExtendedFrameLayout mPanelAnchor, mFragmentContainerRight; + private SlidingPaneView mSlidingPane; private Fragment mDetailsFragment; private boolean mDualPaneInPortrait, mDualPaneInLandscape; - private ExtendedViewGroupInterface.TouchInterceptor mTouchInterceptorRight = new ExtendedFrameLayout.TouchInterceptor() { - - public boolean onInterceptTouchEvent(ViewGroup view, MotionEvent event) { - final int action = event.getAction(); - switch (action) { - case MotionEvent.ACTION_DOWN: { - showRightPane(); - break; - } - } - return false; - } - - public boolean onTouchEvent(ViewGroup view, MotionEvent event) { - return true; - } - - }; - - private ExtendedViewGroupInterface.TouchInterceptor mTouchInterceptorLeft = new ExtendedFrameLayout.TouchInterceptor() { - - public boolean onInterceptTouchEvent(ViewGroup view, MotionEvent event) { - final int action = event.getAction(); - switch (action) { - case MotionEvent.ACTION_DOWN: { - showLeftPane(); - break; - } - } - return false; - } - - public boolean onTouchEvent(ViewGroup view, MotionEvent event) { - return false; - } - - }; - - public final void showLeftPane() { - mSlidingPanel.close(); - } - - public final void showRightPane() { - mSlidingPanel.open(); - } - public Fragment getDetailsFragment() { return mDetailsFragment; } @@ -145,12 +93,7 @@ public void onBackStackChanged() { @Override public void onContentChanged() { super.onContentChanged(); - if (isDualPaneMode()) { - mSlidingPanel = (SlidingPanel) findViewById(R.id.main_container); - mFragmentContainerLeft = (FrameLayout) findViewById(PANE_LEFT); - mFragmentContainerRight = (ExtendedFrameLayout) findViewById(PANE_RIGHT); - mPanelAnchor = (ExtendedFrameLayout) findViewById(R.id.panel_anchor); - } + mSlidingPane = (SlidingPaneView) findViewById(R.id.sliding_pane); } @Override @@ -174,9 +117,10 @@ public void onCreate(final Bundle savedInstanceState) { break; } setContentView(layout); - mFragmentContainerRight.setBackgroundResource(getPaneBackground()); - mFragmentContainerRight.setTouchInterceptor(mTouchInterceptorRight); - mPanelAnchor.setTouchInterceptor(mTouchInterceptorLeft); + final View pane_right = findViewById(PANE_RIGHT); + if (pane_right != null) { + pane_right.setBackgroundResource(getPaneBackground()); + } getSupportFragmentManager().addOnBackStackChangedListener(this); } @@ -210,6 +154,18 @@ public final void showFragment(final Fragment fragment, final boolean add_to_bac } } + public final void showLeftPane() { + if (mSlidingPane != null) { + mSlidingPane.animateClose(); + } + } + + public final void showRightPane() { + if (mSlidingPane != null) { + mSlidingPane.animateOpen(); + } + } + @Override protected void onStart() { final FragmentManager fm = getSupportFragmentManager(); diff --git a/src/org/mariotaku/twidere/activity/FiltersActivity.java b/src/org/mariotaku/twidere/activity/FiltersActivity.java index cdfec31f..91912d02 100644 --- a/src/org/mariotaku/twidere/activity/FiltersActivity.java +++ b/src/org/mariotaku/twidere/activity/FiltersActivity.java @@ -25,10 +25,10 @@ import org.mariotaku.twidere.fragment.BaseFiltersFragment.FilteredKeywordsFragment; import org.mariotaku.twidere.fragment.BaseFiltersFragment.FilteredSourcesFragment; import org.mariotaku.twidere.fragment.BaseFiltersFragment.FilteredUsersFragment; +import org.mariotaku.twidere.view.ExtendedViewPager; +import org.mariotaku.twidere.view.TabPageIndicator; import android.os.Bundle; -import android.support.v4.view.PagerTabStrip; -import android.support.v4.view.ViewPager; import android.view.Menu; import android.view.MenuItem; @@ -36,16 +36,16 @@ public class FiltersActivity extends BaseActivity { private ActionBar mActionBar; - private ViewPager mViewPager; - private PagerTabStrip mPagerTab; + private ExtendedViewPager mViewPager; + private TabPageIndicator mIndicator; private TabsAdapter mAdapter; @Override public void onContentChanged() { super.onContentChanged(); - mViewPager = (ViewPager) findViewById(R.id.pager); - mPagerTab = (PagerTabStrip) findViewById(R.id.pager_tab); + mViewPager = (ExtendedViewPager) findViewById(R.id.pager); + mIndicator = (TabPageIndicator) findViewById(android.R.id.tabs); } @Override @@ -56,12 +56,15 @@ public void onCreate(final Bundle savedInstanceState) { if (mActionBar != null) { mActionBar.setDisplayHomeAsUpEnabled(true); } - mAdapter = new TabsAdapter(this, getSupportFragmentManager(), null); + mAdapter = new TabsAdapter(this, getSupportFragmentManager(), mIndicator); mAdapter.addTab(FilteredUsersFragment.class, null, getString(R.string.users), null, 0); mAdapter.addTab(FilteredKeywordsFragment.class, null, getString(R.string.keywords), null, 1); mAdapter.addTab(FilteredSourcesFragment.class, null, getString(R.string.sources), null, 2); mViewPager.setAdapter(mAdapter); - mPagerTab.setTabIndicatorColorResource(R.color.holo_blue_light); + mViewPager.setPagingEnabled(false); + mIndicator.setViewPager(mViewPager); + mIndicator.setDisplayLabel(true); + mIndicator.setDisplayIcon(false); } @Override diff --git a/src/org/mariotaku/twidere/activity/LinkHandlerActivity.java b/src/org/mariotaku/twidere/activity/LinkHandlerActivity.java index 136a74c5..09239085 100644 --- a/src/org/mariotaku/twidere/activity/LinkHandlerActivity.java +++ b/src/org/mariotaku/twidere/activity/LinkHandlerActivity.java @@ -362,6 +362,7 @@ private boolean setFragment(final Uri uri) { } // This simply disables dual pane layout. + @Override int getDualPaneLayoutRes() { return getNormalLayoutRes(); } diff --git a/src/org/mariotaku/twidere/activity/SettingsActivity.java b/src/org/mariotaku/twidere/activity/SettingsActivity.java index 4b7f6881..6fe0b9a3 100644 --- a/src/org/mariotaku/twidere/activity/SettingsActivity.java +++ b/src/org/mariotaku/twidere/activity/SettingsActivity.java @@ -160,7 +160,7 @@ public boolean onPreferenceClick(final Preference preference) { if (isDualPaneMode()) { final Fragment fragment = new SettingsDetailsFragment(); fragment.setArguments(args); - showFragment(fragment, false); + showFragment(fragment, true); } else { final Intent intent = new Intent(this, SettingsDetailsActivity.class); intent.putExtras(args); diff --git a/src/org/mariotaku/twidere/fragment/StatusFragment.java b/src/org/mariotaku/twidere/fragment/StatusFragment.java index df1e928c..296e8efd 100644 --- a/src/org/mariotaku/twidere/fragment/StatusFragment.java +++ b/src/org/mariotaku/twidere/fragment/StatusFragment.java @@ -102,7 +102,6 @@ import android.widget.AdapterView.OnItemClickListener; import android.widget.BaseAdapter; import android.widget.Button; -import android.widget.FrameLayout; import android.widget.Gallery; import android.widget.ImageView; import android.widget.ListView; @@ -430,7 +429,7 @@ public boolean onMenuItemClick(final MenuItem item) { private final ExtendedFrameLayout.OnSizeChangedListener mOnSizeChangedListener = new ExtendedFrameLayout.OnSizeChangedListener() { @Override - public void onSizeChanged(View view, int w, int h, int oldw, int oldh) { + public void onSizeChanged(final View view, final int w, final int h, final int oldw, final int oldh) { if (getActivity() == null) return; final float density = getResources().getDisplayMetrics().density; mStatusView.setMinimumHeight(h - (int) (density * 2)); diff --git a/src/org/mariotaku/twidere/util/ExtendedViewGroupInterface.java b/src/org/mariotaku/twidere/util/ExtendedViewGroupInterface.java index b12773b4..e82b525a 100644 --- a/src/org/mariotaku/twidere/util/ExtendedViewGroupInterface.java +++ b/src/org/mariotaku/twidere/util/ExtendedViewGroupInterface.java @@ -6,7 +6,7 @@ public interface ExtendedViewGroupInterface extends ExtendedViewInterface { public void setTouchInterceptor(final TouchInterceptor listener); - + public static interface TouchInterceptor { boolean onInterceptTouchEvent(ViewGroup view, MotionEvent event); diff --git a/src/org/mariotaku/twidere/util/ExtendedViewInterface.java b/src/org/mariotaku/twidere/util/ExtendedViewInterface.java index d55e993e..ad9816e4 100644 --- a/src/org/mariotaku/twidere/util/ExtendedViewInterface.java +++ b/src/org/mariotaku/twidere/util/ExtendedViewInterface.java @@ -1,6 +1,5 @@ package org.mariotaku.twidere.util; -import android.view.MotionEvent; import android.view.View; public interface ExtendedViewInterface { diff --git a/src/org/mariotaku/twidere/view/ExtendedFrameLayout.java b/src/org/mariotaku/twidere/view/ExtendedFrameLayout.java index 33d06a9c..6851552d 100644 --- a/src/org/mariotaku/twidere/view/ExtendedFrameLayout.java +++ b/src/org/mariotaku/twidere/view/ExtendedFrameLayout.java @@ -20,12 +20,11 @@ package org.mariotaku.twidere.view; import org.mariotaku.twidere.util.ExtendedViewGroupInterface; - + import android.content.Context; import android.util.AttributeSet; import android.view.MotionEvent; import android.widget.FrameLayout; -import android.view.View; public final class ExtendedFrameLayout extends FrameLayout implements ExtendedViewGroupInterface { @@ -62,10 +61,12 @@ public boolean onTouchEvent(final MotionEvent event) { return super.onTouchEvent(event); } + @Override public void setOnSizeChangedListener(final OnSizeChangedListener listener) { mOnSizeChangedListener = listener; } + @Override public void setTouchInterceptor(final TouchInterceptor listener) { mTouchInterceptor = listener; } diff --git a/src/org/mariotaku/twidere/view/ExtendedLinearLayout.java b/src/org/mariotaku/twidere/view/ExtendedLinearLayout.java index a8308bb0..e4bc7a76 100644 --- a/src/org/mariotaku/twidere/view/ExtendedLinearLayout.java +++ b/src/org/mariotaku/twidere/view/ExtendedLinearLayout.java @@ -25,7 +25,6 @@ import android.util.AttributeSet; import android.view.MotionEvent; import android.widget.LinearLayout; -import android.view.View; public final class ExtendedLinearLayout extends LinearLayout implements ExtendedViewGroupInterface { @@ -61,12 +60,13 @@ public boolean onTouchEvent(final MotionEvent event) { } return super.onTouchEvent(event); } - + @Override public void setOnSizeChangedListener(final OnSizeChangedListener listener) { mOnSizeChangedListener = listener; } + @Override public void setTouchInterceptor(final TouchInterceptor listener) { mTouchInterceptor = listener; } diff --git a/src/org/mariotaku/twidere/view/SlidingPaneView.java b/src/org/mariotaku/twidere/view/SlidingPaneView.java new file mode 100644 index 00000000..0f023a87 --- /dev/null +++ b/src/org/mariotaku/twidere/view/SlidingPaneView.java @@ -0,0 +1,824 @@ +package org.mariotaku.twidere.view; + +import org.mariotaku.twidere.R; +import org.mariotaku.twidere.util.ExtendedViewGroupInterface.TouchInterceptor; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.LinearLayout; +import android.widget.Scroller; + +public class SlidingPaneView extends ViewGroup { + + /** + * Fade is disabled. + */ + public static final int FADE_NONE = 0; + /** + * Fade applies to actions container. + */ + public static final int FADE_LEFT = 1; + /** + * Fade applies to content container. + */ + public static final int FADE_RIGHT = 2; + /** + * Fade applies to every container. + */ + public static final int FADE_BOTH = 3; + + private final View mViewShadow; + private final LeftPaneLayout mViewLeftPaneContainer; + private final RightPaneLayout mViewRightPaneContainer; + private final ExtendedFrameLayout mRightPaneContent; + + final ContentScrollController mController; + + /** + * Value of spacing to use. + */ + private int mRightSpacing; + + /** + * Value of actions container spacing to use. + */ + private int mLeftSpacing; + + /** + * Value of shadow width. + */ + private int mShadowWidth = 0; + + /** + * Indicates how long flinging will take time in milliseconds. + */ + private int mFlingDuration = 250; + + /** + * Fade type. + */ + private int mFadeType = FADE_NONE; + /** + * Max fade value. + */ + private int mFadeMax; + + /** + * Indicates whether refresh of content position should be done on next + * layout calculation. + */ + private boolean mForceRefresh = false; + + private final View mLeftPaneLayout, mRightPaneLayout; + + public SlidingPaneView(final Context context) { + this(context, null); + } + + public SlidingPaneView(final Context context, final AttributeSet attrs) { + this(context, attrs, 0); + } + + public SlidingPaneView(final Context context, final AttributeSet attrs, final int defStyle) { + super(context, attrs, defStyle); + + setClipChildren(false); + setClipToPadding(false); + + // reading attributes + final TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.ActionsContentView); + final int spacingRightDefault = getResources().getDimensionPixelSize(R.dimen.default_slidepane_spacing_right); + mRightSpacing = a.getDimensionPixelSize(R.styleable.ActionsContentView_spacingRight, spacingRightDefault); + final int spacingLeftDefault = getResources().getDimensionPixelSize(R.dimen.default_slidepane_spacing_left); + mLeftSpacing = a.getDimensionPixelSize(R.styleable.ActionsContentView_spacingLeft, spacingLeftDefault); + + final int leftPaneLayout = a.getResourceId(R.styleable.ActionsContentView_layoutLeft, 0); + if (leftPaneLayout == 0) throw new IllegalArgumentException("The layoutLeft attribute is required"); + + final int rightPaneLayout = a.getResourceId(R.styleable.ActionsContentView_layoutRight, 0); + if (rightPaneLayout == leftPaneLayout || rightPaneLayout == 0) + throw new IllegalArgumentException("The layoutRight attribute is required"); + + mShadowWidth = a.getDimensionPixelSize(R.styleable.ActionsContentView_shadowWidth, 0); + final int shadowDrawableRes = a.getResourceId(R.styleable.ActionsContentView_shadowDrawable, 0); + + mFadeType = a.getInteger(R.styleable.ActionsContentView_fadeType, FADE_NONE); + final int fadeValueDefault = getResources().getInteger(R.integer.default_sliding_pane_fade_max); + mFadeMax = a.getDimensionPixelSize(R.styleable.ActionsContentView_fadeMax, fadeValueDefault); + + final int flingDurationDefault = getResources().getInteger(R.integer.default_sliding_pane_fling_duration); + mFlingDuration = a.getInteger(R.styleable.ActionsContentView_flingDuration, flingDurationDefault); + + a.recycle(); + + mController = new ContentScrollController(new Scroller(context)); + final LayoutInflater inflater = LayoutInflater.from(context); + mViewLeftPaneContainer = new LeftPaneLayout(this); + if (leftPaneLayout == 0) throw new IllegalArgumentException(); + mLeftPaneLayout = inflater.inflate(leftPaneLayout, mViewLeftPaneContainer, true); + + addView(mViewLeftPaneContainer, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + + mViewRightPaneContainer = new RightPaneLayout(this); + mViewRightPaneContainer.setOnSwipeListener(new RightPaneLayout.OnSwipeListener() { + @Override + public void onSwipe(final int scrollPosition) { + fadeViews(); + } + }); + + mViewShadow = new View(context); + mViewShadow.setBackgroundResource(shadowDrawableRes); + mViewRightPaneContainer.addView(mViewShadow, mShadowWidth, LinearLayout.LayoutParams.MATCH_PARENT); + + if (mShadowWidth <= 0 || shadowDrawableRes == 0) { + mViewShadow.setVisibility(GONE); + } + mRightPaneContent = new ExtendedFrameLayout(context); + + mRightPaneContent.setTouchInterceptor(new ScrollTouchInterceptor(this)); + + if (rightPaneLayout == 0) throw new IllegalArgumentException(); + mRightPaneLayout = inflater.inflate(rightPaneLayout, mRightPaneContent, true); + mViewRightPaneContainer.addView(mRightPaneContent, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); + + addView(mViewRightPaneContainer, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); + post(new Runnable() { + + @Override + public void run() { + close(); + } + }); + } + + public void animateClose() { + mController.hideContent(mFlingDuration); + } + + public void animateOpen() { + mController.showContent(mFlingDuration); + } + + public void close() { + mController.hideContent(0); + } + + public ViewGroup getActionsContainer() { + return mViewLeftPaneContainer; + } + + public int getActionsSpacingWidth() { + return mLeftSpacing; + } + + public ViewGroup getContentContainer() { + return mViewRightPaneContainer; + } + + public int getFadeType() { + return mFadeType; + } + + public int getFadeValue() { + return mFadeMax; + } + + public int getFlingDuration() { + return mFlingDuration; + } + + public View getLeftPaneLayout() { + return mLeftPaneLayout; + } + + public View getRightPaneLayout() { + return mRightPaneLayout; + } + + public int getShadowWidth() { + return mShadowWidth; + } + + public int getSpacingWidth() { + return mRightSpacing; + } + + public boolean isContentShown() { + return mController.isContentShown(); + } + + public boolean isOpened() { + return !mController.isContentShown(); + } + + public boolean isShadowVisible() { + return mViewShadow.getVisibility() == VISIBLE; + } + + @Override + public void onRestoreInstanceState(final Parcelable state) { + if (!(state instanceof SavedState)) { + super.onRestoreInstanceState(state); + return; + } + + final SavedState ss = (SavedState) state; + super.onRestoreInstanceState(ss.getSuperState()); + + mController.isContentShown = ss.isContentShown; + + mRightSpacing = ss.mSpacing; + mLeftSpacing = ss.mActionsSpacing; + mShadowWidth = ss.mShadowWidth; + mFlingDuration = ss.mFlingDuration; + mFadeType = ss.mFadeType; + mFadeMax = ss.mFadeValue; + + // this will call requestLayout() to calculate layout according to + // values + setShadowVisible(ss.isShadowVisible); + } + + @Override + public Parcelable onSaveInstanceState() { + final Parcelable superState = super.onSaveInstanceState(); + final SavedState ss = new SavedState(superState); + ss.isContentShown = isContentShown(); + ss.mSpacing = getSpacingWidth(); + ss.mActionsSpacing = getActionsSpacingWidth(); + ss.isShadowVisible = isShadowVisible(); + ss.mShadowWidth = getShadowWidth(); + ss.mFlingDuration = getFlingDuration(); + ss.mFadeType = getFadeType(); + ss.mFadeValue = getFadeValue(); + return ss; + } + + public void open() { + mController.showContent(0); + } + + public void setActionsSpacingWidth(final int width) { + if (mLeftSpacing == width) return; + + mLeftSpacing = width; + mForceRefresh = true; + requestLayout(); + } + + public void setFadeType(final int type) { + if (type != FADE_NONE && type != FADE_LEFT && type != FADE_RIGHT && type != FADE_BOTH) return; + + mFadeType = type; + } + + public void setFadeValue(final int value) { + mFadeMax = limit(value, 0x00, 0xFF); + } + + public void setFlingDuration(final int duration) { + mFlingDuration = duration; + } + + public void setShadowVisible(final boolean visible) { + mViewShadow.setVisibility(visible ? VISIBLE : GONE); + mForceRefresh = true; + requestLayout(); + } + + public void setShadowWidth(final int width) { + if (mShadowWidth == width) return; + + mShadowWidth = width; + mViewShadow.getLayoutParams().width = mShadowWidth; + mForceRefresh = true; + requestLayout(); + } + + public void setSpacingWidth(final int width) { + if (mRightSpacing == width) return; + + mRightSpacing = width; + mForceRefresh = true; + requestLayout(); + } + + public void toggle() { + if (isOpened()) { + animateOpen(); + } else { + animateClose(); + } + } + + @Override + protected void onLayout(final boolean changed, final int l, final int t, final int r, final int b) { + // putting every child view to top-left corner + final int childrenCount = getChildCount(); + for (int i = 0; i < childrenCount; ++i) { + final View v = getChildAt(i); + if (v == mViewRightPaneContainer) { + final int shadowWidth = isShadowVisible() ? mShadowWidth : 0; + v.layout(l + mLeftSpacing - shadowWidth, t, l + mLeftSpacing + v.getMeasuredWidth(), + t + v.getMeasuredHeight()); + } else { + v.layout(l, t, l + v.getMeasuredWidth(), t + v.getMeasuredHeight()); + } + } + + if (mForceRefresh) { + mForceRefresh = false; + mController.init(); + } + } + + @Override + protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { + final int width = MeasureSpec.getSize(widthMeasureSpec); + + final int childrenCount = getChildCount(); + for (int i = 0; i < childrenCount; ++i) { + final View v = getChildAt(i); + if (v == mViewLeftPaneContainer) { + // setting size of actions according to spacing parameters + mViewLeftPaneContainer.measure(MeasureSpec.makeMeasureSpec(width - mRightSpacing, MeasureSpec.EXACTLY), + heightMeasureSpec); + } else if (v == mViewRightPaneContainer) { + final int shadowWidth = isShadowVisible() ? mShadowWidth : 0; + final int contentWidth = MeasureSpec.getSize(widthMeasureSpec) - mLeftSpacing + shadowWidth; + v.measure(MeasureSpec.makeMeasureSpec(contentWidth, MeasureSpec.EXACTLY), heightMeasureSpec); + } else { + v.measure(widthMeasureSpec, heightMeasureSpec); + } + } + + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + + @Override + protected void onSizeChanged(final int w, final int h, final int oldw, final int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + + // set correct position of content view after view size was changed + if (w != oldw || h != oldh) { + mController.init(); + } + } + + private void fadeViews() { + if (mFadeType == FADE_NONE) return; + + final float scrollFactor = mController.getScrollFactor(); + if ((mFadeType & FADE_LEFT) > 0) { + final int fadeFactor = (int) (scrollFactor * mFadeMax); + mViewLeftPaneContainer.invalidate(fadeFactor); + } + if ((mFadeType & FADE_RIGHT) > 0) { + final int fadeFactor = (int) ((1f - scrollFactor) * mFadeMax); + mViewRightPaneContainer.invalidate(fadeFactor); + } + } + + private ContentScrollController getController() { + return mController; + } + + /** + * Returns right bound (limit) for scroller. + * + * @return right bound (limit) for scroller. + */ + private int getRightBound() { + return getWidth() - mRightSpacing - mLeftSpacing; + } + + static int limit(final int value, final int min, final int max) { + if (value < min) return min; + if (value > max) return max; + return value; + } + + public static class LeftPaneLayout extends FrameLayout { + + private final Paint mFadePaint = new Paint(); + private int mFadeFactor = 0; + private final SlidingPaneView parent; + + public LeftPaneLayout(final SlidingPaneView parent) { + super(parent.getContext()); + this.parent = parent; + } + + public void invalidate(final int fadeFactor) { + mFadeFactor = fadeFactor; + invalidate(); + } + + @Override + public boolean onInterceptTouchEvent(final MotionEvent ev) { + if (ev.getAction() == MotionEvent.ACTION_DOWN) { + parent.animateClose(); + } + return super.onInterceptTouchEvent(ev); + } + + @Override + protected void dispatchDraw(final Canvas canvas) { + super.dispatchDraw(canvas); + + if (mFadeFactor > 0f) { + mFadePaint.setColor(Color.argb(mFadeFactor, 0, 0, 0)); + canvas.drawRect(0, 0, getWidth(), getHeight(), mFadePaint); + } + } + } + + public static class SavedState extends BaseSavedState { + /** + * Indicates whether content was shown while saving state. + */ + private boolean isContentShown; + + /** + * Value of spacing to use. + */ + private int mSpacing; + + /** + * Value of actions container spacing to use. + */ + private int mActionsSpacing; + + /** + * Indicates whether shadow is visible. + */ + private boolean isShadowVisible; + + /** + * Value of shadow width. + */ + private int mShadowWidth = 0; + + /** + * Indicates how long flinging will take time in milliseconds. + */ + private int mFlingDuration = 250; + + /** + * Fade type. + */ + private int mFadeType = FADE_NONE; + /** + * Max fade value. + */ + private int mFadeValue; + + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + @Override + public SavedState createFromParcel(final Parcel source) { + return new SavedState(source); + } + + @Override + public SavedState[] newArray(final int size) { + return new SavedState[size]; + } + }; + + public SavedState(final Parcelable superState) { + super(superState); + } + + SavedState(final Parcel in) { + super(in); + + isContentShown = in.readInt() == 1; + mSpacing = in.readInt(); + mActionsSpacing = in.readInt(); + isShadowVisible = in.readInt() == 1; + mShadowWidth = in.readInt(); + mFlingDuration = in.readInt(); + mFadeType = in.readInt(); + mFadeValue = in.readInt(); + } + + @Override + public void writeToParcel(final Parcel out, final int flags) { + super.writeToParcel(out, flags); + + out.writeInt(isContentShown ? 1 : 0); + out.writeInt(mSpacing); + out.writeInt(mActionsSpacing); + out.writeInt(isShadowVisible ? 1 : 0); + out.writeInt(mShadowWidth); + out.writeInt(mFlingDuration); + out.writeInt(mFadeType); + out.writeInt(mFadeValue); + } + } + + /** + * Used to handle scrolling events and scroll content container on top of + * actions one. + * + * @author steven + * + */ + private class ContentScrollController implements Runnable { + + /** + * Used to auto-scroll to closest bound on touch up event. + */ + private final Scroller mScroller; + + private int mLastFlingX = 0; + + /** + * Indicates whether we need initialize position of view after measuring + * is finished. + */ + private boolean isContentShown = true; + + public ContentScrollController(final Scroller scroller) { + mScroller = scroller; + } + + public float getScrollFactor() { + return 1f + (float) mViewRightPaneContainer.getScrollX() / (float) getRightBound(); + } + + public void hideContent(final int duration) { + isContentShown = false; + if (mViewRightPaneContainer.getMeasuredWidth() == 0 || mViewRightPaneContainer.getMeasuredHeight() == 0) + return; + + final int startX = mViewRightPaneContainer.getScrollX(); + final int dx = getRightBound() + startX; + fling(startX, dx, duration); + } + + /** + * Initializes visibility of content after views measuring is finished. + */ + public void init() { + if (isContentShown) { + showContent(0); + } else { + hideContent(0); + } + fadeViews(); + } + + public boolean isContentShown() { + final int x; + if (!mScroller.isFinished()) { + x = mScroller.getFinalX(); + } else { + x = mViewRightPaneContainer.getScrollX(); + } + + return x == 0; + } + + public void release(final float delta, final float totalMove) { + completeScrolling(delta); + } + + /** + * Resets scroller controller. Stops flinging on current position. + */ + public void reset() { + if (!mScroller.isFinished()) { + mScroller.forceFinished(true); + } + } + + /** + * Processes auto-scrolling to bound which is closer to current + * position. + */ + @Override + public void run() { + if (mScroller.isFinished()) return; + + final boolean more = mScroller.computeScrollOffset(); + final int x = mScroller.getCurrX(); + final int diff = mLastFlingX - x; + if (diff != 0) { + mViewRightPaneContainer.scrollBy(diff, 0); + mLastFlingX = x; + } + + if (more) { + mViewRightPaneContainer.post(this); + } + } + + public void showContent(final int duration) { + isContentShown = true; + if (mViewRightPaneContainer.getMeasuredWidth() == 0 || mViewRightPaneContainer.getMeasuredHeight() == 0) + return; + + final int startX = mViewRightPaneContainer.getScrollX(); + final int dx = startX; + fling(startX, dx, duration); + } + + /** + * Starts auto-scrolling to bound which is closer to current position. + * + * @param delta + */ + private void completeScrolling(final float delta) { + // if (delta == 0) return; + if (delta > 0) { + showContent(getFlingDuration()); + } else { + hideContent(getFlingDuration()); + } + } + + private void fling(final int startX, final int dx, final int duration) { + reset(); + + if (dx == 0) return; + + if (duration <= 0) { + mViewRightPaneContainer.scrollBy(-dx, 0); + return; + } + + mScroller.startScroll(startX, 0, dx, 0, duration); + + mLastFlingX = startX; + mViewRightPaneContainer.post(this); + } + + /** + * Scrolling content view according by given value. + * + * @param dx + */ + private void scrollBy(final int dx) { + final int x = mViewRightPaneContainer.getScrollX(); + + final int scrollBy; + if (dx < 0) { // scrolling right + final int rightBound = getRightBound(); + if (x + dx < -rightBound) { + scrollBy = -rightBound - x; + } else { + scrollBy = dx; + } + } else { // scrolling left + // don't scroll if we are at left bound + if (x == 0) return; + + if (x + dx > 0) { + scrollBy = -x; + } else { + scrollBy = dx; + } + } + + mViewRightPaneContainer.scrollBy(scrollBy, 0); + } + } + + private static class RightPaneLayout extends LinearLayout { + + private final Paint mFadePaint = new Paint(); + + private int mFadeFactor = 0; + private OnSwipeListener mOnSwipeListener; + + public RightPaneLayout(final SlidingPaneView parent) { + super(parent.getContext()); + setOrientation(LinearLayout.HORIZONTAL); + } + + public void invalidate(final int fadeFactor) { + mFadeFactor = fadeFactor; + invalidate(); + } + + public void setOnSwipeListener(final OnSwipeListener listener) { + mOnSwipeListener = listener; + } + + @Override + protected void dispatchDraw(final Canvas canvas) { + super.dispatchDraw(canvas); + + if (mFadeFactor > 0f) { + mFadePaint.setColor(Color.argb(mFadeFactor, 0, 0, 0)); + canvas.drawRect(0, 0, getWidth(), getHeight(), mFadePaint); + } + } + + @Override + protected void onScrollChanged(final int l, final int t, final int oldl, final int oldt) { + super.onScrollChanged(l, t, oldl, oldt); + if (mOnSwipeListener != null) { + mOnSwipeListener.onSwipe(-getScrollX()); + } + } + + public static interface OnSwipeListener { + public void onSwipe(int scrollPosition); + } + + } + + private static class ScrollTouchInterceptor implements TouchInterceptor { + + private float mTempDelta, mTotalMove; + private final int mScaledTouchSlop; + ContentScrollController mController; + + public ScrollTouchInterceptor(final SlidingPaneView parent) { + mScaledTouchSlop = ViewConfiguration.get(parent.getContext()).getScaledTouchSlop(); + mController = parent.getController(); + } + + @Override + public boolean onInterceptTouchEvent(final ViewGroup view, final MotionEvent event) { + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: { + mTempDelta = 0; + mTotalMove = 0; + mController.reset(); + break; + } + case MotionEvent.ACTION_MOVE: { + final int hist_size = event.getHistorySize(); + if (hist_size == 0) { + break; + } + mTempDelta = event.getX() - event.getHistoricalX(0); + mTotalMove += mTempDelta; + if (Math.abs(mTotalMove) >= mScaledTouchSlop) return true; + break; + } + case MotionEvent.ACTION_UP: { + mTempDelta = 0; + mTotalMove = 0; + break; + } + default: { + mTempDelta = 0; + mTotalMove = 0; + break; + } + } + return false; + } + + @Override + public boolean onTouchEvent(final ViewGroup view, final MotionEvent event) { + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: { + mTempDelta = 0; + mTotalMove = 0; + mController.reset(); + break; + } + case MotionEvent.ACTION_MOVE: { + final int hist_size = event.getHistorySize(); + if (hist_size == 0) { + break; + } + final float distanceX = mTempDelta = event.getX() - event.getHistoricalX(0); + mTotalMove += mTempDelta; + mController.scrollBy((int) -distanceX); + break; + } + case MotionEvent.ACTION_UP: { + mController.release(-mTempDelta, -mTotalMove); + mTempDelta = 0; + mTotalMove = 0; + break; + } + default: { + mTempDelta = 0; + mTotalMove = 0; + break; + } + } + return false; + } + } +} diff --git a/src/org/mariotaku/twidere/view/SlidingPanel.java b/src/org/mariotaku/twidere/view/SlidingPanel.java deleted file mode 100644 index abedcd41..00000000 --- a/src/org/mariotaku/twidere/view/SlidingPanel.java +++ /dev/null @@ -1,163 +0,0 @@ -package org.mariotaku.twidere.view; - -import org.mariotaku.twidere.R; - -import android.content.Context; -import android.content.res.TypedArray; -import android.util.AttributeSet; -import android.view.View; -import android.view.ViewGroup; -import android.view.animation.AccelerateDecelerateInterpolator; -import android.view.animation.Animation; -import android.view.animation.TranslateAnimation; -import android.view.animation.Animation.AnimationListener; - -public class SlidingPanel extends ViewGroup { - - private final int mAnchorId; - private View mAnchor; - private final int mContentId; - private View mContent; - - private final int mClosedLimit; - - private boolean mAnimating = false; - private int mFillOffset = 0; - - private boolean mExpanded = true; - - public SlidingPanel(Context context, AttributeSet attrs) { - this(context, attrs, 0); - } - - public SlidingPanel(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SlidingPanel, - defStyle, 0); - - final int anchorId = a.getResourceId(R.styleable.SlidingPanel_anchor, 0); - if (anchorId == 0) { - throw new IllegalArgumentException("The anchor attribute is required and must refer" + - " to a different child"); - } - - final int contentId = a.getResourceId(R.styleable.SlidingPanel_content, 0); - if (contentId == anchorId || contentId == 0) { - throw new IllegalArgumentException("The content attribute is required and must refer" + - " to a different child"); - } - - mClosedLimit = a.getDimensionPixelSize(R.styleable.SlidingPanel_closedLimit, 0); - - a.recycle(); - - mAnchorId = anchorId; - mContentId = contentId; - - } - - @Override - protected void onFinishInflate() { - mAnchor = findViewById(mAnchorId); - if (mAnchor == null) { - throw new IllegalArgumentException("The anchor attribute must refer to a child"); - } - - mContent = findViewById(mContentId); - if (mContent == null) { - throw new IllegalArgumentException("The content attribute must refer to a child"); - } - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - int width = View.resolveSize(0, widthMeasureSpec); - int height = View.resolveSize(0, heightMeasureSpec); - - final View anchor = mAnchor; - measureChild(anchor, widthMeasureSpec, heightMeasureSpec); - - final View content = mContent; - int contentWidth = width - mClosedLimit; - content.measure(MeasureSpec.makeMeasureSpec(contentWidth, MeasureSpec.EXACTLY), - MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)); - - setMeasuredDimension(width, height); - } - - @Override - protected void onLayout(boolean changed, int l, int t, int r, int b) { - final View anchor = mAnchor; - anchor.layout(0, 0, anchor.getMeasuredWidth(), - getMeasuredHeight()); - - final View content = mContent; - final int contentLeft; - if (mAnimating) { - contentLeft = content.getLeft(); - } else if (mExpanded) { - contentLeft = mClosedLimit; - } else { - contentLeft = anchor.getRight(); - } - content.layout(contentLeft, 0, - contentLeft + content.getMeasuredWidth(), - content.getMeasuredHeight()); - } - - public void open() { - if (mExpanded) return; - toggle(); - } - - public void close() { - if (!mExpanded) return; - toggle(); - } - - public boolean isOpened() { - return mExpanded; - } - - public void toggle() { - if (mAnimating) return; - final View content = mContent; - - final View anchor = mAnchor; - final int offset = anchor.getMeasuredWidth() - mClosedLimit; - TranslateAnimation anim; - if (mExpanded) { - anim = new TranslateAnimation(0, offset, 0, 0); - mFillOffset = offset; - } else { - anim = new TranslateAnimation(0, -offset, 0, 0); - mFillOffset = -offset; - } - mExpanded = !mExpanded; - anim.setFillEnabled(true); - anim.setFillBefore(true); - anim.setDuration(200); - anim.setInterpolator(new AccelerateDecelerateInterpolator()); - anim.setAnimationListener(new AnimationFiller()); - content.startAnimation(anim); - } - - private class AnimationFiller implements AnimationListener { - - @Override - public void onAnimationEnd(Animation animation) { - mContent.offsetLeftAndRight(mFillOffset); - mAnimating = false; - } - - @Override - public void onAnimationRepeat(Animation animation) { - } - - @Override - public void onAnimationStart(Animation animation) { - mAnimating = true; - } - - } -} diff --git a/src/org/mariotaku/twidere/view/TabPageIndicator.java b/src/org/mariotaku/twidere/view/TabPageIndicator.java index 505a0ca1..d1c14a0f 100644 --- a/src/org/mariotaku/twidere/view/TabPageIndicator.java +++ b/src/org/mariotaku/twidere/view/TabPageIndicator.java @@ -74,7 +74,7 @@ public boolean onLongClick(final View view) { private int mSelectedTabIndex; private boolean mPagingEnabled = true; - private boolean mDisplayLabel; + private boolean mDisplayLabel, mDisplayColor = true; public TabPageIndicator(final Context context) { super(context); @@ -200,8 +200,13 @@ public void setCurrentItem(final int item) { } } - public void setDisplayLabel(final boolean label) { - mDisplayLabel = label; + public void setDisplayIcon(final boolean display) { + mDisplayColor = display; + notifyDataSetChanged(); + } + + public void setDisplayLabel(final boolean display) { + mDisplayLabel = display; notifyDataSetChanged(); } @@ -234,7 +239,7 @@ public void setViewPager(final ExtendedViewPager pager, final int initialPositio private void addTab(final CharSequence text, final Drawable icon, final int index) { // Workaround for not being able to pass a defStyle on pre-3.0 final TabView tabView = (TabView) mInflater.inflate(R.layout.vpi__tab, null); - tabView.init(this, mDisplayLabel ? text : null, icon, index); + tabView.init(this, mDisplayLabel ? text : null, mDisplayColor ? icon : null, index); tabView.setFocusable(true); tabView.setOnClickListener(mTabClickListener); tabView.setOnLongClickListener(mTabLongClickListener);