前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Android滑动解锁控件

Android滑动解锁控件

原创
作者头像
用户7999227
修改于 2021-09-23 03:04:43
修改于 2021-09-23 03:04:43
1.1K110
代码可运行
举报
文章被收录于专栏:Java小王子Java小王子
运行总次数:0
代码可运行
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
mport android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.os.Handler;
import android.os.Message;
import android.os.Vibrator;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.mosjoy.ad.R;
public class SliderRelativeLayout extends RelativeLayout {

private static String TAG = "SliderRelativeLayout";
private TextView tv_slider_icon = null; // 初始控件,用来判断是否为拖动?
private Bitmap dragBitmap = null; //拖拽图片
private Context mContext = null; // 初始化图片拖拽时的Bitmap对象
private Handler mainHandler = null; //与主Activity通信的Handler对象
private ImageView mPhoneImageView;
private ImageView mUnlockImageView;
private ImageView mMessageImageView;
private ImageView mCameraImageView;
private boolean mStopBoolean = false;
private Canvas mCanvas;
public SliderRelativeLayout(Context context) {
    super(context);
    mContext = context;
    initDragBitmap();
}

public SliderRelativeLayout(Context context, AttributeSet attrs) {
    super(context, attrs, 0);
    mContext = context;
    initDragBitmap();
}

public SliderRelativeLayout(Context context, AttributeSet attrs,
        int defStyle) {
    super(context, attrs, defStyle);
    mContext = context;
    initDragBitmap();
}

// 初始化图片拖拽时的Bitmap对象
private void initDragBitmap() {
    if (dragBitmap == null)
        dragBitmap = BitmapFactory.decodeResource(mContext.getResources(),
                R.drawable.getup_slider_ico_normal);
}

@Override
protected void onFinishInflate() {
    super.onFinishInflate();
    // 该控件主要判断是否处于滑动点击区域。滑动时 处于INVISIBLE(不可见)状态,滑动时处于VISIBLE(可见)状态
    tv_slider_icon = (TextView) findViewById(R.id.slider_icon);
    mPhoneImageView = (ImageView) findViewById(R.id.iv_phone);
    mUnlockImageView = (ImageView) findViewById(R.id.iv_unlock);
    mCameraImageView = (ImageView) findViewById(R.id.iv_camera);
    mMessageImageView = (ImageView) findViewById(R.id.iv_message);
}
private int mLastMoveX = 1000;  //当前bitmap应该绘制的地方 , 初始值为足够大,可以认为看不见
private int mLastMoveY = 1000;  //当前bitmap应该绘制的地方 , 初始值为足够大,可以认为看不见
public boolean onTouchEvent(MotionEvent event) {
    int x = (int) event.getX();
    int y = (int) event.getY();
    switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN:
        mLastMoveX = (int) event.getX();
        mLastMoveY = (int) event.getY();
        //处理Action_Down事件:  判断是否点击了滑动区域
        return handleActionDownEvenet(event);
    case MotionEvent.ACTION_MOVE:
        mLastMoveX = x; //保存了X轴方向
        mLastMoveY = y;
        invalidate(); //重新绘制   
        return true;
    case MotionEvent.ACTION_UP:
        //处理Action_Up事件:  判断是否解锁成功,成功则结束我们的Activity ;否则 ,缓慢回退该图片。
        handleActionUpEvent(event);
        return true;
    }
    return super.onTouchEvent(event);
}

// 绘制拖动时的图片
@Override
protected void onDraw (Canvas canvas) {
    super.onDraw(canvas);      
    // 图片更随手势移动
    if (!mStopBoolean) {
        invalidateDragImg(canvas);
    }
    mCanvas = canvas;
}

