先看下滑動的效果圖? 滑動解鎖分享的一個(gè)效果
https://github.com/TangfeiJi/SlideToUnlockProject? ?源碼


我是以模塊的方式導(dǎo)入的??聪虏僮鞯牟襟E
1.下載模塊并導(dǎo)入在項(xiàng)目中。

2.在項(xiàng)目的Gradle中增加依賴

3.在布局中增加組件
<com.qdong.slide_to_unlock_view.CustomSlideToUnlockView
? ? ? ? android:id="@+id/slide_to_unlock"
? ? ? ? android:layout_width="match_parent"
? ? ? ? android:layout_height="44dp"
? ? ? ? android:layout_marginLeft="45dp"
? ? ? ? android:layout_marginTop="50dp"
? ? ? ? android:layout_marginRight="45dp"
? ? ? ? android:layout_marginBottom="40dp"
? ? ? ? chuck:slideImageViewResId="@mipmap/unlock_hide"
? ? ? ? chuck:slideImageViewResIdAfter="@mipmap/unlock_1_hide"
? ? ? ? chuck:slideImageViewWidth="35dp"
? ? ? ? chuck:slideThreshold="0.5"
? ? ? ? chuck:textColorResId="#fff"
? ? ? ? chuck:textHint="滑動解鎖"
? ? ? ? chuck:textSize="6"
? ? ? ? chuck:viewBackgroundResId="@drawable/shape_round_normal_green"
? ? ? ? tools:ignore="MissingConstraints">
? ? </com.qdong.slide_to_unlock_view.CustomSlideToUnlockView>
4.在activity中初始化并使用 這是列出它給出的監(jiān)聽
? ? CustomSlideToUnlockView.CallBack callBack = new CustomSlideToUnlockView.CallBack() {
? ? ? ? ? ? @Override//滑動到的位置
? ? ? ? ? ? public void onSlide(int distance) {
? ? ? ? ? ? ? ? Log.e("1111",distance+"");
? ? ? ? ? ? }
? ? ? ? ? ? @Override
? ? ? ? ? ? public void onUnlocked() {? //滑動到最后解鎖
? ? ? ? ? ? ? ? pop_layout.setVisibility(View.VISIBLE);
? ? ? ? ? ? ? ? Toast.makeText(MainActivity.this,"onUnlocked",Toast.LENGTH_LONG).show();
? ? ? ? ? ? }
? ? ? ? };
來看看源碼我這已經(jīng)給出了注釋說明
package com.qdong.slide_to_unlock_view;
import android.content.Context;
import android.content.res.TypedArray;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.github.florent37.viewanimator.AnimationListener;
import com.github.florent37.viewanimator.ViewAnimator;
import com.nineoldandroids.view.ViewHelper;
/**
**/
public class CustomSlideToUnlockView extends RelativeLayout {
? ? private static final String TAG="CustomSlideToUnlockView";
? ? private static final long DEAFULT_DURATIN_LONG = 200;//左彈回,動畫時(shí)長
? ? private static final long DEAFULT_DURATIN_SHORT = 100;//右彈,動畫時(shí)長
? ? private static final boolean LOG = true;//打印開關(guān)
? ? private static int? DISTANCE_LIMIT = 600;//滑動閾值
? ? private static float? THRESHOLD = 0.5F;//滑動閾值比例:默認(rèn)是0.5,即滑動超過父容器寬度的一半再松手就會觸發(fā)
? ? protected Context mContext;
? ? private ImageView iv_slide;//滑塊
? ? private TextView tv_hint;//提示文本
? ? private RelativeLayout rl_slide;//滑動view
? ? private RelativeLayout rl_root;//父容器
? ? private boolean mIsUnLocked;//已經(jīng)滑到最右邊,將不再響應(yīng)touch事件
? ? private CallBack mCallBack;//回調(diào)
? ? private int slideImageViewWidth;//滑塊寬度
? ? private int? slideImageViewResId;//滑塊資源
? ? private int? slideImageViewResIdAfter;//滑動到右邊時(shí),滑塊資源id
? ? private int? viewBackgroundResId;//root 背景
? ? private String textHint;//文本
? ? private int textSize;//單位是sp,只拿數(shù)值
? ? private int textColorResId;//顏色,@color
? ? public CustomSlideToUnlockView(Context mContext) {
? ? ? ? super(mContext);
? ? ? ? this.mContext = mContext;
? ? ? ? initView();
? ? }
? ? public CustomSlideToUnlockView(Context mContext, AttributeSet attrs) {
? ? ? ? super(mContext, attrs);
? ? ? ? this.mContext = mContext;
? ? ? ? TypedArray mTypedArray = mContext.obtainStyledAttributes(attrs,
? ? ? ? ? ? ? ? R.styleable.SlideToUnlockView);
? ? ? ? init(mTypedArray);
? ? ? ? initView();
? ? }
? ? public CustomSlideToUnlockView(Context mContext, AttributeSet attrs, int defStyleAttr) {
? ? ? ? super(mContext, attrs, defStyleAttr);
? ? ? ? this.mContext = mContext;
? ? ? ? TypedArray mTypedArray = mContext.obtainStyledAttributes(attrs,
? ? ? ? ? ? ? ? R.styleable.SlideToUnlockView);
? ? ? ? init(mTypedArray);
? ? ? ? initView();
? ? }
? ? /**
? ? **/
? ? private void init(TypedArray mTypedArray) {
? ? ? ? slideImageViewWidth= (int) mTypedArray.getDimension(R.styleable.SlideToUnlockView_slideImageViewWidth, DensityUtil.dp2px(getContext(), 50));
? ? ? ? slideImageViewResId= mTypedArray.getResourceId(R.styleable.SlideToUnlockView_slideImageViewResId, -1);
? ? ? ? slideImageViewResIdAfter= mTypedArray.getResourceId(R.styleable.SlideToUnlockView_slideImageViewResIdAfter, -1);
? ? ? ? viewBackgroundResId= mTypedArray.getResourceId(R.styleable.SlideToUnlockView_viewBackgroundResId, -1);
? ? ? ? textHint=mTypedArray.getString(R.styleable.SlideToUnlockView_textHint);
? ? ? ? textSize=mTypedArray.getInteger(R.styleable.SlideToUnlockView_textSize, 7);
? ? ? ? textColorResId= mTypedArray.getColor(R.styleable.SlideToUnlockView_textColorResId, getResources().getColor(android.R.color.white));
? ? ? ? THRESHOLD=mTypedArray.getFloat(R.styleable.SlideToUnlockView_slideThreshold, 0.5f);
? ? ? ? mTypedArray.recycle();
? ? }
? ? private int mActionDownX, mLastX, mSlidedDistance;
? ? /**
? ? * 初始化界面布局
? ? */
? ? protected void initView() {
? ? ? ? LayoutInflater.from(mContext).inflate(R.layout.layout_view_slide_to_unlock,
? ? ? ? ? ? ? ? this, true);
? ? ? ? rl_root = (RelativeLayout) findViewById(R.id.rl_root);
? ? ? ? rl_slide = (RelativeLayout) findViewById(R.id.rl_slide);
? ? ? ? iv_slide = (ImageView) findViewById(R.id.iv_slide);
? ? ? ? tv_hint = (TextView) findViewById(R.id.tv_hint);
? ? ? ? LayoutParams params= (LayoutParams) iv_slide .getLayoutParams();
? ? ? ? //獲取當(dāng)前控件的布局對象
? ? ? ? params.width= slideImageViewWidth;//設(shè)置當(dāng)前控件布局的高度
? ? ? ? iv_slide.setLayoutParams(params);//將設(shè)置好的布局參數(shù)應(yīng)用到控件中
? ? ? ? setImageDefault();
? ? ? ? if(viewBackgroundResId>0){
//? ? ? ? ? ? rl_slide.setBackgroundResource(viewBackgroundResId);//rootView設(shè)置背景
? ? ? ? }
? ? ? ? MarginLayoutParams tvParams = (MarginLayoutParams) tv_hint.getLayoutParams();
? ? ? ? tvParams.setMargins(0, 0, slideImageViewWidth, 0);//textview的marginRight設(shè)置為和滑塊的寬度一致
? ? ? ? tv_hint.setLayoutParams(tvParams);
? ? ? ? tv_hint.setTextSize(DensityUtil.sp2px(getContext(), textSize));
? ? ? ? tv_hint.setTextColor(textColorResId);
? ? ? ? tv_hint.setText(TextUtils.isEmpty(textHint)? mContext.getString(R.string.hint):textHint);
? ? ? ? //添加滑動監(jiān)聽
? ? ? ? rl_slide.setOnTouchListener(new OnTouchListener() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public boolean onTouch(View v, MotionEvent event) {
? ? ? ? ? ? ? ? DISTANCE_LIMIT= (int) (CustomSlideToUnlockView.this.getWidth()*THRESHOLD);//默認(rèn)閾值是控件寬度的一半
? ? ? ? ? ? ? ? switch (event.getAction()) {
? ? ? ? ? ? ? ? ? ? case MotionEvent.ACTION_DOWN://按下時(shí)記錄縱坐標(biāo)
? ? ? ? ? ? ? ? ? ? ? ? if(mIsUnLocked){//滑塊已經(jīng)在最右邊則不處理touch
? ? ? ? ? ? ? ? ? ? ? ? ? ? return false;
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? mLastX = (int) event.getRawX();//最后一個(gè)action時(shí)x值
? ? ? ? ? ? ? ? ? ? ? ? mActionDownX = (int) event.getRawX();//按下的瞬間x
? ? ? ? ? ? ? ? ? ? ? ? logI(TAG, mLastX + "X,=============================ACTION_DOWN");
? ? ? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? ? ? case MotionEvent.ACTION_MOVE://上滑才處理,如果用戶一開始就下滑,則過掉不處理
? ? ? ? ? ? ? ? ? ? ? ? logI(TAG, "=============================ACTION_MOVE");
? ? ? ? ? ? ? ? ? ? ? ? logI(TAG, "event.getRawX()============================="+event.getRawX());
? ? ? ? ? ? ? ? ? ? ? ? int dX = (int) event.getRawX() - mLastX;
? ? ? ? ? ? ? ? ? ? ? ? logI(TAG, "dX============================="+dX);
? ? ? ? ? ? ? ? ? ? ? ? mSlidedDistance = (int) event.getRawX() - mActionDownX;
? ? ? ? ? ? ? ? ? ? ? ? logI(TAG, "mSlidedDistance============================="+ mSlidedDistance);
? ? ? ? ? ? ? ? ? ? ? ? final MarginLayoutParams params = (MarginLayoutParams) v.getLayoutParams();
? ? ? ? ? ? ? ? ? ? ? ? int left = params.leftMargin;
? ? ? ? ? ? ? ? ? ? ? ? int top = params.topMargin;
? ? ? ? ? ? ? ? ? ? ? ? int right = params.rightMargin;
? ? ? ? ? ? ? ? ? ? ? ? int bottom = params.bottomMargin;
? ? ? ? ? ? ? ? ? ? ? ? logI(TAG, "left:"+left+",top:"+top+",right:"+right+",bottom"+bottom);
? ? ? ? ? ? ? ? ? ? ? ? int leftNew = left + dX;
? ? ? ? ? ? ? ? ? ? ? ? int rightNew =right - dX;
? ? ? ? ? ? ? ? ? ? ? ? if (mSlidedDistance > 0) {//直接通過margin實(shí)現(xiàn)滑動
? ? ? ? ? ? ? ? ? ? ? ? ? ? params.setMargins(leftNew, top, rightNew, bottom);
? ? ? ? ? ? ? ? ? ? ? ? ? ? logI(TAG, leftNew + "=============================MOVE");
? ? ? ? ? ? ? ? ? ? ? ? ? ? v.setLayoutParams(params);
? ? ? ? ? ? ? ? ? ? ? ? ? ? resetTextViewAlpha(mSlidedDistance);
? ? ? ? ? ? ? ? ? ? ? ? ? ? //回調(diào)
? ? ? ? ? ? ? ? ? ? ? ? ? ? if(mCallBack!=null){
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? mCallBack.onSlide(mSlidedDistance);
? ? ? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? ? ? mLastX = (int) event.getRawX();
? ? ? ? ? ? ? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? ? ? ? ? ? ? return true;
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? ? ? case MotionEvent.ACTION_UP:
? ? ? ? ? ? ? ? ? ? ? ? logI(TAG, "MotionEvent.ACTION_UP,之前移動的偏移值:" + ViewHelper.getTranslationY(v));
? ? ? ? ? ? ? ? ? ? ? ? if (Math.abs(mSlidedDistance) > DISTANCE_LIMIT) {
? ? ? ? ? ? ? ? ? ? ? ? ? ? scrollToRight(v);//右邊
//? ? ? ? ? ? ? ? ? ? ? ? ? ? scrollToLeft(v);//左邊
? ? ? ? ? ? ? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? ? ? ? ? ? ? scrollToLeft(v);//左邊
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? ? ? case MotionEvent.ACTION_CANCEL:
//? ? ? ? ? ? ? ? ? ? ? ? try {
//? ? ? ? ? ? ? ? ? ? ? ? ? ? if (vTracker != null) {
//? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? vTracker.recycle();
//? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? vTracker = null;
//? ? ? ? ? ? ? ? ? ? ? ? ? ? }
//? ? ? ? ? ? ? ? ? ? ? ? ? ? vTracker.recycle();
//? ? ? ? ? ? ? ? ? ? ? ? } catch (Exception e) {
//? ? ? ? ? ? ? ? ? ? ? ? ? ? e.printStackTrace();
//? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? return true;
? ? ? ? ? ? }
? ? ? ? });
? ? }
? ? private void logI(String tag,String content){
? ? ? ? if(LOG){
? ? ? ? ? ? Log.i(tag,content);
? ? ? ? }
? ? }
? ? /**
? ? * @method name:resetTextViewAlpha
? ? * @des:? 重置提示文本的透明度
? ? * @param :[mSlidedDistance]
? ? * @return type:void
? ? * @date 創(chuàng)建時(shí)間:2017/5/24
? ? * @author Chuck
? ? **/
? ? private void resetTextViewAlpha(int distance) {
? ? ? ? if(Math.abs(distance)>=Math.abs(DISTANCE_LIMIT)){
? ? ? ? ? ? tv_hint.setAlpha(0.0f);
? ? ? ? }
? ? ? ? else{
? ? ? ? ? ? tv_hint.setAlpha(1.0f-Math.abs(distance)*1.0f/Math.abs(DISTANCE_LIMIT));
? ? ? ? }
? ? }
? ? /**
? ? * @method name:scrollToLeft
? ? * @des:? 滑動未到閾值時(shí)松開手指,彈回到最左邊
? ? * @param :[v]
? ? * @return type:void
? ? * @date 創(chuàng)建時(shí)間:2017/5/24
? ? * @author Chuck
? ? **/
? ? private void scrollToLeft(final View v) {
? ? ? ? final MarginLayoutParams params1 = (MarginLayoutParams) v.getLayoutParams();
? ? ? ? logI(TAG, "scrollToLeft,ViewHelper.getTranslationX(v):" + ViewHelper.getTranslationX(v));
? ? ? ? logI(TAG, "scrollToLeft,params1.leftMargin:" + params1.leftMargin);
? ? ? ? logI(TAG, "scrollToLeft, params1.rightMargin:" + params1.rightMargin);
? ? ? ? ViewAnimator
? ? ? ? ? ? ? ? .animate( rl_slide)
? ? ? ? ? ? ? ? .translationX(ViewHelper.getTranslationX(v), -params1.leftMargin+15)
? ? ? ? ? ? ? ? .interpolator(new AccelerateInterpolator())
? ? ? ? ? ? ? ? .duration(DEAFULT_DURATIN_LONG)
? ? ? ? ? ? ? ? .onStop(new AnimationListener.Stop() {
? ? ? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? ? ? public void onStop() {
? ? ? ? ? ? ? ? ? ? ? ? MarginLayoutParams para = (MarginLayoutParams) v.getLayoutParams();
? ? ? ? ? ? ? ? ? ? ? ? logI(TAG, "scrollToLeft動畫結(jié)束para.leftMargin:" + para.leftMargin);
? ? ? ? ? ? ? ? ? ? ? ? logI(TAG, "scrollToLeft動畫結(jié)束para.rightMargin:" + para.rightMargin);
? ? ? ? ? ? ? ? ? ? ? ? logI(TAG, "scrollToLeft動畫結(jié)束,ViewHelper.getTranslationX(v):" + ViewHelper.getTranslationX(v));
? ? ? ? ? ? ? ? ? ? ? ? mSlidedDistance = 0;
? ? ? ? ? ? ? ? ? ? ? ? tv_hint.setAlpha(1.0f);
? ? ? ? ? ? ? ? ? ? ? ? mIsUnLocked=false;
? ? ? ? ? ? ? ? ? ? ? ? if(mCallBack!=null){
? ? ? ? ? ? ? ? ? ? ? ? ? ? mCallBack.onSlide(mSlidedDistance);
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? setImageDefault();
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? })
? ? ? ? ? ? ? ? .start();
? ? }
? ? /**
? ? **/
? ? private void scrollToRight(final View v) {
? ? ? ? final MarginLayoutParams params1 = (MarginLayoutParams) v.getLayoutParams();
? ? ? ? logI(TAG, "scrollToRight,ViewHelper.getTranslationX(v):" + ViewHelper.getTranslationX(v));
? ? ? ? logI(TAG, "scrollToRight,params1.leftMargin:" + params1.leftMargin);
? ? ? ? logI(TAG, "scrollToRight, params1.rightMargin:" + params1.rightMargin);
? ? ? ? //移動到最右端? 移動的距離是 父容器寬度-leftMargin
? ? ? ? ViewAnimator
? ? ? ? ? ? ? ? .animate( rl_slide)
? ? ? ? ? ? ? ? //.translationX(ViewHelper.getTranslationX(v), ViewHelper.getTranslationX(v)+100)
? ? ? ? ? ? ? ? .translationX(ViewHelper.getTranslationX(v), -params1.leftMargin+15)
//? ? ? ? ? ? ? ? .translationX(ViewHelper.getTranslationX(v), ( rl_slide.getWidth() - params1.leftMargin-slideImageViewWidth))
? ? ? ? ? ? ? ? //.translationX(params1.leftMargin, ( rl_slide.getWidth() - params1.leftMargin-100))
? ? ? ? ? ? ? ? .interpolator(new AccelerateInterpolator())
? ? ? ? ? ? ? ? .duration(DEAFULT_DURATIN_SHORT)
? ? ? ? ? ? ? ? .onStop(new AnimationListener.Stop() {
? ? ? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? ? ? public void onStop() {
? ? ? ? ? ? ? ? ? ? ? ? MarginLayoutParams para = (MarginLayoutParams) v.getLayoutParams();
? ? ? ? ? ? ? ? ? ? ? ? logI(TAG, "scrollToRight動畫結(jié)束para.leftMargin:" + para.leftMargin);
? ? ? ? ? ? ? ? ? ? ? ? logI(TAG, "scrollToRight動畫結(jié)束para.rightMargin:" + para.rightMargin);
? ? ? ? ? ? ? ? ? ? ? ? logI(TAG, "scrollToRight動畫結(jié)束,ViewHelper.getTranslationX(v):" + ViewHelper.getTranslationX(v));
? ? ? ? ? ? ? ? ? ? ? ? mSlidedDistance = 0;
? ? ? ? ? ? ? ? ? ? ? ? tv_hint.setAlpha(1.0f);
? ? ? ? ? ? ? ? ? ? ? ? mIsUnLocked=false;
//? ? ? ? ? ? ? ? ? ? ? ? if(slideImageViewResIdAfter>0){
//? ? ? ? ? ? ? ? ? ? ? ? ? ? iv_slide.setImageResource(slideImageViewResIdAfter);//滑塊imagview設(shè)置資源
//? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? //回調(diào)
? ? ? ? ? ? ? ? ? ? ? ? if(mCallBack!=null){
? ? ? ? ? ? ? ? ? ? ? ? ? ? mCallBack.onUnlocked();
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? })
? ? ? ? ? ? ? ? .start();
? ? }
? ? public void resetView(){
? ? ? ? mIsUnLocked=false;
? ? ? ? setImageDefault();
? ? ? ? scrollToLeft(rl_slide);
? ? }
? ? private void setImageDefault() {
? ? ? ? /**
? ? ? ? **/
? ? ? ? if(slideImageViewResId>0){
? ? ? ? ? ? iv_slide.setImageResource(slideImageViewResId);//滑塊imagview設(shè)置資源
? ? ? ? }
? ? }
? ? public interface CallBack{
? ? ? ? void onSlide(int distance);//右滑距離回調(diào)
? ? ? ? void onUnlocked();//滑動到了右邊,事件回調(diào)
? ? }
? ? public CallBack getmCallBack() {
? ? ? ? return mCallBack;
? ? }
? ? public void setmCallBack(CallBack mCallBack) {
? ? ? ? this.mCallBack = mCallBack;
? ? }
}
————————————————
版權(quán)聲明:本文為CSDN博主「weixin_36495794」的原創(chuàng)文章,遵循 CC 4.0 BY-SA 版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/weixin_36495794/article/details/102517617