package com.qin.zdlock;
import 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.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
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对象
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_pressed);
}
@Override
protected void onFinishInflate() {
// TODO Auto-generated method stub
super.onFinishInflate();
// 该控件主要判断是否处于滑动点击区域。滑动时 处于INVISIBLE(不可见)状态,滑动时处于VISIBLE(可见)状态
tv_slider_icon = (TextView) findViewById(R.id.slider_icon);
}
private int mLastMoveX = 1000; //当前bitmap应该绘制的地方 , 初始值为足够大,可以认为看不见
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
Log.i(TAG, "onTouchEvent" + " X is " + x + " Y is " + y);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mLastMoveX = (int) event.getX();
//处理Action_Down事件: 判断是否点击了滑动区域
return handleActionDownEvenet(event);
case MotionEvent.ACTION_MOVE:
mLastMoveX = x; //保存了X轴方向
invalidate(); //重新绘制
return true;
case MotionEvent.ACTION_UP:
//处理Action_Up事件: 判断是否解锁成功,成功则结束我们的Activity ;否则 ,缓慢回退该图片。
handleActionUpEvent(event);
return true;
}
return super.onTouchEvent(event);
}
// 绘制拖动时的图片
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
//Log.(TAG, "onDraw ######" );
// 图片更随手势移动
invalidateDragImg(canvas);
}
// 图片更随手势移动
private void invalidateDragImg(Canvas canvas) {
//Log.e(TAG, "handleActionUpEvenet : invalidateDragImg" );
//以合适的坐标值绘制该图片
int drawXCor = mLastMoveX - dragBitmap.getWidth();
int drawYCor = tv_slider_icon.getTop();
Log.i(TAG, "invalidateDragImg" + " drawXCor "+ drawXCor + " and drawYCor" + drawYCor);
canvas.drawBitmap(dragBitmap, drawXCor < 0 ? 5 : drawXCor , drawYCor , null);
}
// 手势落下是,是否点中了图片,即是否需要开始移动
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) //开始拖拽 ,隐藏该图片
tv_slider_icon.setVisibility(View.INVISIBLE);
//Log.e(TAG, "handleActionDownEvenet : isHit" + isHit);
return isHit;
}
//回退动画时间间隔值
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() ;
Log.e(TAG, "handleActionUpEvent : x -->" + x + " getRight() " + getRight() );
//距离在15dip以内代表解锁成功。
boolean isSucess= Math.abs(x - getRight()) <= 15 ;
if(isSucess){
Toast.makeText(mContext, "解锁成功", 1000).show();
resetViewState();
virbate(); //震动一下
//结束我们的主Activity界面
mainHandler.obtainMessage(MainActivity.MSG_LOCK_SUCESS).sendToTarget();
}
else {//没有成功解锁,以一定的算法使其回退
//每隔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();
}
}
}
//重置初始的状态,显示tv_slider_icon图像,使bitmap不可见
private void resetViewState(){
mLastMoveX = 1000 ;
tv_slider_icon.setVisibility(View.VISIBLE);
invalidate(); //重绘最后一次
}
//通过延时控制当前绘制bitmap的位置坐标
private Runnable BackDragImgTask = new Runnable(){
public void run(){
//一下次Bitmap应该到达的坐标值
mLastMoveX = mLastMoveX - (int)(BACK_DURATION * VE_HORIZONTAL);
Log.e(TAG, "BackDragImgTask ############# mLastMoveX " + mLastMoveX);
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){
Log.i(TAG, "handleMessage : #### " );
}
};
//震动一下下咯
private void virbate(){
Vibrator vibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(200);
}
public void setMainHandler(Handler handler){
mainHandler = handler;//activity所在的Handler对象
}
}
实用源码——Android屏幕锁源码.zip
需积分: 0 12 浏览量
更新于2023-11-04
收藏 1.2MB ZIP 举报
在本压缩包“实用源码——Android屏幕锁源码.zip”中,包含了安卓应用程序开发的实战案例,专注于屏幕锁的设计与实现。这个项目是为安卓开发者、学生以及对移动开发有兴趣的人提供的一种学习资源,特别适合于毕业设计、课程设计以及日常的安卓开发实践。下面我们将深入探讨其中涉及的主要知识点:
1. 安卓应用程序架构:了解一个完整的安卓应用如何从布局设计到功能实现。屏幕锁源码将展示如何构建Activity、Service、BroadcastReceiver等关键组件,以及它们之间的交互。
2. 用户界面设计(UI):Android Studio中的XML布局文件用于创建屏幕锁的图形界面。这包括使用LinearLayout、RelativeLayout或ConstraintLayout等布局管理器,以及自定义View控件来实现独特的解锁图案。
3. 触摸事件处理:屏幕锁通常依赖于用户在屏幕上绘制的路径,这就需要处理MotionEvent事件,解析用户的触摸轨迹并进行比较。
4. 数据存储:在安卓中,数据存储可以使用SharedPreferences、SQLite数据库等方式。屏幕锁可能需要存储用户的解锁图案或者密码,这就涉及到了数据的持久化。
5. 自定义动画:为了提升用户体验,屏幕锁可能包含各种动画效果,如解锁成功的反馈提示。这需要使用Android的Animation框架,包括Alpha、Scale、Translate和Rotate等动画类型。
6. 安全性:屏幕锁设计的一个重要方面是确保用户数据的安全。开发者需要理解如何加密存储用户设定的解锁信息,并防止未授权访问。
7. 权限管理:在Android系统中,获取和使用设备的一些功能(如读取联系人、使用摄像头等)需要获取相应的权限。屏幕锁源码会展示如何在AndroidManifest.xml中声明和管理权限。
8. 回调函数:理解Activity的生命周期方法,如onCreate()、onStart()、onResume()、onPause()等,以及如何在这些方法中进行屏幕锁逻辑的实现。
9. BroadcastReceiver:在某些情况下,屏幕锁可能需要监听系统事件,例如设备开机或解锁事件,这就需要用到BroadcastReceiver。
10. 多线程编程:为了保证用户体验,屏幕锁的某些操作可能需要在后台线程执行,比如复杂的计算或网络请求,这涉及到AsyncTask或者Handler/Looper机制。
11. 测试与调试:源码中可能包含了测试用例,帮助开发者检查和调试屏幕锁的功能,包括单元测试和集成测试。
通过深入研究这个屏幕锁源码,开发者不仅可以掌握Android开发的基本技能,还能了解到如何创建安全、易用且具有个性化的屏幕锁应用,这对于提升安卓开发能力大有裨益。
马coder
- 粉丝: 1249
- 资源: 6593
最新资源
- 【全年行事历】团建活动计划表.xlsx
- 【全年行事历】团建行程安排表-xx山.xlsx
- 【全年行事历】团建活动策划方案.docx
- 【全年行事历】团建开销费用分析.xlsx
- 【全年行事历】团建活动物料清单.xlsx
- 【全年行事历】团建文化衫尺码统计表.xlsx
- 【全年行事历】团建医药箱常备药清单.docx
- 【全年行事历】小型公司活动全年活动行事历.xlsx
- 【全年行事历】员工野外拓展活动方案.docx
- 四足机器人机械结构设计PDF
- 06-公司团建活动申请表.docx
- 03-团建活动策划方案.docx
- 07-团建活动采购预算清单.xlsx
- 08-团建日程计划表.xlsx
- 09-财务公司月度团建支出表.xlsx
- T-SQL查询高级SQLServer索引中的碎片和填充因子word文档doc格式最新版本