├── app
├── .gitignore
├── src
│ ├── main
│ │ ├── res
│ │ │ ├── mipmap-hdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── values
│ │ │ │ ├── strings.xml
│ │ │ │ ├── colors.xml
│ │ │ │ ├── dimens.xml
│ │ │ │ └── styles.xml
│ │ │ ├── menu
│ │ │ │ └── menu_main.xml
│ │ │ ├── values-w820dp
│ │ │ │ └── dimens.xml
│ │ │ ├── layout
│ │ │ │ ├── view_recyclerview.xml
│ │ │ │ ├── content_main.xml
│ │ │ │ └── activity_main.xml
│ │ │ └── values-v21
│ │ │ │ └── styles.xml
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ │ └── me
│ │ │ └── undownding
│ │ │ └── baseui
│ │ │ └── MainActivity.java
│ ├── test
│ │ └── java
│ │ │ └── me
│ │ │ └── undownding
│ │ │ └── baseui
│ │ │ └── ExampleUnitTest.java
│ └── androidTest
│ │ └── java
│ │ └── me
│ │ └── undownding
│ │ └── baseui
│ │ └── ApplicationTest.java
├── proguard-rules.pro
└── build.gradle
├── library
├── .gitignore
├── src
│ ├── main
│ │ ├── res
│ │ │ ├── values
│ │ │ │ ├── strings.xml
│ │ │ │ ├── dimens.xml
│ │ │ │ ├── colors.xml
│ │ │ │ ├── styles_swipeback.xml
│ │ │ │ ├── attrs.xml
│ │ │ │ ├── styles.xml
│ │ │ │ ├── attrs_swipeback.xml
│ │ │ │ └── themes.xml
│ │ │ ├── drawable
│ │ │ │ └── bottom_shadow.9.png
│ │ │ ├── drawable-xhdpi
│ │ │ │ ├── shadow_left.png
│ │ │ │ ├── shadow_bottom.png
│ │ │ │ └── shadow_right.png
│ │ │ ├── values-v21
│ │ │ │ ├── styles.xml
│ │ │ │ └── themes.xml
│ │ │ ├── layout
│ │ │ │ ├── swipeback_layout.xml
│ │ │ │ └── activity_very_base.xml
│ │ │ ├── values-v19
│ │ │ │ └── themes.xml
│ │ │ ├── layout-v21
│ │ │ │ └── activity_very_base.xml
│ │ │ └── layout-v19
│ │ │ │ └── activity_very_base.xml
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ │ ├── me
│ │ │ ├── imid
│ │ │ │ └── swipebacklayout
│ │ │ │ │ └── lib
│ │ │ │ │ ├── app
│ │ │ │ │ ├── SwipeBackActivityBase.java
│ │ │ │ │ ├── SwipeBackPreferenceActivity.java
│ │ │ │ │ ├── SwipeBackActivity.java
│ │ │ │ │ └── SwipeBackActivityHelper.java
│ │ │ │ │ ├── Utils.java
│ │ │ │ │ ├── SwipeBackLayout.java
│ │ │ │ │ └── ViewDragHelper.java
│ │ │ └── undownding
│ │ │ │ └── baseui
│ │ │ │ └── library
│ │ │ │ ├── NoFitLinearLayout.java
│ │ │ │ ├── VeryBaseActivity.java
│ │ │ │ └── ShadowView.java
│ │ │ └── moe
│ │ │ └── feng
│ │ │ └── material
│ │ │ └── statusbar
│ │ │ ├── StatusBarCompat.java
│ │ │ ├── TranslucentSBActivity.java
│ │ │ ├── util
│ │ │ └── ViewHelper.java
│ │ │ ├── StatusBarHeaderView.java
│ │ │ └── AppBarLayout.java
│ ├── test
│ │ └── java
│ │ │ └── me
│ │ │ └── undownding
│ │ │ └── baseui
│ │ │ └── library
│ │ │ └── ExampleUnitTest.java
│ └── androidTest
│ │ └── java
│ │ └── me
│ │ └── undownding
│ │ └── baseui
│ │ └── library
│ │ └── ApplicationTest.java
├── proguard-rules.pro
└── build.gradle
├── settings.gradle
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── .gitignore
├── gradle.properties
├── README.md
├── gradlew.bat
└── gradlew
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/library/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':library'
2 |
--------------------------------------------------------------------------------
/library/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
20 | * Call this whenever the background of a translucent Activity has changed 21 | * to become opaque. Doing so will allow the {@link android.view.Surface} of 22 | * the Activity behind to be released. 23 | *
24 | * This call has no effect on non-translucent activities or on activities 25 | * with the {@link android.R.attr#windowIsFloating} attribute. 26 | */ 27 | public static void convertActivityFromTranslucent(Activity activity) { 28 | try { 29 | Method method = Activity.class.getDeclaredMethod("convertFromTranslucent"); 30 | method.setAccessible(true); 31 | method.invoke(activity); 32 | } catch (Throwable t) { 33 | } 34 | } 35 | 36 | /** 37 | * Convert a translucent themed Activity 38 | * {@link android.R.attr#windowIsTranslucent} back from opaque to 39 | * translucent following a call to 40 | * {@link #convertActivityFromTranslucent(android.app.Activity)} . 41 | *
42 | * Calling this allows the Activity behind this one to be seen again. Once 43 | * all such Activities have been redrawn 44 | *
45 | * This call has no effect on non-translucent activities or on activities
46 | * with the {@link android.R.attr#windowIsFloating} attribute.
47 | */
48 | public static void convertActivityToTranslucent(Activity activity) {
49 | try {
50 | Class>[] classes = Activity.class.getDeclaredClasses();
51 | Class> translucentConversionListenerClazz = null;
52 | for (Class clazz : classes) {
53 | if (clazz.getSimpleName().contains("TranslucentConversionListener")) {
54 | translucentConversionListenerClazz = clazz;
55 | }
56 | }
57 | Method method = Activity.class.getDeclaredMethod("convertToTranslucent",
58 | translucentConversionListenerClazz);
59 | method.setAccessible(true);
60 | method.invoke(activity, new Object[] {
61 | null
62 | });
63 | } catch (Throwable t) {
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/library/src/main/java/me/undownding/baseui/library/VeryBaseActivity.java:
--------------------------------------------------------------------------------
1 | package me.undownding.baseui.library;
2 |
3 | import android.os.Build;
4 | import android.os.Bundle;
5 | import android.support.design.widget.AppBarLayout;
6 | import android.support.v4.widget.NestedScrollView;
7 | import android.support.v7.widget.Toolbar;
8 | import android.view.View;
9 | import android.view.ViewGroup;
10 | import android.widget.FrameLayout;
11 |
12 | import moe.feng.material.statusbar.TranslucentSBActivity;
13 | import moe.feng.material.statusbar.util.ViewHelper;
14 |
15 | /**
16 | * Created by undownding on 15-11-10.
17 | */
18 | public class VeryBaseActivity extends TranslucentSBActivity{
19 |
20 | private boolean toolbarAutoHidden;
21 | private Toolbar toolbar;
22 | private FrameLayout content;
23 |
24 | @Override
25 | protected void onCreate(Bundle savedInstanceState) {
26 | super.onCreate(savedInstanceState);
27 | super.setContentView(R.layout.activity_very_base);
28 | toolbar = (Toolbar) findViewById(R.id.toolbar);
29 | content = (FrameLayout) findViewById(R.id.verybase_content);
30 |
31 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
32 | View view = findViewById(R.id.status_bar_view);
33 | if (ViewHelper.isChrome()) {
34 | view.setVisibility(View.GONE);
35 | } else {
36 | view.getLayoutParams().height = ViewHelper.getStatusBarHeight(this);
37 | view.invalidate();
38 | }
39 | }
40 | }
41 |
42 | public boolean isToolbarAutoHidden() {
43 | return toolbarAutoHidden;
44 | }
45 |
46 | public void setToolbarAutoHidden(boolean toolbarAutoHidden) {
47 | this.toolbarAutoHidden = toolbarAutoHidden;
48 | AppBarLayout.LayoutParams params =
49 | (AppBarLayout.LayoutParams) toolbar.getLayoutParams();
50 | if (isToolbarAutoHidden()) {
51 | params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL
52 | | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS);
53 | } else {
54 | params.setScrollFlags(0);
55 | }
56 | toolbar.invalidate();
57 | }
58 |
59 | @Override
60 | public final void setContentView(int layoutResID) {
61 | final View view = getLayoutInflater().inflate(layoutResID, content, false);
62 | setContentView(view);
63 | }
64 |
65 | @Override
66 | public final void setContentView(View view) {
67 | setContentView(view, new NestedScrollView.LayoutParams(
68 | ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
69 | );
70 | }
71 |
72 | @Override
73 | public final void setContentView(View view, ViewGroup.LayoutParams params) {
74 | content.addView(view, params);
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/library/src/main/java/me/undownding/baseui/library/ShadowView.java:
--------------------------------------------------------------------------------
1 | package me.undownding.baseui.library;
2 |
3 | import android.annotation.TargetApi;
4 | import android.content.Context;
5 | import android.os.Build;
6 | import android.support.v4.view.NestedScrollingChild;
7 | import android.support.v4.view.NestedScrollingChildHelper;
8 | import android.util.AttributeSet;
9 | import android.widget.FrameLayout;
10 |
11 | /**
12 | * Created by undownding on 15-11-10.
13 | */
14 | public class ShadowView extends FrameLayout implements NestedScrollingChild {
15 |
16 | private final NestedScrollingChildHelper mChildHelper = new NestedScrollingChildHelper(this);
17 |
18 | public ShadowView(Context context) {
19 | super(context);
20 | }
21 |
22 | public ShadowView(Context context, AttributeSet attrs) {
23 | super(context, attrs);
24 | }
25 |
26 | public ShadowView(Context context, AttributeSet attrs, int defStyleAttr) {
27 | super(context, attrs, defStyleAttr);
28 | }
29 |
30 | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
31 | public ShadowView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
32 | super(context, attrs, defStyleAttr, defStyleRes);
33 | }
34 |
35 | // NestedScrollingChild
36 |
37 | @Override
38 | public void setNestedScrollingEnabled(boolean enabled) {
39 | mChildHelper.setNestedScrollingEnabled(enabled);
40 | }
41 |
42 | @Override
43 | public boolean isNestedScrollingEnabled() {
44 | return mChildHelper.isNestedScrollingEnabled();
45 | }
46 |
47 | @Override
48 | public boolean startNestedScroll(int axes) {
49 | return mChildHelper.startNestedScroll(axes);
50 | }
51 |
52 | @Override
53 | public void stopNestedScroll() {
54 | mChildHelper.stopNestedScroll();
55 | }
56 |
57 | @Override
58 | public boolean hasNestedScrollingParent() {
59 | return mChildHelper.hasNestedScrollingParent();
60 | }
61 |
62 | @Override
63 | public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed,
64 | int dyUnconsumed, int[] offsetInWindow) {
65 | return mChildHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed,
66 | offsetInWindow);
67 | }
68 |
69 | @Override
70 | public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) {
71 | return mChildHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow);
72 | }
73 |
74 | @Override
75 | public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
76 | return mChildHelper.dispatchNestedFling(velocityX, velocityY, consumed);
77 | }
78 |
79 | @Override
80 | public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
81 | return mChildHelper.dispatchNestedPreFling(velocityX, velocityY);
82 | }
83 |
84 | }
85 |
--------------------------------------------------------------------------------
/library/src/main/java/moe/feng/material/statusbar/StatusBarHeaderView.java:
--------------------------------------------------------------------------------
1 | package moe.feng.material.statusbar;
2 |
3 | import android.content.Context;
4 | import android.content.res.TypedArray;
5 | import android.graphics.Color;
6 | import android.os.Build;
7 | import android.util.AttributeSet;
8 | import android.view.View;
9 | import android.view.ViewGroup;
10 |
11 | import me.undownding.baseui.library.R;
12 | import moe.feng.material.statusbar.util.ViewHelper;
13 |
14 | public class StatusBarHeaderView extends View {
15 |
16 | private int colorNormal, colorDark, enableMode;
17 |
18 | public static final int MODE_KITKAT = 1, MODE_LOLLIPOP = 2, MODE_ALL = 3;
19 |
20 | public StatusBarHeaderView(Context context) {
21 | this(context, null);
22 | }
23 |
24 | public StatusBarHeaderView(Context context, AttributeSet attrs) {
25 | this(context, attrs, 0);
26 | }
27 |
28 | public StatusBarHeaderView(Context context, AttributeSet attrs, int defStyle) {
29 | super(context, attrs, defStyle);
30 | TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.StatusBarHeaderView, defStyle,
31 | R.style.Widget_FengMoe_StatusBarHeaderView);
32 | colorNormal = a.getColor(R.styleable.StatusBarHeaderView_colorNormal, Color.TRANSPARENT);
33 | if (a.hasValue(R.styleable.StatusBarHeaderView_colorDark)) {
34 | colorDark = a.getColor(R.styleable.StatusBarHeaderView_colorDark, Color.TRANSPARENT);
35 | } else {
36 | colorDark = ViewHelper.getMiddleColor(colorNormal, Color.BLACK, 0.2f);
37 | }
38 | enableMode = a.getInt(R.styleable.StatusBarHeaderView_enableMode, MODE_ALL);
39 | init();
40 | a.recycle();
41 | }
42 |
43 | public StatusBarHeaderView(Context context, int colorNormal, int colorDark, int enableMode) {
44 | this(context);
45 | this.colorNormal = colorNormal;
46 | this.colorDark = colorDark;
47 | this.enableMode = enableMode;
48 | init();
49 | }
50 |
51 | @Override
52 | public void onMeasure(int widthSpec, int heightSpec) {
53 | super.onMeasure(widthSpec, heightSpec);
54 | // adjustHeight();
55 | }
56 |
57 | @Override
58 | public void invalidate() {
59 | super.invalidate();
60 | adjustHeight();
61 | }
62 |
63 | public void adjustHeight() {
64 | ViewGroup.LayoutParams params = getLayoutParams();
65 | params.height = ViewHelper.getStatusBarHeight(getContext());
66 | }
67 |
68 | void init() {
69 | int SDK_INT = Build.VERSION.SDK_INT;
70 | this.setBackgroundColor(SDK_INT == 19 ? colorNormal : colorDark);
71 | this.setVisibility(
72 | !ViewHelper.isChrome() && (
73 | (((enableMode == MODE_KITKAT) && (SDK_INT == 19)) ||
74 | ((enableMode == MODE_LOLLIPOP) && (SDK_INT == 21)) ||
75 | ((enableMode == MODE_ALL) && (SDK_INT >= 19)))
76 | ) ? View.VISIBLE : View.GONE
77 | );
78 | }
79 |
80 | public void setNormalColor(int colorNormal) {
81 | this.colorNormal = colorNormal;
82 | init();
83 | }
84 |
85 | public void setDarkColor(int colorDark) {
86 | this.colorDark = colorDark;
87 | init();
88 | }
89 |
90 | public int getNormalColor() {
91 | return this.colorNormal;
92 | }
93 |
94 | public int getDarkColor() {
95 | return this.colorDark;
96 | }
97 |
98 | public void setMode(int mode) {
99 | this.enableMode = mode;
100 | init();
101 | }
102 |
103 | public int getMode() {
104 | return this.enableMode;
105 | }
106 |
107 | }
108 |
--------------------------------------------------------------------------------
/library/src/main/java/moe/feng/material/statusbar/AppBarLayout.java:
--------------------------------------------------------------------------------
1 | package moe.feng.material.statusbar;
2 |
3 | import android.content.Context;
4 | import android.content.res.TypedArray;
5 | import android.graphics.Color;
6 | import android.os.Build;
7 | import android.support.annotation.ColorInt;
8 | import android.support.annotation.ColorRes;
9 | import android.util.AttributeSet;
10 | import android.widget.LinearLayout;
11 |
12 | import me.undownding.baseui.library.R;
13 | import moe.feng.material.statusbar.util.ViewHelper;
14 |
15 | public class AppBarLayout extends LinearLayout {
16 |
17 | private int colorNormal, colorDark, enableMode;
18 |
19 | private StatusBarHeaderView headerView;
20 |
21 | public static final int MODE_KITKAT = 1, MODE_LOLLIPOP = 2, MODE_ALL = 3;
22 |
23 | public AppBarLayout(Context context) {
24 | this(context, null);
25 | }
26 |
27 | public AppBarLayout(Context context, AttributeSet attrs) {
28 | this(context, attrs, 0);
29 | }
30 |
31 | public AppBarLayout(Context context, AttributeSet attrs, int defStyle) {
32 | super(context, attrs, defStyle);
33 | TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.StatusBarHeaderView, defStyle,
34 | R.style.Widget_FengMoe_StatusBarHeaderView);
35 | colorNormal = a.getColor(R.styleable.StatusBarHeaderView_colorNormal, Color.TRANSPARENT);
36 | if (a.hasValue(R.styleable.StatusBarHeaderView_colorDark)) {
37 | colorDark = a.getColor(R.styleable.StatusBarHeaderView_colorDark, Color.TRANSPARENT);
38 | } else {
39 | colorDark = ViewHelper.getMiddleColor(colorNormal, Color.BLACK, 0.2f);
40 | }
41 | enableMode = a.getInt(R.styleable.StatusBarHeaderView_enableMode, MODE_ALL);
42 | headerView = new StatusBarHeaderView(context, colorNormal, colorDark, enableMode);
43 | this.setBackgroundColorWithoutAlpha(colorNormal);
44 | this.setOrientation(LinearLayout.VERTICAL);
45 | this.addView(headerView);
46 | a.recycle();
47 | if (Build.VERSION.SDK_INT >= 21) {
48 | this.setElevation(ViewHelper.dpToPx(context, 5f));
49 | }
50 | }
51 |
52 | public void setNormalColor(@ColorInt int colorNormal) {
53 | this.colorNormal = colorNormal;
54 | this.setBackgroundColorWithoutAlpha(colorNormal);
55 | headerView.setNormalColor(colorNormal);
56 | headerView.init();
57 | }
58 |
59 | public void setDarkColor(@ColorInt int colorDark) {
60 | this.colorDark = colorDark;
61 | headerView.setDarkColor(colorDark);
62 | headerView.init();
63 | }
64 |
65 | public void setColor(@ColorInt int colorNormal,@ColorInt int colorDark) {
66 | this.colorNormal = colorNormal;
67 | this.colorDark = colorDark;
68 | this.setBackgroundColorWithoutAlpha(colorNormal);
69 | headerView.setNormalColor(colorNormal);
70 | headerView.setDarkColor(colorDark);
71 | headerView.init();
72 | }
73 |
74 | public void setColorResources(@ColorRes int colorNormal, @ColorRes int colorDark) {
75 | this.setColor(
76 | getResources().getColor(colorNormal),
77 | getResources().getColor(colorDark)
78 | );
79 | }
80 |
81 | public int getNormalColor() {
82 | return this.colorNormal;
83 | }
84 |
85 | public int getDarkColor(){
86 | return this.colorDark;
87 | }
88 |
89 | public void setMode(int mode) {
90 | this.enableMode = mode;
91 | headerView.setMode(mode);
92 | headerView.init();
93 | }
94 |
95 | public int getMode(){
96 | return this.enableMode;
97 | }
98 |
99 | private void setBackgroundColorWithoutAlpha(int color) {
100 | this.setBackgroundColor(Color.argb(255, Color.red(color), Color.green(color), Color.blue(color)));
101 | }
102 |
103 | }
104 |
--------------------------------------------------------------------------------
/app/src/main/java/me/undownding/baseui/MainActivity.java:
--------------------------------------------------------------------------------
1 | package me.undownding.baseui;
2 |
3 | import android.os.Build;
4 | import android.os.Bundle;
5 | import android.support.design.widget.FloatingActionButton;
6 | import android.support.v7.widget.LinearLayoutManager;
7 | import android.support.v7.widget.RecyclerView;
8 | import android.support.v7.widget.Toolbar;
9 | import android.view.Menu;
10 | import android.view.MenuItem;
11 | import android.view.View;
12 | import android.view.ViewGroup;
13 | import android.widget.TextView;
14 |
15 | import me.undownding.baseui.library.VeryBaseActivity;
16 | import moe.feng.material.statusbar.TranslucentSBActivity;
17 | import moe.feng.material.statusbar.util.ViewHelper;
18 |
19 | public class MainActivity extends VeryBaseActivity {
20 |
21 | @Override
22 | protected void onCreate(Bundle savedInstanceState) {
23 | super.onCreate(savedInstanceState);
24 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
25 | setSupportActionBar(toolbar);
26 |
27 | FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
28 | /*fab.setOnClickListener(new View.OnClickListener() {
29 | @Override
30 | public void onClick(View view) {
31 | Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
32 | .setAction("Action", null).show();
33 | }
34 | });*/
35 |
36 | RecyclerView recyclerView = (RecyclerView) getLayoutInflater().inflate(R.layout.view_recyclerview, null, false);
37 | recyclerView.setAdapter(new RecyclerView.Adapter
206 | * Calling code may decide to fling or otherwise release the view to let
207 | * it settle into place. It should do so using
208 | * {@link #settleCapturedViewAt(int, int)} or
209 | * {@link #flingCapturedView(int, int, int, int)}. If the Callback
210 | * invokes one of these methods, the ViewDragHelper will enter
211 | * {@link #STATE_SETTLING} and the view capture will not fully end until
212 | * it comes to a complete stop. If neither of these methods is invoked
213 | * before
313 | * ViewDragHelper may call this method multiple times for the same view
314 | * even if the view is already captured; this indicates that a new
315 | * pointer is trying to take control of the view.
316 | *
318 | * If this method returns true, a call to
319 | * {@link #onViewCaptured(android.view.View, int)} will follow if the
320 | * capture is successful.
321 | *
616 | * This operation does not count as a capture event, though
617 | * {@link #getCapturedView()} will still report the sliding view while the
618 | * slide is in progress.
619 | *
948 | * The state used to report this information is populated by the methods
949 | * {@link #shouldInterceptTouchEvent(android.view.MotionEvent)} or
950 | * {@link #processTouchEvent(android.view.MotionEvent)}. If one of these
951 | * methods has not been called for all relevant MotionEvents to track, the
952 | * information reported by this method may be stale or incorrect.
953 | *
1381 | * This depends on internal state populated by
1382 | * {@link #shouldInterceptTouchEvent(android.view.MotionEvent)} or
1383 | * {@link #processTouchEvent(android.view.MotionEvent)}. You should only
1384 | * rely on the results of this method after all currently available touch
1385 | * data has been provided to one of these two methods.
1386 | *
1407 | * This depends on internal state populated by
1408 | * {@link #shouldInterceptTouchEvent(android.view.MotionEvent)} or
1409 | * {@link #processTouchEvent(android.view.MotionEvent)}. You should only
1410 | * rely on the results of this method after all currently available touch
1411 | * data has been provided to one of these two methods.
1412 | * on*methods are invoked on
158 | * siginficant events and several accessor methods are expected to provide
159 | * the ViewDragHelper with more information about the state of the parent
160 | * view upon request. The callback also makes decisions governing the range
161 | * and draggability of child views.
162 | */
163 | public static abstract class Callback {
164 | /**
165 | * Called when the drag state changes. See the STATE_*
166 | * constants for more information.
167 | *
168 | * @param state The new drag state
169 | * @see #STATE_IDLE
170 | * @see #STATE_DRAGGING
171 | * @see #STATE_SETTLING
172 | */
173 | public void onViewDragStateChanged(int state) {
174 | }
175 |
176 | /**
177 | * Called when the captured view's position changes as the result of a
178 | * drag or settle.
179 | *
180 | * @param changedView View whose position changed
181 | * @param left New X coordinate of the left edge of the view
182 | * @param top New Y coordinate of the top edge of the view
183 | * @param dx Change in X position from the last call
184 | * @param dy Change in Y position from the last call
185 | */
186 | public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
187 | }
188 |
189 | /**
190 | * Called when a child view is captured for dragging or settling. The ID
191 | * of the pointer currently dragging the captured view is supplied. If
192 | * activePointerId is identified as {@link #INVALID_POINTER} the capture
193 | * is programmatic instead of pointer-initiated.
194 | *
195 | * @param capturedChild Child view that was captured
196 | * @param activePointerId Pointer id tracking the child capture
197 | */
198 | public void onViewCaptured(View capturedChild, int activePointerId) {
199 | }
200 |
201 | /**
202 | * Called when the child view is no longer being actively dragged. The
203 | * fling velocity is also supplied, if relevant. The velocity values may
204 | * be clamped to system minimums or maximums.
205 | * onViewReleased returns, the view will stop in
214 | * place and the ViewDragHelper will return to {@link #STATE_IDLE}.
215 | * index
278 | */
279 | public int getOrderedChildIndex(int index) {
280 | return index;
281 | }
282 |
283 | /**
284 | * Return the magnitude of a draggable child view's horizontal range of
285 | * motion in pixels. This method should return 0 for views that cannot
286 | * move horizontally.
287 | *
288 | * @param child Child view to check
289 | * @return range of horizontal motion in pixels
290 | */
291 | public int getViewHorizontalDragRange(View child) {
292 | return 0;
293 | }
294 |
295 | /**
296 | * Return the magnitude of a draggable child view's vertical range of
297 | * motion in pixels. This method should return 0 for views that cannot
298 | * move vertically.
299 | *
300 | * @param child Child view to check
301 | * @return range of vertical motion in pixels
302 | */
303 | public int getViewVerticalDragRange(View child) {
304 | return 0;
305 | }
306 |
307 | /**
308 | * Called when the user's input indicates that they want to capture the
309 | * given child view with the pointer indicated by pointerId. The
310 | * callback should return true if the user is permitted to drag the
311 | * given view with the indicated pointer.
312 | * child to the given (left, top) position. If
611 | * this method returns true, the caller should invoke
612 | * {@link #continueSettling(boolean)} on each subsequent frame to continue
613 | * the motion until it returns false. If this method returns false there is
614 | * no further work to do to complete the movement.
615 | * value
740 | */
741 | private int clampMag(int value, int absMin, int absMax) {
742 | final int absValue = Math.abs(value);
743 | if (absValue < absMin)
744 | return 0;
745 | if (absValue > absMax)
746 | return value > 0 ? absMax : -absMax;
747 | return value;
748 | }
749 |
750 | /**
751 | * Clamp the magnitude of value for absMin and absMax. If the value is below
752 | * the minimum, it will be clamped to zero. If the value is above the
753 | * maximum, it will be clamped to the maximum.
754 | *
755 | * @param value Value to clamp
756 | * @param absMin Absolute value of the minimum significant value to return
757 | * @param absMax Absolute value of the maximum value to return
758 | * @return The clamped value with the same sign as value
759 | */
760 | private float clampMag(float value, float absMin, float absMax) {
761 | final float absValue = Math.abs(value);
762 | if (absValue < absMin)
763 | return 0;
764 | if (absValue > absMax)
765 | return value > 0 ? absMax : -absMax;
766 | return value;
767 | }
768 |
769 | private float distanceInfluenceForSnapDuration(float f) {
770 | f -= 0.5f; // center the values about 0.
771 | f *= 0.3f * Math.PI / 2.0f;
772 | return (float) Math.sin(f);
773 | }
774 |
775 | /**
776 | * Settle the captured view based on standard free-moving fling behavior.
777 | * The caller should invoke {@link #continueSettling(boolean)} on each
778 | * subsequent frame to continue the motion until it returns false.
779 | *
780 | * @param minLeft Minimum X position for the view's left edge
781 | * @param minTop Minimum Y position for the view's top edge
782 | * @param maxLeft Maximum X position for the view's left edge
783 | * @param maxTop Maximum Y position for the view's top edge
784 | */
785 | public void flingCapturedView(int minLeft, int minTop, int maxLeft, int maxTop) {
786 | if (!mReleaseInProgress) {
787 | throw new IllegalStateException("Cannot flingCapturedView outside of a call to "
788 | + "Callback#onViewReleased");
789 | }
790 |
791 | mScroller.fling(mCapturedView.getLeft(), mCapturedView.getTop(),
792 | (int) VelocityTrackerCompat.getXVelocity(mVelocityTracker, mActivePointerId),
793 | (int) VelocityTrackerCompat.getYVelocity(mVelocityTracker, mActivePointerId),
794 | minLeft, maxLeft, minTop, maxTop);
795 |
796 | setDragState(STATE_SETTLING);
797 | }
798 |
799 | /**
800 | * Move the captured settling view by the appropriate amount for the current
801 | * time. If continueSettling returns true, the caller should
802 | * call it again on the next frame to continue.
803 | *
804 | * @param deferCallbacks true if state callbacks should be deferred via
805 | * posted message. Set this to true if you are calling this
806 | * method from {@link android.view.View#computeScroll()} or
807 | * similar methods invoked as part of layout or drawing.
808 | * @return true if settle is still in progress
809 | */
810 | public boolean continueSettling(boolean deferCallbacks) {
811 | if (mDragState == STATE_SETTLING) {
812 | boolean keepGoing = mScroller.computeScrollOffset();
813 | final int x = mScroller.getCurrX();
814 | final int y = mScroller.getCurrY();
815 | final int dx = x - mCapturedView.getLeft();
816 | final int dy = y - mCapturedView.getTop();
817 |
818 | if (dx != 0) {
819 | mCapturedView.offsetLeftAndRight(dx);
820 | }
821 | if (dy != 0) {
822 | mCapturedView.offsetTopAndBottom(dy);
823 | }
824 |
825 | if (dx != 0 || dy != 0) {
826 | mCallback.onViewPositionChanged(mCapturedView, x, y, dx, dy);
827 | }
828 |
829 | if (keepGoing && x == mScroller.getFinalX() && y == mScroller.getFinalY()) {
830 | // Close enough. The interpolator/scroller might think we're
831 | // still moving
832 | // but the user sure doesn't.
833 | mScroller.abortAnimation();
834 | keepGoing = mScroller.isFinished();
835 | }
836 |
837 | if (!keepGoing) {
838 | if (deferCallbacks) {
839 | mParentView.post(mSetIdleRunnable);
840 | } else {
841 | setDragState(STATE_IDLE);
842 | }
843 | }
844 | }
845 |
846 | return mDragState == STATE_SETTLING;
847 | }
848 |
849 | /**
850 | * Like all callback events this must happen on the UI thread, but release
851 | * involves some extra semantics. During a release (mReleaseInProgress) is
852 | * the only time it is valid to call {@link #settleCapturedViewAt(int, int)}
853 | * or {@link #flingCapturedView(int, int, int, int)}.
854 | */
855 | private void dispatchViewReleased(float xvel, float yvel) {
856 | mReleaseInProgress = true;
857 | mCallback.onViewReleased(mCapturedView, xvel, yvel);
858 | mReleaseInProgress = false;
859 |
860 | if (mDragState == STATE_DRAGGING) {
861 | // onViewReleased didn't call a method that would have changed this.
862 | // Go idle.
863 | setDragState(STATE_IDLE);
864 | }
865 | }
866 |
867 | private void clearMotionHistory() {
868 | if (mInitialMotionX == null) {
869 | return;
870 | }
871 | Arrays.fill(mInitialMotionX, 0);
872 | Arrays.fill(mInitialMotionY, 0);
873 | Arrays.fill(mLastMotionX, 0);
874 | Arrays.fill(mLastMotionY, 0);
875 | Arrays.fill(mInitialEdgeTouched, 0);
876 | Arrays.fill(mEdgeDragsInProgress, 0);
877 | Arrays.fill(mEdgeDragsLocked, 0);
878 | mPointersDown = 0;
879 | }
880 |
881 | private void clearMotionHistory(int pointerId) {
882 | if (mInitialMotionX == null) {
883 | return;
884 | }
885 | mInitialMotionX[pointerId] = 0;
886 | mInitialMotionY[pointerId] = 0;
887 | mLastMotionX[pointerId] = 0;
888 | mLastMotionY[pointerId] = 0;
889 | mInitialEdgeTouched[pointerId] = 0;
890 | mEdgeDragsInProgress[pointerId] = 0;
891 | mEdgeDragsLocked[pointerId] = 0;
892 | mPointersDown &= ~(1 << pointerId);
893 | }
894 |
895 | private void ensureMotionHistorySizeForId(int pointerId) {
896 | if (mInitialMotionX == null || mInitialMotionX.length <= pointerId) {
897 | float[] imx = new float[pointerId + 1];
898 | float[] imy = new float[pointerId + 1];
899 | float[] lmx = new float[pointerId + 1];
900 | float[] lmy = new float[pointerId + 1];
901 | int[] iit = new int[pointerId + 1];
902 | int[] edip = new int[pointerId + 1];
903 | int[] edl = new int[pointerId + 1];
904 |
905 | if (mInitialMotionX != null) {
906 | System.arraycopy(mInitialMotionX, 0, imx, 0, mInitialMotionX.length);
907 | System.arraycopy(mInitialMotionY, 0, imy, 0, mInitialMotionY.length);
908 | System.arraycopy(mLastMotionX, 0, lmx, 0, mLastMotionX.length);
909 | System.arraycopy(mLastMotionY, 0, lmy, 0, mLastMotionY.length);
910 | System.arraycopy(mInitialEdgeTouched, 0, iit, 0, mInitialEdgeTouched.length);
911 | System.arraycopy(mEdgeDragsInProgress, 0, edip, 0, mEdgeDragsInProgress.length);
912 | System.arraycopy(mEdgeDragsLocked, 0, edl, 0, mEdgeDragsLocked.length);
913 | }
914 |
915 | mInitialMotionX = imx;
916 | mInitialMotionY = imy;
917 | mLastMotionX = lmx;
918 | mLastMotionY = lmy;
919 | mInitialEdgeTouched = iit;
920 | mEdgeDragsInProgress = edip;
921 | mEdgeDragsLocked = edl;
922 | }
923 | }
924 |
925 | private void saveInitialMotion(float x, float y, int pointerId) {
926 | ensureMotionHistorySizeForId(pointerId);
927 | mInitialMotionX[pointerId] = mLastMotionX[pointerId] = x;
928 | mInitialMotionY[pointerId] = mLastMotionY[pointerId] = y;
929 | mInitialEdgeTouched[pointerId] = getEdgeTouched((int) x, (int) y);
930 | mPointersDown |= 1 << pointerId;
931 | }
932 |
933 | private void saveLastMotion(MotionEvent ev) {
934 | final int pointerCount = MotionEventCompat.getPointerCount(ev);
935 | for (int i = 0; i < pointerCount; i++) {
936 | final int pointerId = MotionEventCompat.getPointerId(ev, i);
937 | final float x = MotionEventCompat.getX(ev, i);
938 | final float y = MotionEventCompat.getY(ev, i);
939 | mLastMotionX[pointerId] = x;
940 | mLastMotionY[pointerId] = y;
941 | }
942 | }
943 |
944 | /**
945 | * Check if the given pointer ID represents a pointer that is currently down
946 | * (to the best of the ViewDragHelper's knowledge).
947 | *