// 图片更随手势移动
private void invalidateDragImg(Canvas canvas) {
    //Log.e(TAG, "handleActionUpEvenet : invalidateDragImg" );
    //以合适的坐标值绘制该图片
    int drawXCor = mLastMoveX - dragBitmap.getWidth()/2;
    int drawYCor = mLastMoveY - dragBitmap.getHeight()/2;
    canvas.drawBitmap(dragBitmap,  drawXCor < 0 ? 5 : drawXCor , drawYCor , null);

//      isHitUnlock(canvas);
    }

// 手势落下是,是否点中了图片,即是否需要开始移动
private boolean handleActionDownEvenet(MotionEvent event) {
    Rect rect = new Rect();
    tv_slider_icon.getHitRect(rect);
    boolean isHit = rect.contains((int) event.getX(), (int) event.getY());
    //开始拖拽 ,隐藏该图片
    if(isHit && !mStopBoolean){ 
        tv_slider_icon.setVisibility(View.INVISIBLE);
        mPhoneImageView.setVisibility(View.VISIBLE);
        mUnlockImageView.setVisibility(View.VISIBLE);
        mMessageImageView.setVisibility(View.VISIBLE);
        mCameraImageView.setVisibility(View.VISIBLE);
    }
    return isHit;
}

//判断是否到达解锁点
private boolean isHitUnlock() {
    Rect phoneRect = new Rect();
    mPhoneImageView.getHitRect(phoneRect);
    Rect unlockRect = new Rect();
    mUnlockImageView.getHitRect(unlockRect);
    Rect messageRect = new Rect();
    mMessageImageView.getHitRect(messageRect);
    Rect cameraRect = new Rect();
    mCameraImageView.getHitRect(cameraRect);
    //解锁到电话界面
    if(phoneRect.contains(mLastMoveX,mLastMoveY)){
        mStopBoolean = true;
        adStopTwoSecond();
       //结束我们的主Activity界面
        Message msg = new Message();
        msg.what = MainLockActivity.MSG_PHONE_LOCK_SUCESS;
        mainHandler.sendMessageDelayed(msg, 2*1000);

//         mainHandler.obtainMessage(MainLockActivity.MSG_PHONE_LOCK_SUCESS).sendToTarget();
           return true;
        }else if(unlockRect.contains(mLastMoveX,mLastMoveY)){
            mStopBoolean = true;
            adStopTwoSecond();
            //结束我们的主Activity界面
            Message msg = new Message();
            msg.what = MainLockActivity.MSG_LOCK_SUCESS;
            mainHandler.sendMessageDelayed(msg, 21000);
            return true;
        }else if(messageRect.contains(mLastMoveX,mLastMoveY)){
            mStopBoolean = true;
            adStopTwoSecond();
            //结束我们的主Activity界面
            Message msg = new Message();
            msg.what = MainLockActivity.MSG_MESSAGE_LOCK_SUCESS;
            mainHandler.sendMessageDelayed(msg, 21000);
//          mainHandler.obtainMessage(MainLockActivity.MSG_MESSAGE_LOCK_SUCESS).sendToTarget();
            return true;
        }else if(cameraRect.contains(mLastMoveX,mLastMoveY)){
            mStopBoolean = true;
            adStopTwoSecond();
            //结束我们的主Activity界面
            Message msg = new Message();
            msg.what = MainLockActivity.MSG_CAMERA_LOOK_SUCESS;
            mainHandler.sendMessageDelayed(msg, 2*1000);
//          mainHandler.obtainMessage(MainLockActivity.MSG_CAMERA_LOOK_SUCESS).sendToTarget();
            return true;
        }
        return false;
    }

