├── README.md
├── SlideToUnlockView
├── .gitignore
├── build.gradle
├── proguard-rules.pro
├── slidetounlockview.iml
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── qdong
│ │ └── slide_to_unlock_view
│ │ └── ApplicationTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── qdong
│ │ │ └── slide_to_unlock_view
│ │ │ ├── CustomSlideToUnlockView.java
│ │ │ └── DensityUtil.java
│ └── res
│ │ ├── drawable
│ │ └── shape_round_normal_green.xml
│ │ ├── layout
│ │ └── layout_view_slide_to_unlock.xml
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ └── icon_slide.png
│ │ └── values
│ │ ├── attrs.xml
│ │ └── strings.xml
│ └── test
│ └── java
│ └── com
│ └── qdong
│ └── slide_to_unlock_view
│ └── ExampleUnitTest.java
├── app-debug.apk
├── app
├── .gitignore
├── app.iml
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── qdong
│ │ └── slidetounlockdemo
│ │ └── ApplicationTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── qdong
│ │ │ └── slidetounlockdemo
│ │ │ └── MainActivity.java
│ └── res
│ │ ├── drawable
│ │ └── shape_round_normal_green.xml
│ │ ├── layout
│ │ └── activity_main.xml
│ │ ├── mipmap-hdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-mdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ └── icon_slide.png
│ │ ├── mipmap-xxhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxxhdpi
│ │ └── ic_launcher.png
│ │ ├── values-w820dp
│ │ └── dimens.xml
│ │ └── values
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── qdong
│ └── slidetounlockdemo
│ └── ExampleUnitTest.java
├── build.gradle
├── demo.gif
└── gradle
└── wrapper
├── gradle-wrapper.jar
└── gradle-wrapper.properties
/README.md:
--------------------------------------------------------------------------------
1 | # AndroidCustomSlideToUnlockView
2 | ## 安卓自定义滑动解锁控件
3 |
4 | ### 添加依赖:
5 | dependencies {
6 | // your dependencies ...
7 | compile 'com.linklink.views:slide_to_unlock_view:1.0.0'
8 | }
9 |
10 | ### 效果图:
11 |
12 | 
13 |
14 | ## 可以自定义的属性:
15 | >>name="slideImageViewWidth" format="dimension" //滑块宽度
16 | >>name="slideImageViewResId" format="reference"//滑块资源id
17 | >>name="slideImageViewResIdAfter" format="reference"//滑动到右边时,滑块资源id
18 | >>name="viewBackgroundResId" format="reference"//背景资源id
19 | >>name="textHint" format="string"//文本内容
20 | >>name="textSize" format="integer"/>//文本字号
21 | >>name="textColorResId" format="color"//文本字色
22 | >>name="slideThreshold" format="float"//滑动阈值,默认是0.5,当右滑距离不满整个控件宽度的0.5,就会回弹至左边
23 |
24 | ## xml :
25 |
26 | android:id="@+id/slide_to_unlock"
27 | android:layout_width="match_parent"
28 | android:layout_height="50dp"
29 | chuck:viewBackgroundResId="@drawable/shape_round_normal_green"
30 | chuck:slideImageViewWidth="@dimen/slide_width"
31 | chuck:slideImageViewResId="@mipmap/icon_slide"
32 | chuck:slideImageViewResIdAfter="@mipmap/ic_launcher"
33 | chuck:slideThreshold="0.5"
34 | chuck:textSize="6"
35 | chuck:textHint="@string/hint"
36 | chuck:textColorResId="@color/colorWhite"
37 |
38 |
39 | ## MainActivity.java :
40 | ```Java
41 | package com.qdong.slidetounlockdemo;
42 | import android.os.Bundle;
43 | import android.support.v7.app.AppCompatActivity;
44 | import android.view.View;
45 | import android.widget.TextView;
46 | import com.qdong.slide_to_unlock_view.CustomSlideToUnlockView;
47 |
48 |
49 | public class MainActivity extends AppCompatActivity {
50 |
51 | private CustomSlideToUnlockView mCustomSlideToUnlockView;
52 | private TextView tv_text;
53 |
54 | @Override
55 | protected void onCreate(Bundle savedInstanceState) {
56 | super.onCreate(savedInstanceState);
57 | setContentView(R.layout.activity_main);
58 | mCustomSlideToUnlockView= (com.qdong.slide_to_unlock_view.CustomSlideToUnlockView) findViewById(R.id.slide_to_unlock);
59 | tv_text= (TextView) findViewById(R.id.tv_text);
60 |
61 | CustomSlideToUnlockView.CallBack callBack=new CustomSlideToUnlockView.CallBack() {
62 | @Override
63 | public void onSlide(int distance) {
64 | tv_text.setText("slide distance:"+distance);
65 | }
66 |
67 | @Override
68 | public void onUnlocked() {
69 | tv_text.setText("onUnlocked");
70 | }
71 | };
72 | mCustomSlideToUnlockView.setmCallBack(callBack);
73 | findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
74 | @Override
75 | public void onClick(View view) {
76 | mCustomSlideToUnlockView.resetView();
77 | }
78 | });
79 | }
80 | }
81 | ```
--------------------------------------------------------------------------------
/SlideToUnlockView/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/SlideToUnlockView/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | apply plugin: 'maven'
4 | apply plugin: 'com.novoda.bintray-release'
5 |
6 | android {
7 | compileSdkVersion 25
8 | buildToolsVersion "25.0.1"
9 |
10 | defaultConfig {
11 | minSdkVersion 19
12 | targetSdkVersion 25
13 | versionCode 1
14 | versionName "1.0"
15 | }
16 | buildTypes {
17 | release {
18 | minifyEnabled false
19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
20 | }
21 | }
22 | }
23 |
24 | dependencies {
25 | compile fileTree(dir: 'libs', include: ['*.jar'])
26 | testCompile 'junit:junit:4.12'
27 | compile 'com.android.support:appcompat-v7:25.1.0'
28 | compile 'com.nineoldandroids:library:2.4.0'
29 | compile 'com.github.florent37:viewanimator:1.0.0@aar'
30 | }
31 |
32 |
33 |
34 | publish {
35 | userOrg = 'linklink'
36 | groupId = 'com.linklink.views'
37 | artifactId = 'slide_to_unlock_view'
38 | version = '1.0.0'
39 | description = 'Slide To Unlock View'
40 | website = 'https://github.com/506954774/AndroidCustomSlideToUnlockView'
41 | }
42 |
43 |
44 |
45 | tasks.withType(JavaCompile) {
46 | options.encoding = "UTF-8"
47 | }
48 |
49 | tasks.withType(Javadoc) {
50 | options.addStringOption('Xdoclint:none', '-quiet')
51 | options.addStringOption('encoding', 'UTF-8')
52 | }
--------------------------------------------------------------------------------
/SlideToUnlockView/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:\IDE\sdk/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 |
--------------------------------------------------------------------------------
/SlideToUnlockView/slidetounlockview.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | generateDebugSources
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 |
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 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
--------------------------------------------------------------------------------
/SlideToUnlockView/src/androidTest/java/com/qdong/slide_to_unlock_view/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.qdong.slide_to_unlock_view;
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 | }
--------------------------------------------------------------------------------
/SlideToUnlockView/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/SlideToUnlockView/src/main/java/com/qdong/slide_to_unlock_view/CustomSlideToUnlockView.java:
--------------------------------------------------------------------------------
1 | package com.qdong.slide_to_unlock_view;
2 |
3 | import android.content.Context;
4 | import android.content.res.TypedArray;
5 | import android.text.TextUtils;
6 | import android.util.AttributeSet;
7 | import android.util.Log;
8 | import android.view.LayoutInflater;
9 | import android.view.MotionEvent;
10 | import android.view.View;
11 | import android.view.animation.AccelerateInterpolator;
12 | import android.widget.ImageView;
13 | import android.widget.RelativeLayout;
14 | import android.widget.TextView;
15 |
16 | import com.github.florent37.viewanimator.AnimationListener;
17 | import com.github.florent37.viewanimator.ViewAnimator;
18 | import com.nineoldandroids.view.ViewHelper;
19 |
20 |
21 | /**
22 | * CustomSlideToUnlockView
23 | * 责任人: Chuck
24 | * 修改人: Chuck
25 | * 创建/修改时间: 2017/5/23 16:53
26 | * Copyright : 2014-2016 深圳趣动智能科技有限公司-版权所有
27 | **/
28 | public class CustomSlideToUnlockView extends RelativeLayout {
29 |
30 | private static final String TAG="CustomSlideToUnlockView";
31 | private static final long DEAFULT_DURATIN_LONG = 200;//左弹回,动画时长
32 | private static final long DEAFULT_DURATIN_SHORT = 100;//右弹,动画时长
33 | private static final boolean LOG = true;//打印开关
34 | private static int DISTANCE_LIMIT = 600;//滑动阈值
35 | private static float THRESHOLD = 0.5F;//滑动阈值比例:默认是0.5,即滑动超过父容器宽度的一半再松手就会触发
36 | protected Context mContext;
37 | private ImageView iv_slide;//滑块
38 | private TextView tv_hint;//提示文本
39 | private RelativeLayout rl_slide;//滑动view
40 | private RelativeLayout rl_root;//父容器
41 | private boolean mIsUnLocked;//已经滑到最右边,将不再响应touch事件
42 | private CallBack mCallBack;//回调
43 |
44 |
45 | private int slideImageViewWidth;//滑块宽度
46 | private int slideImageViewResId;//滑块资源
47 | private int slideImageViewResIdAfter;//滑动到右边时,滑块资源id
48 | private int viewBackgroundResId;//root 背景
49 | private String textHint;//文本
50 | private int textSize;//单位是sp,只拿数值
51 | private int textColorResId;//颜色,@color
52 |
53 |
54 | public CustomSlideToUnlockView(Context mContext) {
55 | super(mContext);
56 | this.mContext = mContext;
57 | initView();
58 | }
59 |
60 | public CustomSlideToUnlockView(Context mContext, AttributeSet attrs) {
61 | super(mContext, attrs);
62 | this.mContext = mContext;
63 | TypedArray mTypedArray = mContext.obtainStyledAttributes(attrs,
64 | R.styleable.SlideToUnlockView);
65 | init(mTypedArray);
66 | initView();
67 | }
68 |
69 | public CustomSlideToUnlockView(Context mContext, AttributeSet attrs, int defStyleAttr) {
70 | super(mContext, attrs, defStyleAttr);
71 | this.mContext = mContext;
72 |
73 | TypedArray mTypedArray = mContext.obtainStyledAttributes(attrs,
74 | R.styleable.SlideToUnlockView);
75 | init(mTypedArray);
76 |
77 | initView();
78 |
79 | }
80 |
81 | /**
82 | * @method name:init
83 | * @des:获取自定义属性
84 | * @param :[mTypedArray]
85 | * @return type:void
86 | * @date 创建时间:2017/5/24
87 | * @author Chuck
88 | **/
89 | private void init(TypedArray mTypedArray) {
90 |
91 | slideImageViewWidth= (int) mTypedArray.getDimension(R.styleable.SlideToUnlockView_slideImageViewWidth, DensityUtil.dp2px(getContext(), 50));
92 | slideImageViewResId= mTypedArray.getResourceId(R.styleable.SlideToUnlockView_slideImageViewResId, -1);
93 | slideImageViewResIdAfter= mTypedArray.getResourceId(R.styleable.SlideToUnlockView_slideImageViewResIdAfter, -1);
94 | viewBackgroundResId= mTypedArray.getResourceId(R.styleable.SlideToUnlockView_viewBackgroundResId, -1);
95 | textHint=mTypedArray.getString(R.styleable.SlideToUnlockView_textHint);
96 | textSize=mTypedArray.getInteger(R.styleable.SlideToUnlockView_textSize, 7);
97 | textColorResId= mTypedArray.getColor(R.styleable.SlideToUnlockView_textColorResId, getResources().getColor(android.R.color.white));
98 | THRESHOLD=mTypedArray.getFloat(R.styleable.SlideToUnlockView_slideThreshold, 0.5f);
99 |
100 | mTypedArray.recycle();
101 | }
102 |
103 |
104 | private int mActionDownX, mLastX, mSlidedDistance;
105 |
106 |
107 | /**
108 | * 初始化界面布局
109 | */
110 | protected void initView() {
111 |
112 | LayoutInflater.from(mContext).inflate(R.layout.layout_view_slide_to_unlock,
113 | this, true);
114 |
115 | rl_root = (RelativeLayout) findViewById(R.id.rl_root);
116 | rl_slide = (RelativeLayout) findViewById(R.id.rl_slide);
117 | iv_slide = (ImageView) findViewById(R.id.iv_slide);
118 | tv_hint = (TextView) findViewById(R.id.tv_hint);
119 |
120 | LayoutParams params= (LayoutParams) iv_slide .getLayoutParams();
121 | //获取当前控件的布局对象
122 | params.width= slideImageViewWidth;//设置当前控件布局的高度
123 | iv_slide.setLayoutParams(params);//将设置好的布局参数应用到控件中
124 |
125 | setImageDefault();
126 | if(viewBackgroundResId>0){
127 | rl_slide.setBackgroundResource(viewBackgroundResId);//rootView设置背景
128 | }
129 |
130 | MarginLayoutParams tvParams = (MarginLayoutParams) tv_hint.getLayoutParams();
131 | tvParams.setMargins(0, 0, slideImageViewWidth, 0);//textview的marginRight设置为和滑块的宽度一致
132 | tv_hint.setLayoutParams(tvParams);
133 | tv_hint.setTextSize(DensityUtil.sp2px(getContext(), textSize));
134 | tv_hint.setTextColor(textColorResId);
135 | tv_hint.setText(TextUtils.isEmpty(textHint)? mContext.getString(R.string.hint):textHint);
136 |
137 | //添加滑动监听
138 | rl_slide.setOnTouchListener(new OnTouchListener() {
139 | @Override
140 | public boolean onTouch(View v, MotionEvent event) {
141 |
142 | DISTANCE_LIMIT= (int) (CustomSlideToUnlockView.this.getWidth()*THRESHOLD);//默认阈值是控件宽度的一半
143 |
144 | switch (event.getAction()) {
145 |
146 | case MotionEvent.ACTION_DOWN://按下时记录纵坐标
147 |
148 | if(mIsUnLocked){//滑块已经在最右边则不处理touch
149 | return false;
150 | }
151 |
152 | mLastX = (int) event.getRawX();//最后一个action时x值
153 | mActionDownX = (int) event.getRawX();//按下的瞬间x
154 | logI(TAG, mLastX + "X,=============================ACTION_DOWN");
155 | break;
156 |
157 | case MotionEvent.ACTION_MOVE://上滑才处理,如果用户一开始就下滑,则过掉不处理
158 |
159 | logI(TAG, "=============================ACTION_MOVE");
160 | logI(TAG, "event.getRawX()============================="+event.getRawX());
161 |
162 | int dX = (int) event.getRawX() - mLastX;
163 | logI(TAG, "dX============================="+dX);
164 |
165 | mSlidedDistance = (int) event.getRawX() - mActionDownX;
166 | logI(TAG, "mSlidedDistance============================="+ mSlidedDistance);
167 |
168 | final MarginLayoutParams params = (MarginLayoutParams) v.getLayoutParams();
169 | int left = params.leftMargin;
170 | int top = params.topMargin;
171 | int right = params.rightMargin;
172 | int bottom = params.bottomMargin;
173 |
174 | logI(TAG, "left:"+left+",top:"+top+",right:"+right+",bottom"+bottom);
175 |
176 | int leftNew = left + dX;
177 | int rightNew =right - dX;
178 |
179 | if (mSlidedDistance > 0) {//直接通过margin实现滑动
180 | params.setMargins(leftNew, top, rightNew, bottom);
181 | logI(TAG, leftNew + "=============================MOVE");
182 | v.setLayoutParams(params);
183 | resetTextViewAlpha(mSlidedDistance);
184 |
185 | //回调
186 | if(mCallBack!=null){
187 | mCallBack.onSlide(mSlidedDistance);
188 | }
189 | mLastX = (int) event.getRawX();
190 | } else {
191 | return true;
192 | }
193 |
194 | break;
195 |
196 |
197 | case MotionEvent.ACTION_UP:
198 | logI(TAG, "MotionEvent.ACTION_UP,之前移动的偏移值:" + ViewHelper.getTranslationY(v));
199 | if (Math.abs(mSlidedDistance) > DISTANCE_LIMIT) {
200 | scrollToRight(v);//右边
201 | } else {
202 | scrollToLeft(v);//左边
203 | }
204 | break;
205 |
206 |
207 | case MotionEvent.ACTION_CANCEL:
208 | // try {
209 | // if (vTracker != null) {
210 | // vTracker.recycle();
211 | // vTracker = null;
212 | // }
213 | // vTracker.recycle();
214 | // } catch (Exception e) {
215 | // e.printStackTrace();
216 | // }
217 |
218 | break;
219 |
220 | }
221 |
222 |
223 | return true;
224 | }
225 | });
226 |
227 |
228 |
229 | }
230 |
231 |
232 | private void logI(String tag,String content){
233 | if(LOG){
234 | Log.i(tag,content);
235 | }
236 | }
237 |
238 | /**
239 | * @method name:resetTextViewAlpha
240 | * @des: 重置提示文本的透明度
241 | * @param :[mSlidedDistance]
242 | * @return type:void
243 | * @date 创建时间:2017/5/24
244 | * @author Chuck
245 | **/
246 | private void resetTextViewAlpha(int distance) {
247 |
248 | if(Math.abs(distance)>=Math.abs(DISTANCE_LIMIT)){
249 | tv_hint.setAlpha(0.0f);
250 | }
251 | else{
252 | tv_hint.setAlpha(1.0f-Math.abs(distance)*1.0f/Math.abs(DISTANCE_LIMIT));
253 | }
254 | }
255 |
256 |
257 | /**
258 | * @method name:scrollToLeft
259 | * @des: 滑动未到阈值时松开手指,弹回到最左边
260 | * @param :[v]
261 | * @return type:void
262 | * @date 创建时间:2017/5/24
263 | * @author Chuck
264 | **/
265 | private void scrollToLeft(final View v) {
266 |
267 |
268 | final MarginLayoutParams params1 = (MarginLayoutParams) v.getLayoutParams();
269 | logI(TAG, "scrollToLeft,ViewHelper.getTranslationX(v):" + ViewHelper.getTranslationX(v));
270 | logI(TAG, "scrollToLeft,params1.leftMargin:" + params1.leftMargin);
271 | logI(TAG, "scrollToLeft, params1.rightMargin:" + params1.rightMargin);
272 |
273 |
274 | ViewAnimator
275 | .animate( rl_slide)
276 | .translationX(ViewHelper.getTranslationX(v), -params1.leftMargin)
277 | .interpolator(new AccelerateInterpolator())
278 | .duration(DEAFULT_DURATIN_LONG)
279 | .onStop(new AnimationListener.Stop() {
280 | @Override
281 | public void onStop() {
282 | MarginLayoutParams para = (MarginLayoutParams) v.getLayoutParams();
283 | logI(TAG, "scrollToLeft动画结束para.leftMargin:" + para.leftMargin);
284 | logI(TAG, "scrollToLeft动画结束para.rightMargin:" + para.rightMargin);
285 | logI(TAG, "scrollToLeft动画结束,ViewHelper.getTranslationX(v):" + ViewHelper.getTranslationX(v));
286 | mSlidedDistance = 0;
287 | tv_hint.setAlpha(1.0f);
288 | mIsUnLocked=false;
289 | if(mCallBack!=null){
290 | mCallBack.onSlide(mSlidedDistance);
291 | }
292 | setImageDefault();
293 | }
294 | })
295 | .start();
296 | }
297 |
298 |
299 | /**
300 | * @method name:scrollToRight
301 | * @des:滑动到右边,并触发回调
302 | * @param :[v]
303 | * @return type:void
304 | * @date 创建时间:2017/5/24
305 | * @author Chuck
306 | **/
307 | private void scrollToRight(final View v) {
308 |
309 |
310 | final MarginLayoutParams params1 = (MarginLayoutParams) v.getLayoutParams();
311 | logI(TAG, "scrollToRight,ViewHelper.getTranslationX(v):" + ViewHelper.getTranslationX(v));
312 | logI(TAG, "scrollToRight,params1.leftMargin:" + params1.leftMargin);
313 | logI(TAG, "scrollToRight, params1.rightMargin:" + params1.rightMargin);
314 |
315 | //移动到最右端 移动的距离是 父容器宽度-leftMargin
316 | ViewAnimator
317 | .animate( rl_slide)
318 | //.translationX(ViewHelper.getTranslationX(v), ViewHelper.getTranslationX(v)+100)
319 | .translationX(ViewHelper.getTranslationX(v), ( rl_slide.getWidth() - params1.leftMargin-slideImageViewWidth))
320 | //.translationX(params1.leftMargin, ( rl_slide.getWidth() - params1.leftMargin-100))
321 | .interpolator(new AccelerateInterpolator())
322 | .duration(DEAFULT_DURATIN_SHORT)
323 | .onStop(new AnimationListener.Stop() {
324 | @Override
325 | public void onStop() {
326 | MarginLayoutParams para = (MarginLayoutParams) v.getLayoutParams();
327 | logI(TAG, "scrollToRight动画结束para.leftMargin:" + para.leftMargin);
328 | logI(TAG, "scrollToRight动画结束para.rightMargin:" + para.rightMargin);
329 | logI(TAG, "scrollToRight动画结束,ViewHelper.getTranslationX(v):" + ViewHelper.getTranslationX(v));
330 | mSlidedDistance = 0;
331 | tv_hint.setAlpha(0.0f);
332 | mIsUnLocked=true;
333 |
334 | if(slideImageViewResIdAfter>0){
335 | iv_slide.setImageResource(slideImageViewResIdAfter);//滑块imagview设置资源
336 | }
337 |
338 | //回调
339 | if(mCallBack!=null){
340 | mCallBack.onUnlocked();
341 | }
342 | }
343 | })
344 | .start();
345 |
346 |
347 | }
348 |
349 |
350 | public void resetView(){
351 | mIsUnLocked=false;
352 | setImageDefault();
353 | scrollToLeft(rl_slide);
354 | }
355 |
356 | private void setImageDefault() {
357 | /**
358 | * @method name:setImageDefault
359 | * @des: 设置默认图片
360 | * @param :[]
361 | * @return type:void
362 | * @date 创建时间:2017/5/25
363 | * @author Chuck
364 | **/
365 |
366 | if(slideImageViewResId>0){
367 | iv_slide.setImageResource(slideImageViewResId);//滑块imagview设置资源
368 | }
369 | }
370 |
371 | public interface CallBack{
372 | void onSlide(int distance);//右滑距离回调
373 | void onUnlocked();//滑动到了右边,事件回调
374 | }
375 |
376 |
377 | public CallBack getmCallBack() {
378 | return mCallBack;
379 | }
380 |
381 | public void setmCallBack(CallBack mCallBack) {
382 | this.mCallBack = mCallBack;
383 | }
384 | }
385 |
--------------------------------------------------------------------------------
/SlideToUnlockView/src/main/java/com/qdong/slide_to_unlock_view/DensityUtil.java:
--------------------------------------------------------------------------------
1 | package com.qdong.slide_to_unlock_view;
2 |
3 | import android.content.Context;
4 | import android.util.DisplayMetrics;
5 | import android.util.TypedValue;
6 | import android.view.WindowManager;
7 |
8 | public class DensityUtil {
9 |
10 | @Deprecated
11 | public static int dip2px(Context paramContext, float paramFloat) {
12 | return (int) (0.5F + paramFloat
13 | * paramContext.getResources().getDisplayMetrics().density);
14 | }
15 |
16 | @Deprecated
17 | public static int px2dip(Context context, float paramFloat) {
18 | return (int) (0.5F + paramFloat
19 | / context.getResources().getDisplayMetrics().density);
20 | }
21 |
22 | @Deprecated
23 | public static int sp2px(Context context, float spValue) {
24 | final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
25 | return (int) (spValue * fontScale + 0.5f);
26 | }
27 |
28 | @Deprecated
29 | public static int px2sp(Context context, float value) {
30 | final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
31 | return (int) (value / fontScale + 0.5f);
32 | }
33 |
34 | public static int dip2px(float density, float value) {
35 | return (int) (0.5F + value * density);
36 | }
37 |
38 | public static int px2dip(float density, float value) {
39 | return (int) (0.5F + value / density);
40 | }
41 |
42 | public static int sp2px(float scaledDensity, float value) {
43 | return (int) (0.5F + value * scaledDensity);
44 | }
45 |
46 | public static int px2sp(float fontScale /** scaledDensity */
47 | , float value) {
48 | return (int) (value / fontScale + 0.5f);
49 |
50 |
51 | }
52 |
53 | public static final int getStatusHeighByDensity(Context context) {
54 | int h = 38;
55 | int density = context.getResources().getDisplayMetrics().densityDpi;
56 |
57 | switch (density) {
58 | case 120:
59 | h = 19;
60 | break;
61 | case 160:
62 | h = 25;
63 | break;
64 | case 240:
65 | h = 38;
66 | break;
67 | case 320:
68 | h = 50;
69 | break;
70 | case 400:
71 | h = 63;
72 | break;
73 | case 480:
74 | h = 75;
75 | break;
76 | default:
77 | break;
78 | }
79 |
80 | return h;
81 | }
82 |
83 | private static int displayWidth, displayHeight;
84 |
85 | private static void initDisplay(Context context) {
86 | DisplayMetrics dm = new DisplayMetrics();
87 | ((WindowManager) context.getApplicationContext().getSystemService(
88 | Context.WINDOW_SERVICE)).getDefaultDisplay().getMetrics(dm);
89 |
90 | displayWidth = dm.widthPixels;
91 |
92 | displayHeight = dm.heightPixels;
93 | }
94 |
95 |
96 | public static final int getDisplayWidth(Context context) {
97 | if (displayWidth == 0) {
98 | initDisplay(context);
99 | }
100 | return displayWidth;
101 | }
102 |
103 |
104 | public static final int getDisplayHeight(Context context) {
105 | if (displayHeight == 0) {
106 | initDisplay(context);
107 | }
108 | return displayHeight;
109 | }
110 |
111 | public static int dp2px(Context context, int dp) {
112 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,context.getResources().getDisplayMetrics());
113 | }
114 |
115 | public static int dp2px(Context context, float dp) {
116 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,context.getResources().getDisplayMetrics());
117 | }
118 |
119 | public static int px2dp(Context context, int px) {
120 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, px,context.getResources().getDisplayMetrics());
121 | }
122 |
123 | public static int px2sp(Context context, int px) {
124 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, px,context.getResources().getDisplayMetrics());
125 | }
126 |
127 | public static int getScreenWidth(Context context)
128 | {
129 | WindowManager wm = (WindowManager) context
130 | .getSystemService(Context.WINDOW_SERVICE );
131 | DisplayMetrics outMetrics = new DisplayMetrics();
132 | wm.getDefaultDisplay().getMetrics( outMetrics);
133 | return outMetrics .widthPixels ;
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/SlideToUnlockView/src/main/res/drawable/shape_round_normal_green.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/SlideToUnlockView/src/main/res/layout/layout_view_slide_to_unlock.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
15 |
16 |
20 |
21 |
27 |
28 |
29 |
30 |
31 |
32 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/SlideToUnlockView/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/506954774/AndroidCustomSlideToUnlockView/6eb1bf618c51dac7371656bfa36e35c443661ecc/SlideToUnlockView/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/SlideToUnlockView/src/main/res/mipmap-xhdpi/icon_slide.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/506954774/AndroidCustomSlideToUnlockView/6eb1bf618c51dac7371656bfa36e35c443661ecc/SlideToUnlockView/src/main/res/mipmap-xhdpi/icon_slide.png
--------------------------------------------------------------------------------
/SlideToUnlockView/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/SlideToUnlockView/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | SlideToUnlockView
3 | 滑动解锁
4 |
5 |
6 |
--------------------------------------------------------------------------------
/SlideToUnlockView/src/test/java/com/qdong/slide_to_unlock_view/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.qdong.slide_to_unlock_view;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * To work on unit tests, switch the Test Artifact in the Build Variants view.
9 | */
10 | public class ExampleUnitTest {
11 | @Test
12 | public void addition_isCorrect() throws Exception {
13 | assertEquals(4, 2 + 2);
14 | }
15 | }
--------------------------------------------------------------------------------
/app-debug.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/506954774/AndroidCustomSlideToUnlockView/6eb1bf618c51dac7371656bfa36e35c443661ecc/app-debug.apk
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/app.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | generateDebugSources
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 |
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 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | repositories {
4 | flatDir {
5 | dir 'libs'
6 | }
7 | maven { url "https://jitpack.io" }
8 | }
9 |
10 | android {
11 | compileSdkVersion 25
12 | buildToolsVersion "25.0.1"
13 |
14 | defaultConfig {
15 | applicationId "com.qdong.slidetounlockdemo"
16 | minSdkVersion 19
17 | targetSdkVersion 25
18 | versionCode 1
19 | versionName "1.0"
20 | }
21 | buildTypes {
22 | release {
23 | minifyEnabled false
24 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
25 | }
26 | }
27 | }
28 |
29 | dependencies {
30 | compile fileTree(include: ['*.jar'], dir: 'libs')
31 | testCompile 'junit:junit:4.12'
32 | compile 'com.android.support:appcompat-v7:25.1.0'
33 | compile 'com.nineoldandroids:library:2.4.0'
34 | compile 'com.github.florent37:viewanimator:1.0.0@aar'
35 | //compile project(':slidetounlockview')
36 | compile 'com.linklink.views:slide_to_unlock_view:1.0.0'
37 | }
38 |
--------------------------------------------------------------------------------
/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:\IDE\sdk/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 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/qdong/slidetounlockdemo/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.qdong.slidetounlockdemo;
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 | }
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/java/com/qdong/slidetounlockdemo/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.qdong.slidetounlockdemo;
2 | import android.os.Bundle;
3 | import android.support.v7.app.AppCompatActivity;
4 | import android.view.View;
5 | import android.widget.TextView;
6 | import com.qdong.slide_to_unlock_view.CustomSlideToUnlockView;
7 |
8 |
9 | public class MainActivity extends AppCompatActivity {
10 |
11 | private CustomSlideToUnlockView mCustomSlideToUnlockView;
12 | private TextView tv_text;
13 |
14 | @Override
15 | protected void onCreate(Bundle savedInstanceState) {
16 | super.onCreate(savedInstanceState);
17 | setContentView(R.layout.activity_main);
18 | mCustomSlideToUnlockView= (com.qdong.slide_to_unlock_view.CustomSlideToUnlockView) findViewById(R.id.slide_to_unlock);
19 | tv_text= (TextView) findViewById(R.id.tv_text);
20 |
21 | CustomSlideToUnlockView.CallBack callBack=new CustomSlideToUnlockView.CallBack() {
22 | @Override
23 | public void onSlide(int distance) {
24 | tv_text.setText("slide distance:"+distance);
25 | }
26 |
27 | @Override
28 | public void onUnlocked() {
29 | tv_text.setText("onUnlocked");
30 | }
31 | };
32 | mCustomSlideToUnlockView.setmCallBack(callBack);
33 | findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
34 | @Override
35 | public void onClick(View view) {
36 | mCustomSlideToUnlockView.resetView();
37 | }
38 | });
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/shape_round_normal_green.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 |
16 |
17 |
21 |
22 |
24 |
37 |
38 |
39 |
40 |
41 |
49 |
50 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/506954774/AndroidCustomSlideToUnlockView/6eb1bf618c51dac7371656bfa36e35c443661ecc/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/506954774/AndroidCustomSlideToUnlockView/6eb1bf618c51dac7371656bfa36e35c443661ecc/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/506954774/AndroidCustomSlideToUnlockView/6eb1bf618c51dac7371656bfa36e35c443661ecc/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/icon_slide.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/506954774/AndroidCustomSlideToUnlockView/6eb1bf618c51dac7371656bfa36e35c443661ecc/app/src/main/res/mipmap-xhdpi/icon_slide.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/506954774/AndroidCustomSlideToUnlockView/6eb1bf618c51dac7371656bfa36e35c443661ecc/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/506954774/AndroidCustomSlideToUnlockView/6eb1bf618c51dac7371656bfa36e35c443661ecc/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 | #FFFFFF
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 | 50dp
6 | 18sp
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | SlideToUnlock
3 | 滑动解锁
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/test/java/com/qdong/slidetounlockdemo/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.qdong.slidetounlockdemo;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * To work on unit tests, switch the Test Artifact in the Build Variants view.
9 | */
10 | public class ExampleUnitTest {
11 | @Test
12 | public void addition_isCorrect() throws Exception {
13 | assertEquals(4, 2 + 2);
14 | }
15 | }
--------------------------------------------------------------------------------
/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:2.0.0'
9 |
10 |
11 | classpath 'com.novoda:bintray-release:0.3.4'
12 |
13 | // NOTE: Do not place your application dependencies here; they belong
14 | // in the individual module build.gradle files
15 | }
16 | }
17 |
18 | allprojects {
19 | repositories {
20 | jcenter()
21 | }
22 | }
23 |
24 | task clean(type: Delete) {
25 | delete rootProject.buildDir
26 | }
27 |
28 | tasks.withType(JavaCompile) {
29 | options.encoding = "UTF-8"
30 | }
31 |
--------------------------------------------------------------------------------
/demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/506954774/AndroidCustomSlideToUnlockView/6eb1bf618c51dac7371656bfa36e35c443661ecc/demo.gif
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/506954774/AndroidCustomSlideToUnlockView/6eb1bf618c51dac7371656bfa36e35c443661ecc/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Dec 28 10:00:20 PST 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.10-all.zip
7 |
--------------------------------------------------------------------------------