├── Drawer
├── .gitignore
├── .idea
│ ├── .name
│ ├── codeStyleSettings.xml
│ ├── compiler.xml
│ ├── copyright
│ │ └── profiles_settings.xml
│ ├── encodings.xml
│ ├── gradle.xml
│ ├── misc.xml
│ ├── modules.xml
│ ├── runConfigurations.xml
│ └── vcs.xml
├── Drawer.iml
├── app
│ ├── .gitignore
│ ├── app.iml
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src
│ │ ├── androidTest
│ │ └── java
│ │ │ └── com
│ │ │ └── example
│ │ │ └── lenovo
│ │ │ └── drawer
│ │ │ └── ApplicationTest.java
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── lenovo
│ │ │ └── drawer
│ │ │ ├── CustomAnimatorListener.java
│ │ │ ├── MainActivity.java
│ │ │ └── VerticalDrawerActivity.java
│ │ └── res
│ │ ├── drawable-xhdpi
│ │ ├── guide_drawer_btn_call.png
│ │ ├── guide_drawer_btn_find.png
│ │ ├── guide_drawer_btn_snapshot.png
│ │ ├── guide_drawer_content.9.png
│ │ ├── guide_drawer_handler.9.png
│ │ ├── guide_drawer_handler_arrow_close.png
│ │ ├── guide_drawer_handler_arrow_open.png
│ │ └── ic_launcher.png
│ │ ├── layout
│ │ ├── activity_drawer.xml
│ │ └── activity_verticaldrawer.xml
│ │ ├── menu
│ │ └── menu_main.xml
│ │ ├── mipmap-hdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-mdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxhdpi
│ │ └── ic_launcher.png
│ │ ├── values-w820dp
│ │ └── dimens.xml
│ │ └── values
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
├── build.gradle
├── drawerlibrary
│ ├── .gitignore
│ ├── build.gradle
│ ├── drawerlibrary.iml
│ ├── libs
│ │ └── nineoldandroids.jar
│ ├── proguard-rules.pro
│ └── src
│ │ ├── androidTest
│ │ └── java
│ │ │ └── com
│ │ │ └── example
│ │ │ └── lenovo
│ │ │ └── drawerlibrary
│ │ │ └── ApplicationTest.java
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── lenovo
│ │ │ └── drawerlibrary
│ │ │ ├── Drawer.java
│ │ │ └── DrawerLayout.java
│ │ └── res
│ │ ├── menu
│ │ └── menu_main.xml
│ │ ├── values-w820dp
│ │ └── dimens.xml
│ │ └── values
│ │ ├── dimens.xml
│ │ ├── drawer_attrs.xml
│ │ ├── drawerlayout_attrs.xml
│ │ └── strings.xml
├── gradle.properties
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── screen capture
│ ├── GIF.gif
│ ├── bottom_drawer.gif
│ └── device-2015-08-18-123035.png
└── settings.gradle
└── README.md
/Drawer/.gitignore:
--------------------------------------------------------------------------------
1 | .gradle
2 | /local.properties
3 | /.idea/workspace.xml
4 | /.idea/libraries
5 | .DS_Store
6 | /build
7 | /captures
8 |
--------------------------------------------------------------------------------
/Drawer/.idea/.name:
--------------------------------------------------------------------------------
1 | Drawer
--------------------------------------------------------------------------------
/Drawer/.idea/codeStyleSettings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
229 |
230 |
231 |
--------------------------------------------------------------------------------
/Drawer/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/Drawer/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/Drawer/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Drawer/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/Drawer/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/Drawer/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/Drawer/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/Drawer/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Drawer/Drawer.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/Drawer/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/Drawer/app/app.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | generateDebugAndroidTestSources
19 | generateDebugSources
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
--------------------------------------------------------------------------------
/Drawer/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 22
5 | buildToolsVersion "22.0.1"
6 |
7 | defaultConfig {
8 | applicationId "com.example.lenovo.drawer"
9 | minSdkVersion 10
10 | targetSdkVersion 22
11 | versionCode 1
12 | versionName "1.0"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | compile fileTree(dir: 'libs', include: ['*.jar'])
24 | compile 'com.android.support:appcompat-v7:22.2.1'
25 | compile project(':drawerlibrary')
26 | }
27 |
--------------------------------------------------------------------------------
/Drawer/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in D:\developtools\android sdk windows/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/Drawer/app/src/androidTest/java/com/example/lenovo/drawer/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.example.lenovo.drawer;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/Drawer/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
10 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Drawer/app/src/main/java/com/example/lenovo/drawer/CustomAnimatorListener.java:
--------------------------------------------------------------------------------
1 | package com.example.lenovo.drawer;
2 |
3 |
4 | import com.nineoldandroids.animation.Animator;
5 |
6 |
7 | /**
8 | * Created by Panda Guo on 2015/11/6.
9 | *
10 | * Common Animator Listener, you need not to implement the four full animation
11 | * function. For example: ****.setListener(new CustomAnimatorListener() {
12 | *
13 | * @Override public void onAnimationEnd(Animator animator) { })
14 | *
15 | *
16 | *
17 | */
18 | public class CustomAnimatorListener implements Animator.AnimatorListener
19 | {
20 | @Override
21 | public void onAnimationStart(Animator animator)
22 | {
23 |
24 | }
25 |
26 | @Override
27 | public void onAnimationEnd(Animator animator)
28 | {
29 |
30 | }
31 |
32 | @Override
33 | public void onAnimationCancel(Animator animator)
34 | {
35 |
36 | }
37 |
38 | @Override
39 | public void onAnimationRepeat(Animator animator)
40 | {
41 |
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Drawer/app/src/main/java/com/example/lenovo/drawer/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.lenovo.drawer;
2 |
3 |
4 | import android.content.Intent;
5 | import android.os.Bundle;
6 | import android.support.v7.app.AppCompatActivity;
7 | import android.view.View;
8 |
9 |
10 | public class MainActivity extends AppCompatActivity
11 | {
12 |
13 | @Override
14 | protected void onCreate(Bundle savedInstanceState)
15 | {
16 | super.onCreate(savedInstanceState);
17 | setContentView(R.layout.activity_drawer);
18 |
19 | findViewById(R.id.guide_call_layout).setOnClickListener(
20 | new View.OnClickListener()
21 | {
22 | @Override
23 | public void onClick(View v)
24 | {
25 | startActivity(new Intent(MainActivity.this,
26 | VerticalDrawerActivity.class));
27 | }
28 | });
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/Drawer/app/src/main/java/com/example/lenovo/drawer/VerticalDrawerActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.lenovo.drawer;
2 |
3 |
4 | import java.util.ArrayList;
5 | import java.util.List;
6 |
7 | import android.os.Bundle;
8 | import android.support.v7.app.AppCompatActivity;
9 | import android.util.Log;
10 | import android.view.View;
11 | import android.view.animation.AccelerateInterpolator;
12 | import android.view.animation.DecelerateInterpolator;
13 | import android.widget.AdapterView;
14 | import android.widget.ArrayAdapter;
15 | import android.widget.Button;
16 | import android.widget.LinearLayout;
17 | import android.widget.ListView;
18 | import android.widget.Toast;
19 |
20 | import com.example.lenovo.drawerlibrary.DrawerLayout;
21 | import com.nineoldandroids.animation.Animator;
22 | import com.nineoldandroids.view.ViewHelper;
23 | import com.nineoldandroids.view.ViewPropertyAnimator;
24 |
25 |
26 | /**
27 | * Created by 郭攀峰 on 2015/10/31.
28 | */
29 | public class VerticalDrawerActivity extends AppCompatActivity
30 | {
31 |
32 | private static final String tag = VerticalDrawerActivity.class.getSimpleName();
33 |
34 | private DrawerLayout mDrawerLayout;
35 | private LinearLayout mNumberLayout;
36 | private LinearLayout mDrawerContent;
37 | private int mTranslationY = 0;
38 | private boolean isOpened = false;
39 | private boolean isClosed = false;
40 |
41 | @Override
42 | protected void onCreate(Bundle savedInstanceState)
43 | {
44 | super.onCreate(savedInstanceState);
45 | Log.d(tag, "activity onCreate function");
46 |
47 | setContentView(R.layout.activity_verticaldrawer);
48 |
49 | findViewById(R.id.click).setOnClickListener(new View.OnClickListener()
50 | {
51 | @Override
52 | public void onClick(View v)
53 | {
54 | Toast.makeText(VerticalDrawerActivity.this, "clicked", Toast.LENGTH_SHORT)
55 | .show();
56 | }
57 | });
58 |
59 | mNumberLayout = (LinearLayout) findViewById(R.id.number_layout);
60 |
61 | mDrawerContent = (LinearLayout) findViewById(R.id.drawerContent);
62 | mDrawerContent.setOnClickListener(new View.OnClickListener()
63 | {
64 | @Override
65 | public void onClick(View v)
66 | {
67 | Log.d(tag, "drawer content click");
68 | }
69 | });
70 | Button mDelBtn = (Button) findViewById(R.id.del_click);
71 | mDelBtn.setOnClickListener(new View.OnClickListener()
72 | {
73 | @Override
74 | public void onClick(View v)
75 | {
76 | Log.d(tag, "clicked delete button");
77 | }
78 | });
79 |
80 | fillListView((ListView) findViewById(R.id.list_view));
81 |
82 | mDrawerLayout = (DrawerLayout) findViewById(R.id.dial_drawer);
83 | mDrawerLayout.setInitialState(DrawerLayout.State.Open); //set drawer initial state: open or close
84 | mDrawerLayout.setDrawerListener(new DrawerLayout.DrawerListener()
85 | {
86 | @Override
87 | public void drawerOpened()
88 | {
89 | if (!isOpened)
90 | showNumberView();
91 | }
92 |
93 | @Override
94 | public void drawerClosed()
95 | {
96 | if (!isClosed)
97 | hideNumberView();
98 | }
99 | });
100 | }
101 |
102 | private void fillListView(ListView view)
103 | {
104 | List list = new ArrayList(100);
105 | for (int i = 0; i < 100; i++)
106 | {
107 | list.add("Item " + i);
108 | }
109 |
110 | ArrayAdapter adapter = new ArrayAdapter(this,
111 | android.R.layout.simple_list_item_1, list);
112 | view.setAdapter(adapter);
113 |
114 | view.setOnItemClickListener(new AdapterView.OnItemClickListener()
115 | {
116 | @Override
117 | public void onItemClick(AdapterView> parent, View view, int position,
118 | long id)
119 | {
120 | Log.d(tag, "ListView item clicked");
121 | }
122 | });
123 | }
124 |
125 | private void showNumberView()
126 | {
127 | ViewHelper.setAlpha(mNumberLayout, 0);
128 | ViewHelper.setTranslationY(mNumberLayout,
129 | mTranslationY - mNumberLayout.getHeight());
130 | ViewPropertyAnimator.animate(mNumberLayout).alpha(1f).translationY(mTranslationY)
131 | .setInterpolator(new DecelerateInterpolator()).setDuration(300)
132 | .setStartDelay(0).setListener(new CustomAnimatorListener()
133 | {
134 | @Override
135 | public void onAnimationEnd(Animator animator)
136 | {
137 | isOpened = true;
138 | isClosed = false;
139 | }
140 | }).start();
141 | }
142 |
143 | private void hideNumberView()
144 | {
145 | ViewPropertyAnimator.animate(mNumberLayout).alpha(0f)
146 | .translationY(-mNumberLayout.getHeight() + mTranslationY)
147 | .setInterpolator(new AccelerateInterpolator()).setDuration(300)
148 | .setListener(new CustomAnimatorListener()
149 | {
150 | @Override
151 | public void onAnimationEnd(Animator animator)
152 | {
153 | isOpened = false;
154 | isClosed = true;
155 | }
156 | }).start();
157 |
158 | }
159 | }
160 |
--------------------------------------------------------------------------------
/Drawer/app/src/main/res/drawable-xhdpi/guide_drawer_btn_call.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gpfduoduo/DrawerOnCorner/cdd4c58295c09ac4dae874ff619a6e8a6e12c3a4/Drawer/app/src/main/res/drawable-xhdpi/guide_drawer_btn_call.png
--------------------------------------------------------------------------------
/Drawer/app/src/main/res/drawable-xhdpi/guide_drawer_btn_find.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gpfduoduo/DrawerOnCorner/cdd4c58295c09ac4dae874ff619a6e8a6e12c3a4/Drawer/app/src/main/res/drawable-xhdpi/guide_drawer_btn_find.png
--------------------------------------------------------------------------------
/Drawer/app/src/main/res/drawable-xhdpi/guide_drawer_btn_snapshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gpfduoduo/DrawerOnCorner/cdd4c58295c09ac4dae874ff619a6e8a6e12c3a4/Drawer/app/src/main/res/drawable-xhdpi/guide_drawer_btn_snapshot.png
--------------------------------------------------------------------------------
/Drawer/app/src/main/res/drawable-xhdpi/guide_drawer_content.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gpfduoduo/DrawerOnCorner/cdd4c58295c09ac4dae874ff619a6e8a6e12c3a4/Drawer/app/src/main/res/drawable-xhdpi/guide_drawer_content.9.png
--------------------------------------------------------------------------------
/Drawer/app/src/main/res/drawable-xhdpi/guide_drawer_handler.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gpfduoduo/DrawerOnCorner/cdd4c58295c09ac4dae874ff619a6e8a6e12c3a4/Drawer/app/src/main/res/drawable-xhdpi/guide_drawer_handler.9.png
--------------------------------------------------------------------------------
/Drawer/app/src/main/res/drawable-xhdpi/guide_drawer_handler_arrow_close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gpfduoduo/DrawerOnCorner/cdd4c58295c09ac4dae874ff619a6e8a6e12c3a4/Drawer/app/src/main/res/drawable-xhdpi/guide_drawer_handler_arrow_close.png
--------------------------------------------------------------------------------
/Drawer/app/src/main/res/drawable-xhdpi/guide_drawer_handler_arrow_open.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gpfduoduo/DrawerOnCorner/cdd4c58295c09ac4dae874ff619a6e8a6e12c3a4/Drawer/app/src/main/res/drawable-xhdpi/guide_drawer_handler_arrow_open.png
--------------------------------------------------------------------------------
/Drawer/app/src/main/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gpfduoduo/DrawerOnCorner/cdd4c58295c09ac4dae874ff619a6e8a6e12c3a4/Drawer/app/src/main/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Drawer/app/src/main/res/layout/activity_drawer.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
12 |
13 |
14 |
27 |
28 |
35 |
36 |
42 |
43 |
49 |
50 |
55 |
56 |
57 |
58 |
63 |
64 |
71 |
72 |
78 |
79 |
80 |
84 |
85 |
92 |
93 |
99 |
100 |
101 |
105 |
106 |
113 |
114 |
120 |
121 |
122 |
123 |
124 |
--------------------------------------------------------------------------------
/Drawer/app/src/main/res/layout/activity_verticaldrawer.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
18 |
19 |
23 |
24 |
29 |
30 |
31 |
35 |
36 |
41 |
42 |
49 |
50 |
58 |
59 |
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/Drawer/app/src/main/res/menu/menu_main.xml:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/Drawer/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gpfduoduo/DrawerOnCorner/cdd4c58295c09ac4dae874ff619a6e8a6e12c3a4/Drawer/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Drawer/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gpfduoduo/DrawerOnCorner/cdd4c58295c09ac4dae874ff619a6e8a6e12c3a4/Drawer/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Drawer/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gpfduoduo/DrawerOnCorner/cdd4c58295c09ac4dae874ff619a6e8a6e12c3a4/Drawer/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Drawer/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/Drawer/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/Drawer/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Drawer
3 |
4 | Hello world!
5 | Settings
6 |
7 |
--------------------------------------------------------------------------------
/Drawer/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Drawer/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:1.2.3'
9 |
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | jcenter()
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Drawer/drawerlibrary/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/Drawer/drawerlibrary/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 22
5 | buildToolsVersion "22.0.1"
6 |
7 | defaultConfig {
8 | minSdkVersion 10
9 | targetSdkVersion 22
10 | versionCode 1
11 | versionName "1.0"
12 | }
13 | buildTypes {
14 | release {
15 | minifyEnabled false
16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
17 | }
18 | }
19 | }
20 |
21 | dependencies {
22 | compile fileTree(dir: 'libs', include: ['*.jar'])
23 | compile 'com.android.support:appcompat-v7:22.2.1'
24 | compile files('libs/nineoldandroids.jar')
25 | }
26 |
--------------------------------------------------------------------------------
/Drawer/drawerlibrary/drawerlibrary.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | generateDebugAndroidTestSources
19 | generateDebugSources
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
--------------------------------------------------------------------------------
/Drawer/drawerlibrary/libs/nineoldandroids.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gpfduoduo/DrawerOnCorner/cdd4c58295c09ac4dae874ff619a6e8a6e12c3a4/Drawer/drawerlibrary/libs/nineoldandroids.jar
--------------------------------------------------------------------------------
/Drawer/drawerlibrary/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in D:\developtools\android sdk windows/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/Drawer/drawerlibrary/src/androidTest/java/com/example/lenovo/drawerlibrary/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.example.lenovo.drawerlibrary;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/Drawer/drawerlibrary/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/Drawer/drawerlibrary/src/main/java/com/example/lenovo/drawerlibrary/Drawer.java:
--------------------------------------------------------------------------------
1 | package com.example.lenovo.drawerlibrary;
2 |
3 | import android.content.Context;
4 | import android.content.res.TypedArray;
5 | import android.graphics.Canvas;
6 | import android.os.Vibrator;
7 | import android.support.annotation.NonNull;
8 | import android.util.AttributeSet;
9 | import android.view.MotionEvent;
10 | import android.view.View;
11 | import android.view.animation.AccelerateDecelerateInterpolator;
12 | import android.view.animation.AccelerateInterpolator;
13 | import android.widget.LinearLayout;
14 |
15 | import com.nineoldandroids.animation.Animator;
16 | import com.nineoldandroids.animation.AnimatorListenerAdapter;
17 | import com.nineoldandroids.animation.AnimatorSet;
18 | import com.nineoldandroids.animation.ObjectAnimator;
19 | import com.nineoldandroids.animation.ValueAnimator;
20 | import com.nineoldandroids.animation.ValueAnimator.AnimatorUpdateListener;
21 |
22 | import java.util.ArrayList;
23 | import java.util.List;
24 |
25 | /**
26 | * @author 作者 郭攀峰 10129302
27 | * 可以放置在左侧或者右侧的Drawer抽屉
28 | */
29 | public class Drawer extends LinearLayout {
30 |
31 | private final static int ANIMATION_DURATION = 300;
32 | private static final int TAG_OPEN = 1;
33 | private static final int TAG_CLOSE = -1;
34 | /**
35 | * 抽屉的位置
36 | */
37 | private int mPosition;
38 | /**
39 | * 抽屉把手的view的id
40 | */
41 | private int mHandleId;
42 | /**
43 | * 抽屉内容view的id
44 | */
45 | private int mContentId;
46 |
47 | private int mCloseHandleId;
48 |
49 | /**
50 | * 抽屉中的把手
51 | */
52 | private View mHandle;
53 | /**
54 | * 打开时的抽屉按钮背景
55 | */
56 | private int mOpenedBackground;
57 | /**
58 | * 关闭是的抽屉按钮背景
59 | */
60 | private int mClosedBackground;
61 | /**
62 | * 抽屉的内容
63 | */
64 | private View mContent;
65 |
66 | private float mTrackX;
67 | /**
68 | * 抽屉的位置
69 | */
70 | private static final int LEFT = 2;
71 | private static final int RIGHT = 3;
72 |
73 | private int openWidth;
74 | private int closeWidth;
75 |
76 | private enum State {
77 | READY, CLICK, END
78 | }
79 | /**
80 | * 抽屉状态
81 | */
82 | private State mState;
83 |
84 | /**
85 | * 抽屉内容View的宽度
86 | */
87 | private int mContentWidth;
88 |
89 | private ValueAnimator animWidth, animatorTrackAnimator;
90 |
91 | private ViewWrapper wrapper;
92 |
93 | private AnimatorSet animatorSet = new AnimatorSet();
94 | private List animators = new ArrayList<>();
95 |
96 |
97 | public Drawer(Context context, AttributeSet attrs) {
98 | super(context, attrs);
99 |
100 | TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Drawer);
101 | mPosition = a.getInteger(R.styleable.Drawer_drawer_position, LEFT);
102 |
103 | RuntimeException e = null;
104 | mHandleId = a.getResourceId(R.styleable.Drawer_drawer_handle, -1);
105 | if (mHandleId == -1) {
106 | e = new IllegalArgumentException(a.getPositionDescription()
107 | + ": 抽屉把手必须制定一个子View");
108 | }
109 | mContentId = a.getResourceId(R.styleable.Drawer_drawer_content, -1);
110 | if (mContentId == -1) {
111 | e = new IllegalArgumentException(a.getPositionDescription()
112 | + ": 抽屉内容必须制定一个子View");
113 | }
114 | mCloseHandleId = a.getResourceId(R.styleable.Drawer_drawer_closeHandle, -1);
115 | mOpenedBackground = a.getResourceId(R.styleable.Drawer_drawer_openedBackground, -1);
116 | mClosedBackground = a.getResourceId(R.styleable.Drawer_drawer_closedBackground, -1);
117 |
118 | openWidth = a.getDimensionPixelOffset(R.styleable.Drawer_drawer_handle_openWidth,
119 | dip2px(context, 65));
120 | closeWidth = a.getDimensionPixelOffset(R.styleable.Drawer_drawer_handle_closeWidth,
121 | dip2px(context, 30));
122 |
123 | a.recycle(); // 不能忘记
124 |
125 | if (e != null) {
126 | throw e;
127 | }
128 |
129 | setOrientation(HORIZONTAL);
130 | mState = State.READY;
131 |
132 | setBaselineAligned(false);
133 | }
134 |
135 | /**
136 | * 设置抽屉的位置
137 | * @param position
138 | */
139 | public void setPosition(int position) {
140 | mPosition = position;
141 | setOrientation(HORIZONTAL);
142 |
143 | removeView(mHandle);
144 | removeView(mContent);
145 |
146 | if (mPosition == LEFT) {
147 | addView(mContent);
148 | addView(mHandle);
149 | } else {
150 | addView(mHandle);
151 | addView(mContent);
152 | }
153 | }
154 |
155 | @Override
156 | protected void onFinishInflate() {
157 | super.onFinishInflate();
158 | mHandle = findViewById(mHandleId);
159 | if (mHandle == null) {
160 | String name = getResources().getResourceEntryName(mHandleId);
161 | throw new RuntimeException("xml中需要添加属性:" + name);
162 | }
163 | mHandle.setClickable(true);
164 | mHandle.setOnClickListener(onClickListener);
165 | mHandle.setOnTouchListener(onTouchListener);
166 |
167 | View mCloseHandle = findViewById(mCloseHandleId);
168 | if (mCloseHandle != null) {
169 | mCloseHandle.setClickable(true);
170 | mCloseHandle.setOnClickListener(onClickListener);
171 | }
172 |
173 | mContent = findViewById(mContentId);
174 | if (mContent == null) {
175 | String name = getResources().getResourceEntryName(mHandleId);
176 | throw new RuntimeException("xml中需要添加属性:" + name);
177 | }
178 |
179 | //重新布局子View
180 | removeView(mHandle);
181 | removeView(mContent);
182 | if (mPosition == LEFT) {
183 | addView(mContent);
184 | addView(mHandle);
185 | } else {
186 | addView(mHandle);
187 | addView(mContent);
188 | }
189 |
190 | if (mOpenedBackground != -1) {
191 | mHandle.setBackgroundResource(mOpenedBackground);
192 | mHandle.setTag(TAG_OPEN);
193 | }
194 |
195 | mContent.setClickable(true);
196 | mContent.setVisibility(GONE);
197 | }
198 |
199 | @Override
200 | protected void onLayout(boolean changed, int l, int t, int r, int b) {
201 | super.onLayout(changed, l, t, r, b);
202 | mContentWidth = mContent.getWidth();
203 |
204 | if (mContentWidth != 0 &&
205 | mState == State.CLICK &&
206 | mHandle.getTag().equals(TAG_OPEN)) {
207 | mHandle.setTag(TAG_CLOSE);
208 | openOrCloseDrawer(true);
209 | }
210 | }
211 |
212 | /**
213 | * 主要用来绘制子元素
214 | */
215 | @Override
216 | protected void dispatchDraw(@NonNull Canvas canvas) {
217 | if (mState == State.READY) {
218 | int delta = mContentWidth;
219 | if (mPosition == LEFT) {
220 | delta = -delta;
221 | }
222 | canvas.translate(delta, 0);
223 | } else if (mState == State.CLICK) {
224 | canvas.translate(mTrackX, 0);
225 | }
226 | super.dispatchDraw(canvas);
227 | }
228 |
229 | private OnClickListener onClickListener = new OnClickListener() {
230 | @Override
231 | public void onClick(View v) {
232 | if (mHandleId == v.getId()) {
233 | if (mContent.getVisibility() != VISIBLE) {
234 | mState = State.CLICK;
235 | mHandle.setTag(TAG_OPEN);
236 | mContent.setVisibility(View.VISIBLE);
237 | } else {
238 | if(mCloseHandleId == -1) {
239 | mState = State.CLICK;
240 | mHandle.setTag(TAG_CLOSE);
241 | openOrCloseDrawer(false);
242 | }
243 | }
244 | }
245 | if (mCloseHandleId != -1 && v.getId() == mCloseHandleId) {
246 | mState = State.CLICK;
247 | mHandle.setTag(TAG_CLOSE);
248 | openOrCloseDrawer(false);
249 | }
250 | }
251 | };
252 |
253 | private OnTouchListener onTouchListener = new OnTouchListener() {
254 | int lastX;
255 | int lastY;
256 | boolean isPressedDown = false;
257 | boolean isDragging = false;
258 |
259 | int initialX;
260 | int initialY;
261 |
262 | public boolean onTouch(View v, MotionEvent event) {
263 | int action = event.getAction();
264 | switch (action) {
265 | case MotionEvent.ACTION_DOWN:
266 | isPressedDown = true;
267 | v.postDelayed(new Runnable() {
268 | public void run() {
269 | if (isPressedDown) {
270 | Vibrator vib = (Vibrator) getContext()
271 | .getSystemService(Context.VIBRATOR_SERVICE);
272 | vib.vibrate(50);
273 | isDragging = true;
274 | }
275 | }
276 | }, 500);
277 |
278 | initialX = lastX = (int) event.getRawX();
279 | initialY = lastY = (int) event.getRawY();
280 | v.getParent().requestDisallowInterceptTouchEvent(true);
281 | break;
282 | case MotionEvent.ACTION_MOVE:
283 | if (!isDragging) {
284 | int x = (int) event.getRawX();
285 | int y = (int) event.getRawY();
286 |
287 | int deltaX = Math.abs(x - initialX);
288 | int deltaY = Math.abs(y - initialY);
289 |
290 | if ((deltaX > 8 || deltaY > 8) && isPressedDown) {
291 | isPressedDown = false;
292 | }
293 | } else {
294 | int dx = (int) event.getRawX() - lastX;
295 | int dy = (int) event.getRawY() - lastY;
296 |
297 | int left = ((LinearLayout) v.getParent()).getLeft() + dx;
298 | int top = ((LinearLayout) v.getParent()).getTop() + dy;
299 | int right = ((LinearLayout) v.getParent()).getRight() + dx;
300 | int bottom = ((LinearLayout) v.getParent()).getBottom() + dy;
301 |
302 | ((LinearLayout) v.getParent()).layout(left, top, right, bottom); //移动位置
303 |
304 | lastX = (int) event.getRawX();
305 | lastY = (int) event.getRawY();
306 | }
307 | break;
308 | case MotionEvent.ACTION_UP:
309 | if (!isPressedDown) {
310 | break;
311 | }
312 | if (!isDragging) {
313 | v.performClick();
314 | }
315 | isDragging = false;
316 | isPressedDown = false;
317 | break;
318 | }
319 |
320 | return true;
321 | }
322 | };
323 |
324 | private void openOrCloseDrawer(boolean open) {
325 | if (wrapper == null) {
326 | wrapper = new ViewWrapper(mHandle);
327 | }
328 |
329 | animators.clear();
330 | if (animatorSet.isRunning()) {
331 | animatorSet.end();
332 | }
333 |
334 | if (open) {
335 | if (mPosition == LEFT) {
336 | animatorTrackAnimator = ValueAnimator.ofInt(-mContentWidth, 0);
337 | } else if (mPosition == RIGHT) {
338 | animatorTrackAnimator = ValueAnimator.ofInt(mContentWidth, 0);
339 | }
340 | animatorTrackAnimator.addListener(new AnimatorListenerAdapter() {
341 | @Override
342 | public void onAnimationEnd(Animator animation) {
343 | mContent.setVisibility(View.VISIBLE);
344 | mHandle.setBackgroundResource(mClosedBackground);
345 | mHandle.setTag(TAG_OPEN);
346 | mState = State.END;
347 | }
348 | });
349 | animWidth = ObjectAnimator.ofInt(wrapper, "width", openWidth, closeWidth);
350 | } else {
351 | if (mPosition == LEFT) {
352 | animatorTrackAnimator = ValueAnimator.ofInt(0, -mContentWidth);
353 | } else if (mPosition == RIGHT) {
354 | animatorTrackAnimator = ValueAnimator.ofInt(0, mContentWidth);
355 | }
356 | animatorTrackAnimator.addListener(new AnimatorListenerAdapter() {
357 | @Override
358 | public void onAnimationEnd(Animator animation) {
359 | mContent.setVisibility(View.GONE);
360 | mHandle.setBackgroundResource(mOpenedBackground);
361 | mHandle.setTag(TAG_CLOSE);
362 | mState = State.END;
363 | }
364 | });
365 | animWidth = ObjectAnimator.ofInt(wrapper, "width", closeWidth, openWidth);
366 | }
367 |
368 | animWidth.setDuration(ANIMATION_DURATION);
369 | animWidth.setInterpolator(new AccelerateInterpolator());
370 |
371 | animatorTrackAnimator.setDuration(ANIMATION_DURATION);
372 | animatorTrackAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
373 | animatorTrackAnimator.addUpdateListener(new AnimatorUpdateListener() {
374 |
375 | @Override
376 | public void onAnimationUpdate(ValueAnimator animation) {
377 | mTrackX = (Integer) animatorTrackAnimator.getAnimatedValue();
378 | invalidate();
379 | }
380 | });
381 |
382 | animators.add(animWidth);
383 | animators.add(animatorTrackAnimator);
384 |
385 | animatorSet.playTogether(animators);
386 | animatorSet.start();
387 | }
388 |
389 | /**
390 | * 必须实现属性动画的get和set方法
391 | */
392 | private static class ViewWrapper {
393 | private View mTarget;
394 |
395 | public ViewWrapper(View target) {
396 | mTarget = target;
397 | }
398 |
399 | public int getWidth() {
400 | return mTarget.getLayoutParams().width;
401 | }
402 |
403 | public void setWidth(int width) {
404 | mTarget.getLayoutParams().width = width;
405 | mTarget.requestLayout();
406 | }
407 | }
408 |
409 | private int dip2px(Context ctx, float dipValue) {
410 | final float scale = ctx.getResources().getDisplayMetrics().density;
411 | return (int) (dipValue * scale + 0.5f);
412 | }
413 | }
414 |
--------------------------------------------------------------------------------
/Drawer/drawerlibrary/src/main/java/com/example/lenovo/drawerlibrary/DrawerLayout.java:
--------------------------------------------------------------------------------
1 | package com.example.lenovo.drawerlibrary;
2 |
3 |
4 | import android.content.Context;
5 | import android.content.res.TypedArray;
6 | import android.util.AttributeSet;
7 | import android.util.Log;
8 | import android.view.MotionEvent;
9 | import android.view.View;
10 | import android.view.ViewConfiguration;
11 | import android.view.animation.LinearInterpolator;
12 | import android.widget.RelativeLayout;
13 |
14 | import com.nineoldandroids.animation.Animator;
15 | import com.nineoldandroids.animation.AnimatorListenerAdapter;
16 | import com.nineoldandroids.animation.ValueAnimator;
17 |
18 |
19 | /**
20 | * Created by 10129302 郭攀峰 on 15-5-19.
21 | */
22 | public class DrawerLayout extends RelativeLayout
23 | {
24 |
25 | private static final String tag = DrawerLayout.class.getSimpleName();
26 |
27 | /**
28 | * 滚动显示和隐藏左侧布局时,手指滑动需要达到的速度。
29 | */
30 | public static final int SNAP_VELOCITY = 200;
31 |
32 | private final static int DEFAULT_DURATION = 250;
33 |
34 | private final static int MAX_CLICK_TIME = 300;
35 | private final static float MAX_CLICK_DISTANCE = 5;
36 |
37 | /**
38 | * 在被判定为滚动之前用户手指可以移动的最大值。
39 | */
40 | private int touchSlop;
41 |
42 | /**
43 | * 记录手指按下时的横坐标。
44 | */
45 | private float xDown;
46 |
47 | /**
48 | * 记录手指按下时的纵坐标。
49 | */
50 | private float yDown;
51 |
52 | /**
53 | * 记录手指移动时的横坐标。
54 | */
55 | private float yMove;
56 |
57 | private MarginLayoutParams drawerLayoutParams;
58 | private int mDrawerLayoutHandlerId;
59 | private View mDrawerLayoutHandler;
60 | private int mDrawerLayoutContentId;
61 | private View mDrawerLayoutContent;
62 | private int mDrawerLayoutId = -1;
63 | private View mDrawer;
64 |
65 | private boolean isDragging;
66 |
67 | private boolean isTouchingDrawer = false;
68 | private boolean isShowing = false;
69 | private long mPressStartTime;
70 |
71 | private boolean isFirstInit = false;
72 |
73 | private int initialState = State.Close;
74 |
75 | private DrawerListener mDrawerListener;
76 |
77 | public static interface State
78 | {
79 | public static final int Open = 0;
80 | public static final int Close = 1;
81 | }
82 |
83 | public interface DrawerListener
84 | {
85 | public void drawerOpened();
86 |
87 | public void drawerClosed();
88 | }
89 |
90 | public DrawerLayout(Context context)
91 | {
92 | super(context);
93 | init(context, null);
94 | }
95 |
96 | public DrawerLayout(Context context, AttributeSet attrs)
97 | {
98 | super(context, attrs);
99 | init(context, attrs);
100 | }
101 |
102 | public DrawerLayout(Context context, AttributeSet attrs, int defStyleAttr)
103 | {
104 | super(context, attrs, defStyleAttr);
105 | init(context, attrs);
106 | }
107 |
108 | public void setInitialState(int state)
109 | {
110 | initialState = state;
111 | }
112 |
113 | public void setDrawerListener(DrawerListener listener)
114 | {
115 | this.mDrawerListener = listener;
116 | }
117 |
118 | /**
119 | * 判断是打开还是关闭
120 | *
121 | * @return
122 | */
123 | public boolean isOpened()
124 | {
125 | return isShowing;
126 | }
127 |
128 | @Override
129 | protected void onLayout(boolean changed, int l, int t, int r, int b)
130 | {
131 | super.onLayout(changed, l, t, r, b);
132 |
133 | if (!isFirstInit)
134 | {
135 | for (int i = 0; i < getChildCount(); i++)
136 | {
137 | View view = getChildAt(i);
138 | if (view.equals(mDrawer))
139 | {
140 | Log.d(tag, "onLayout");
141 | drawerLayoutParams = (MarginLayoutParams) view.getLayoutParams();
142 | if (initialState == State.Close)
143 | {
144 | drawerLayoutParams.bottomMargin = -mDrawerLayoutContent
145 | .getMeasuredHeight();
146 | isShowing = false;
147 | }
148 | else
149 | {
150 | drawerLayoutParams.bottomMargin = 0;
151 | isShowing = true;
152 | }
153 |
154 | view.setLayoutParams(drawerLayoutParams);
155 | break;
156 | }
157 | }
158 | isFirstInit = true;
159 | }
160 | }
161 |
162 | @Override
163 | protected void onFinishInflate()
164 | {
165 | super.onFinishInflate();
166 | mDrawerLayoutHandler = findViewById(mDrawerLayoutHandlerId);
167 | mDrawerLayoutContent = findViewById(mDrawerLayoutContentId);
168 | mDrawer = findViewById(mDrawerLayoutId);
169 | }
170 |
171 | @Override
172 | public boolean dispatchTouchEvent(MotionEvent event)
173 | {
174 | boolean isConsumed = false;
175 | switch (event.getActionMasked())
176 | {
177 | case MotionEvent.ACTION_DOWN :
178 | isConsumed = processDown(event);
179 | break;
180 | case MotionEvent.ACTION_MOVE :
181 | processMove(event);
182 | break;
183 | case MotionEvent.ACTION_UP :
184 | processUp(event);
185 | break;
186 | }
187 |
188 | return isConsumed || super.dispatchTouchEvent(event);
189 | }
190 |
191 | @Override
192 | public boolean onInterceptTouchEvent(MotionEvent ev)
193 | {
194 | return isDragging;
195 | }
196 |
197 | private void init(Context context, AttributeSet attrs)
198 | {
199 | if (attrs != null)
200 | {
201 | TypedArray ta = context.obtainStyledAttributes(attrs,
202 | R.styleable.DrawerLayout);
203 | mDrawerLayoutId = ta.getResourceId(R.styleable.DrawerLayout_DrawerLayout_ID,
204 | -1);
205 | mDrawerLayoutHandlerId = ta.getResourceId(
206 | R.styleable.DrawerLayout_DrawerLayoutHandler_ID, -1);
207 | mDrawerLayoutContentId = ta.getResourceId(
208 | R.styleable.DrawerLayout_DrawerLayoutContent_ID, -1);
209 |
210 | if (mDrawerLayoutContentId == -1 || mDrawerLayoutHandlerId == -1
211 | || mDrawerLayoutId == -1)
212 | {
213 | throw new IllegalArgumentException("必须指定属性值");
214 | }
215 | ta.recycle();
216 | }
217 | touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
218 | }
219 |
220 | private boolean isViewHit(View view, int x, int y)
221 | {
222 | int[] viewLocation = new int[2];
223 | view.getLocationOnScreen(viewLocation);
224 | int[] parentLocation = new int[2];
225 | this.getLocationOnScreen(parentLocation);
226 |
227 | int screenX = parentLocation[0] + x;
228 | int screenY = parentLocation[1] + y;
229 |
230 | return screenX >= viewLocation[0] && screenX < viewLocation[0] + view.getWidth()
231 | && screenY >= viewLocation[1] && screenY < viewLocation[1] + view.getHeight();
232 | }
233 |
234 | private boolean processDown(MotionEvent event)
235 | {
236 | xDown = event.getX();
237 | yDown = event.getY();
238 |
239 | if (!isShowing && isViewHit(mDrawer, (int) xDown, (int) yDown))
240 | {
241 | isTouchingDrawer = true;
242 | return true;
243 | }
244 |
245 | //Drawer已经打开,
246 | if (isShowing)
247 | {
248 | //点击其他位置,关闭Drawer
249 | if (!isViewHit(mDrawer, (int) xDown, (int) yDown))
250 | {
251 | closeDrawer();
252 | }
253 | else
254 | {
255 | isTouchingDrawer = true;
256 | }
257 | }
258 |
259 | return false;
260 | }
261 |
262 | private void processMove(MotionEvent event)
263 | {
264 | if (!isTouchingDrawer)
265 | {
266 | return;
267 | }
268 |
269 | mPressStartTime = System.currentTimeMillis();
270 |
271 | yMove = event.getY();
272 | // 手指移动时,对比按下时的坐标,计算出移动的距离。
273 | int moveDistanceY = (int) (yMove - yDown);
274 |
275 | if (!isDragging && Math.abs(moveDistanceY) > touchSlop)
276 | {
277 | isDragging = true;
278 | }
279 |
280 | if (isDragging)
281 | {
282 | yDown = yMove;
283 | drawerLayoutParams.bottomMargin -= moveDistanceY;
284 |
285 | if (drawerLayoutParams.bottomMargin >= 0)
286 | {
287 | drawerLayoutParams.bottomMargin = 0;
288 | isShowing = true;
289 | mDrawerListener.drawerOpened();
290 | }
291 |
292 | if (drawerLayoutParams.bottomMargin < -mDrawerLayoutContent
293 | .getMeasuredHeight())
294 | {
295 | drawerLayoutParams.bottomMargin = -mDrawerLayoutContent
296 | .getMeasuredHeight();
297 | isShowing = false;
298 | mDrawerListener.drawerClosed();
299 | }
300 |
301 | mDrawer.setLayoutParams(drawerLayoutParams);
302 | }
303 | }
304 |
305 | private void processUp(MotionEvent event)
306 | {
307 | Log.d(tag, "process up isShowing = " + isShowing);
308 | if (!isTouchingDrawer)
309 | {
310 | return;
311 | }
312 | //long pressDuration = System.currentTimeMillis() - mPressStartTime;
313 |
314 | isTouchingDrawer = false;
315 |
316 | //相当于点击打开
317 | if (!isShowing /* && pressDuration < MAX_CLICK_TIME */
318 | && distance(xDown, yDown, event.getX(), event.getY()) < MAX_CLICK_DISTANCE)
319 | {
320 | openDrawer();
321 | return;
322 | }
323 |
324 | //相当于点击关闭
325 | if (isShowing
326 | && isViewHit(mDrawerLayoutHandler, (int) event.getX(), (int) event.getY())
327 | /* && pressDuration < MAX_CLICK_TIME */
328 | && distance(xDown, yDown, event.getX(), event.getY()) < MAX_CLICK_DISTANCE)
329 | {
330 | closeDrawer();
331 | return;
332 | }
333 |
334 | //无论打开还是关闭只要过半就关闭,反之打开
335 | if (drawerLayoutParams.bottomMargin <= -(mDrawerLayoutContent.getMeasuredHeight()) / 2)
336 | {
337 | isShowing = true;
338 | closeDrawer();
339 | }
340 | else
341 | {
342 | isShowing = false;
343 | openDrawer();
344 | }
345 |
346 | isDragging = false;
347 | }
348 |
349 | public void openDrawer()
350 | {
351 | Log.d(tag, "openDrawer");
352 |
353 | if (isShowing)
354 | return;
355 |
356 | ValueAnimator openAnimator = ValueAnimator.ofFloat(
357 | drawerLayoutParams.bottomMargin, 0).setDuration(DEFAULT_DURATION);
358 | openAnimator.setTarget(mDrawer);
359 | openAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener()
360 | {
361 | @Override
362 | public void onAnimationUpdate(ValueAnimator valueAnimator)
363 | {
364 | float value = (float) valueAnimator.getAnimatedValue();
365 | drawerLayoutParams.bottomMargin = (int) value;
366 | mDrawer.setLayoutParams(drawerLayoutParams);
367 | }
368 | });
369 | openAnimator.addListener(new AnimatorListenerAdapter()
370 | {
371 | @Override
372 | public void onAnimationEnd(Animator animation)
373 | {
374 | isShowing = true;
375 | Log.d(tag, "open drawer end isShowing = " + isShowing);
376 | mDrawerListener.drawerOpened();
377 | }
378 | });
379 | openAnimator.setInterpolator(new LinearInterpolator());
380 | openAnimator.start();
381 | }
382 |
383 | public void closeDrawer()
384 | {
385 | Log.d(tag, "closeDrawer function");
386 |
387 | if (!isShowing)
388 | return;
389 |
390 | ValueAnimator closeAnimator = ValueAnimator.ofFloat(
391 | drawerLayoutParams.bottomMargin, -mDrawerLayoutContent.getMeasuredHeight())
392 | .setDuration(DEFAULT_DURATION);
393 | closeAnimator.setTarget(mDrawer);
394 | closeAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener()
395 | {
396 | @Override
397 | public void onAnimationUpdate(ValueAnimator valueAnimator)
398 | {
399 | float value = (float) valueAnimator.getAnimatedValue();
400 | drawerLayoutParams.bottomMargin = (int) value;
401 | mDrawer.setLayoutParams(drawerLayoutParams);
402 | }
403 | });
404 | closeAnimator.addListener(new AnimatorListenerAdapter()
405 | {
406 | @Override
407 | public void onAnimationEnd(Animator animation)
408 | {
409 | isShowing = false;
410 | Log.d(tag, "close drawer end isShowing = " + isShowing);
411 | mDrawerListener.drawerClosed();
412 | }
413 | });
414 | closeAnimator.setInterpolator(new LinearInterpolator());
415 | closeAnimator.start();
416 | }
417 |
418 | private double distance(float x1, float y1, float x2, float y2)
419 | {
420 | float deltaX = x2 - x1;
421 | float deltaY = y2 - y1;
422 | return Math.sqrt(deltaX * deltaX + deltaY * deltaY);
423 | }
424 |
425 | }
426 |
--------------------------------------------------------------------------------
/Drawer/drawerlibrary/src/main/res/menu/menu_main.xml:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/Drawer/drawerlibrary/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/Drawer/drawerlibrary/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/Drawer/drawerlibrary/src/main/res/values/drawer_attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/Drawer/drawerlibrary/src/main/res/values/drawerlayout_attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Drawer/drawerlibrary/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | DrawerLibrary
3 |
4 | Hello world!
5 | Settings
6 |
7 |
--------------------------------------------------------------------------------
/Drawer/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/Drawer/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gpfduoduo/DrawerOnCorner/cdd4c58295c09ac4dae874ff619a6e8a6e12c3a4/Drawer/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/Drawer/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Tue Aug 18 00:14:36 CST 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-all.zip
7 |
--------------------------------------------------------------------------------
/Drawer/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/Drawer/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 |
--------------------------------------------------------------------------------
/Drawer/screen capture/GIF.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gpfduoduo/DrawerOnCorner/cdd4c58295c09ac4dae874ff619a6e8a6e12c3a4/Drawer/screen capture/GIF.gif
--------------------------------------------------------------------------------
/Drawer/screen capture/bottom_drawer.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gpfduoduo/DrawerOnCorner/cdd4c58295c09ac4dae874ff619a6e8a6e12c3a4/Drawer/screen capture/bottom_drawer.gif
--------------------------------------------------------------------------------
/Drawer/screen capture/device-2015-08-18-123035.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gpfduoduo/DrawerOnCorner/cdd4c58295c09ac4dae874ff619a6e8a6e12c3a4/Drawer/screen capture/device-2015-08-18-123035.png
--------------------------------------------------------------------------------
/Drawer/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':drawerlibrary'
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # DrawerOnCorner
2 | 一个简单的抽屉控件 a simple drawer widget
3 |
4 | 点击左下角的按钮,抽屉内容便滑动而出,再次点击缩回。
5 |
6 | ## 实现方法
7 | 1、本文所用的方法
8 | 重写dispatchDraw方法,并通过Canvas.translate函数平移画布实现控件的显示和隐藏,具体的最右边小View的大小通过修改LayoutPramater来实现。
9 | 2、其他实现方法
10 | 整体布局通过layout_margin中的leftMargin的数值变化来实现,最右边的view同上。
11 |
12 |
13 | ## 动态效果图
14 |
15 | ### Drawer
16 |
17 | 
18 |
19 | ### DrawerLayout
20 |
21 | 
22 |
23 | ## 具体的使用方法
24 |
25 | ### XML中使用
26 | 通过设置属性drawer获取一些参数和位置(left or right)
27 |
40 |
41 |
48 |
49 |
55 |
56 |
62 |
63 |
68 |
69 |
70 |
71 |
75 |
76 |
83 |
84 |
90 |
91 |
92 |
96 |
97 |
104 |
105 |
111 |
112 |
113 |
117 |
118 |
125 |
126 |
132 |
133 |
134 |
135 |
136 | ### 代码中也可以设置位置
137 | 通过setPosition(left or right)来实现位置的变化
138 |
139 | ## 需要注意的地方
140 | 代码中使用动画的时候采用了ObjectAnimator,必须实现set和get方法,否则对于一些机器可能出现carsh,这样用的话,如果你
141 | 使用了代码混淆,set和get方法可能会被去除,所以最好的方法是使用ValueAnimator,监听其变化过程,然后设置属性值。
142 |
--------------------------------------------------------------------------------