//回退动画时间间隔值
private static int BACK_DURATION = 20 ;   // 20ms
//水平方向前进速率
private static float VE_HORIZONTAL = 0.7f ;  //0.1dip/ms
//判断松开手指时,是否达到末尾即可以开锁了 , 是,则开锁,否则,通过一定的算法使其回退。
private void handleActionUpEvent(MotionEvent event){       
    int x = (int) event.getX() ;   
    int y = (int)event.getY();
    //解锁到电话界面
    if(isHitUnlock()){
    }else {
        mStopBoolean = false;
        //没有成功解锁,以一定的算法使其回退
        //每隔20ms , 速率为0.6dip/ms ,  使当前的图片往后回退一段距离,直到到达最左端  
        mLastMoveX = x ;  //记录手势松开时,当前的坐标位置。
        int distance = x - tv_slider_icon.getRight() ;
        //只有移动了足够距离才回退
        Log.e(TAG, "handleActionUpEvent : mLastMoveX -->" + mLastMoveX + " distance -->" + distance );
        if(distance >= 0)
            mHandler.postDelayed(BackDragImgTask, BACK_DURATION);
        else{  //复原初始场景
            resetViewState();
        }
    }
}

//暂停两秒
private void adStopTwoSecond() {
    mPhoneImageView.setVisibility(View.INVISIBLE);
    mUnlockImageView.setVisibility(View.INVISIBLE);
    mCameraImageView.setVisibility(View.INVISIBLE);
    mMessageImageView.setVisibility(View.INVISIBLE);

//      mCanvas.drawBitmap(dragBitmap, 2000, 2000, null);
        invalidate();
//      try {
//          Thread.sleep(2*1000);
//      } catch (InterruptedException e) {
//          e.printStackTrace();
//      }
    }

//重置初始的状态,显示tv_slider_icon图像,使bitmap不可见
private void resetViewState(){
    mLastMoveX = 1000;
    mLastMoveY = 1000;
    tv_slider_icon.setVisibility(View.VISIBLE);
    mPhoneImageView.setVisibility(View.INVISIBLE);
    mUnlockImageView.setVisibility(View.INVISIBLE);
    mCameraImageView.setVisibility(View.INVISIBLE);
    mMessageImageView.setVisibility(View.INVISIBLE);
    invalidate();        //重绘最后一次
}

//通过延时控制当前绘制bitmap的位置坐标
private Runnable BackDragImgTask = new Runnable(){
    public void run(){
        //一下次Bitmap应该到达的坐标值
        mLastMoveX = mLastMoveX - (int)(BACK_DURATION * VE_HORIZONTAL);
        invalidate();//重绘      
        //是否需要下一次动画 ? 到达了初始位置,不在需要绘制
        boolean shouldEnd = Math.abs(mLastMoveX - tv_slider_icon.getRight()) <= 8 ;         
        if(!shouldEnd)
            mHandler.postDelayed(BackDragImgTask, BACK_DURATION);
        else { //复原初始场景
            resetViewState();  
        }              
    }
};

private Handler mHandler =new Handler (){
    public void handleMessage(Message msg){
    }
};
//震动一下下咯
private void virbate(){
    Vibrator vibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);
    vibrator.vibrate(200);
}
public void setMainHandler(Handler handler){
    mainHandler = handler;//activity所在的Handler对象
}

}</pre> 

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
11 条评论
热度
最新
sudo: unknown user steam sudo: error initializing audit plugin sudoers_audit 发生这两个错误怎么办?
sudo: unknown user steam sudo: error initializing audit plugin sudoers_audit 发生这两个错误怎么办?
222举报
同问同问
同问同问
回复回复1举报
为啥都不用docker呢,1s就搞定了最新解决办法我的已经搞定了:https://www.playezu.com/810853.html PalWorld 幻兽帕鲁开服(Docker版)支持升级存档
为啥都不用docker呢,1s就搞定了最新解决办法我的已经搞定了:https://www.playezu.com/810853.html PalWorld 幻兽帕鲁开服(Docker版)支持升级存档
回复回复点赞举报
2月1号的更新你们2月3号出教程,到了2月27号再次更新 页面都不一样了 怎么更?
2月1号的更新你们2月3号出教程,到了2月27号再次更新 页面都不一样了 怎么更?
回复回复1举报
在这里执行命令不用获取管理员权限了吗 也不用停止和重启游戏了吗
在这里执行命令不用获取管理员权限了吗 也不用停止和重启游戏了吗
回复回复1举报
在这里执行命令不用获取管理员权限了吗
在这里执行命令不用获取管理员权限了吗
回复回复点赞举报
windows版如果命令运行好了还是不兼容可以再执行几次命令
windows版如果命令运行好了还是不兼容可以再执行几次命令
回复回复点赞举报
回复回复点赞举报
更新好了,谢谢大佬,主要是今天一直在用公共命令里的那个更新,一直执行失败
更新好了,谢谢大佬,主要是今天一直在用公共命令里的那个更新,一直执行失败
11点赞举报
哈哈多谢,欢迎来交流群帮更多的人成功更新游戏。
哈哈多谢,欢迎来交流群帮更多的人成功更新游戏。
回复回复点赞举报
我一直执行失败是什么原因
我一直执行失败是什么原因
回复回复点赞举报
推荐阅读
编辑精选文章
换一批
Android自定义控件之滑动解锁
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/149102.html原文链接:https://javaforall.cn
全栈程序员站长
2022/09/12
2.1K0
Android自定义控件之滑动解锁
Android滑动解锁功能实现,Android_滑动解锁
图片资源:https://pan.baidu.com/s/1tkcw0tdxV78mnwHqOtcAGg
全栈程序员站长
2022/09/07
1.3K0
一个可以拖动的自定义Gridview代码
这个可以拖动的gridview继承于gridview,所以,用法和gridview一样, 代码如下: public class DragGridView extends GridView { private long dragResponseMS = 700; // item长按响应的时间 private int mDragPosition;// 正在拖拽的position private boolean isDrag = false; // 是否可以拖拽,用于控件内部逻辑实现
xiangzhihong
2018/02/01
1.1K0
10.下拉刷新、加载更多、标记已读、轮播条、缓存
下拉刷新、加载更多、标记已读、轮播条、缓存 下拉刷新------- 1.addHeaderView必须在setAdapter之前调用 2.将paddingTop设置一个headerView高度的负值去隐藏它 getHeight()和getMeasuredHeight()的区别: getMeasuredHeight():获取测量完的高度,只要在onMeasure方法执行完,就可以用                    它获取到宽高,在自定义控件内部多使用这个 使用view.measure(0
六月的雨
2018/05/14
1.2K0
可拖拽gridview
在Android开发中,我们常常用到ListView和GridView,而有的时候系统的ListView,GridView并不能满足我们的需求,所以我们需要自己定义一个ListView或者GridView,我的上一篇文章中就是自定义的一个左右滑动删除item的例子,大家有兴趣的可以去看看 Android 使用Scroller实现绚丽的ListView左右滑动删除Item效果,今天这篇文章就给大家来自定义GridView的控件,GridView主要是来显示网格的控件,在Android的开发中使用很普通,相对
xiangzhihong
2018/01/29
5.1K0
可拖拽gridview
android滑动监听事件折叠菜单
1.定义两个title布局 2.监听ScrollView控件在下面布局不可见的时候显示第二个title布局
tea9
2022/07/16
2K0
android滑动监听事件折叠菜单
Android 高德地图API(详细步骤+源码)七
在RouteActivity中找到onRideRouteSearched方法,方法里面添加如下代码:
晨曦_LLW
2021/03/04
1.8K4
Android 高德地图API(详细步骤+源码)七
6.下拉刷新
下拉刷新------- 1.addHeaderView必须在setAdapter之前调用 2.将paddingTop设置一个headerView高度的负值去隐藏它 getHeight()和getMeasuredHeight()的区别: getMeasuredHeight():获取测量完的高度,只要在onMeasure方法执行完,就可以用                     它获取到宽高,在自定义控件内部多使用这个 使用view.measure(0,0)方法可以主动通知系统去测量,然后就 可
六月的雨
2018/05/14
1.7K0
相关推荐
Android自定义控件之滑动解锁
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验