仿 惠锁屏 侧滑锁屏的原理

上面是效果图。

锁屏 总体来说 注意的地方 就两点  一个是  关闭电源 重启 的时候 保证  锁屏界面可以出现, 另一个就是  按home键的时候 不要返回 桌面。

对于  唤醒 电源键  和重启手机时候 弹出锁屏界面 ,可以通过监听 电源 唤醒的 广播,开机广播。

1) 待机:

广播消息:android.intent.action.SCREEN_OFF

2) 唤醒:

广播消息:android.intent.action.SCREEN_ON 

3) 开机

广播消息:android.intent.action.BOOT_COMPLETED

对于屏蔽home 键   我在网上找了一些方法 大致如下,但是很遗憾 都有问题。

在2.3版本以下重写下面方法就能重写home键

public void onAttachedToWindow() {

this.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD);

super.onAttachedToWindow();

}

在4.0以上的版本中需要利用以下方法屏蔽和重写Home键,代码如下:

public static final int FLAG_HOMEKEY_DISPATCHED = 0x80000000; //需要自己定义标志

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

this.getWindow().setFlags(FLAG_HOMEKEY_DISPATCHED, FLAG_HOMEKEY_DISPATCHED);//关键代码

setContentView(R.layout.main);

}

再重写onKey事件即可。

@Override

public boolean onKeyDown( int keyCode, KeyEvent event) {

// TODO Auto-generated method stub

if (keyCode == event. KEYCODE_HOME) {

return true;

}

return super.onKeyDown(keyCode, event);

      }

PS:

在AndroidMainfest.xml需要加权限:

<uses-permission android:name = "android.permission.DISABLE_KEYGUARD"/><!-- 屏蔽HOME键需要的权限 -->

在配置文件中,在你使用了Notification的activity中加一个属性android: android:launchMode="singleInstance"

很遗憾 上面的方法 会导致  手机黑屏 。。。。 

而且 home键 监听 我们的权限不够,只能想办法 绕过去了,我的思路是 在 点击 home 键 的时候 

 在加载一次当前的界面。 保证 不被 退回到后台中。 稍后 代码中解释。

上面两点  就是 我认为 锁屏 的 关键地方。

下面 在说一下   侧滑界面的实现。 先说原理    中间 是一个大的○  左边 右边 各一个图片。

滑动图片  主要就是 图片的 touch 事件, 图片随着手指落下的位置 移动,当移动到左边图片相交时,我选择让其 直接 以左边图片的中心 为圆心  ,不在让其跟随手指滑动。 同理 右边。 

这里左右图片的半径 其实就是图片宽度的 1/2   (说半径不合适 因为都不是○。记得 是宽度 1/2 就OK)

当○ 往左滑动, 一旦与左边图片相交 也就是绿色线的地方,

让中间的○以 左边图片的中心  。并且此时在往左滑动,也不让中间的○移动, 左边界就是 左图 的中心, 同理 中间大圆环 能滑到右边的 最远距离  就是右图 的 中心的 ○。

原理 就说这些。。。。。。。。。。。。。。。

======================================================================================================

下面稍微介绍下项目 。首先  先实现左右滑动的效果。 那么先把布局做出来,布局就是上面图片中的 三个图片

很简单的布局

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:background="#000000"
    tools:context=".MainActivity" >

        <ImageView
            android:id="@+id/iv_drag"
            android:layout_centerInParent="true"
            android:src="@drawable/lock_slide_icon_normal_no_quick_launcher"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
        <ImageView
            android:layout_alignParentLeft="true"
            android:id="@+id/iv_left"
            android:layout_centerInParent="true"
            android:src="@drawable/lock_left_download_icon_normal"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
        <ImageView
              android:layout_alignParentRight="true"
            android:id="@+id/iv_right"
            android:layout_centerInParent="true"
            android:src="@drawable/lock_right_icon_normal"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>

</RelativeLayout>

 下面看怎么用这个布局 , 这里定义 一个 LockView  继承  RelativeLayout ,在构造方法中 找到三个图片的id , 并  实现  中间○的 touch 事件,

 

img.setOnTouchListener(new OnTouchListener() {
			private int height;

			public boolean onTouch(View v, MotionEvent event) {

				switch (event.getAction()) {

				case MotionEvent.ACTION_DOWN:
					// leftImageView_left:32rightImageView_right:688
					leftImageView_left = leftImageView.getLeft();<span style="font-family: KaiTi_GB2312;">① 左边图片的左边界 距离屏幕左边距离</span>
				        leftImageView_right = leftImageView.getRight();<span style="font-family: KaiTi_GB2312;">① 左边图片 右边界 距离屏幕左边的距离</span>
					rightImageView_right = rightImageView.getRight();<span style="font-family: KaiTi_GB2312;">① 右两边图片的右边界距离屏幕左边的距离</span>
					rightImageView_left = rightImageView.getLeft();<span style="font-family: KaiTi_GB2312;">① 右两边图片的左边 距离屏幕左边的距离</span>
					System.out.println("leftImageView_left:" + leftImageView_left + "rightImageView_right:" + rightImageView_right);
					img.setImageDrawable(getResources().getDrawable(R.drawable.lock_slide_icon_pressed));//改一下 圆环  大的 变成小的
					System.out.println("event.getRawX()" + event.getRawX() + "event.getRawY()" + event.getRawY());
					System.out.println("event.getX()" + event.getX() + "event.getY()" + event.getY());
					height = (int) (event.getRawY() - 50);
					System.out.println("v.getTop()" + v.getTop() + "event.getBottom()" + v.getBottom() + "v.getLeft()" + v.getLeft() + "v.getRight" + v.getRight());
					left = v.getLeft();
					right = v.getRight();
					top = v.getTop();
					bottom = v.getBottom();
					break;
				case MotionEvent.ACTION_MOVE:
					System.out.println("----------event.getRawX()" + event.getRawX() + "event.getRawY()" + event.getRawY());
					System.out.println("----------event.getX()" + event.getX() + "event.getY()" + event.getY());
					mx = (int) (event.getRawX()); //② 记录 中间圆环距离屏幕左边界距离
					my = (int) (event.getRawY() - 50);//<span style="font-family:KaiTi_GB2312;">② 记录 中间圆环距离屏幕上边界距离</span>
					Log.i(TAG1, "  mx " + mx + "   my" + my + "  img.getWidth()/2" + img.getWidth() / 2 + "   img.getHeight()/2" + img.getHeight() / 2);
					if (mx < width / 2) {// ②这里的 with 是手机屏幕的宽度,如果 圆环距离屏幕左边距离小于手机屏幕宽度的二分之一  说明向左滑动
						if (mx < leftImageView_right) {// ②这里是判断  有没有滑动到左边图片的右边,如果 小于 说明 圆环 跟左边的图片 已经发生了接触,一旦接触 让 圆环移动到已左边图片中心的位置。
							v.layout(leftImageView_left, top, leftImageView_right, bottom);
							left_flag = true //② 标志  如果到了这个位置 代表滑到最左边了,此时松手 会解锁屏幕
						} else {// 没有接触 那就 按移动的位置去 重新绘制 圆环 layout(l ,t, r, b)   // ②左  上 右 下 四个坐标
							v.layout(mx - img.getWidth() / 2, top, mx + img.getWidth() / 2, bottom);
							left_flag = false;
						}

					} else if (mx > width / 2) {//②<span style="font-family: KaiTi_GB2312;">这里的 with 是手机屏幕的宽度,如果 圆环距离屏幕左边距离大于手机屏幕宽度的二分之一  说明向右滑动 </span>

						if ((mx + img.getWidth() / 2) < rightImageView_right) { // 右边跟左边同理,。。。
							v.layout(mx - img.getWidth() / 2, top, mx + img.getWidth() / 2, bottom);
							Log.i(TAG2, "  int l " + (mx - img.getWidth() / 2) + "   int top" + (my - img.getHeight() / 2) + "    int right" + (mx + img.getWidth() / 2)
									+ "   int bottom" + (my + img.getHeight() / 2));
						}// 688

						if (mx > rightImageView_left) {
							v.layout(rightImageView_left, top, rightImageView_right, bottom);
							right_flag = true;
						} else {
							v.layout(mx - img.getWidth() / 2, top, mx + img.getWidth() / 2, bottom);
							right_flag = false;
						}
					}
					break;

				case MotionEvent.ACTION_UP:

					if (right_flag) {// ③  右边解锁
						Toast.makeText(mContext, "解锁右边", 0).show();
						Intent i = new Intent(mContext, MyService.class);
						i.setAction(MyService.UNLOCK_ACTION); // ***********************这里 是解锁的关键。 到服务里面详细说*************
						mContext.startService(i);

					} else if (left_flag) {
						Toast.makeText(mContext, "解锁左边", 0).show();
						Intent i2 = new Intent(mContext, MyService.class);
						i2.setAction(MyService.UNLOCK_ACTION);
						mContext.startService(i2);
					}
					right_flag = false;
					left_flag = false;
					v.layout(left, top, right, bottom);  // ③恢复圆环的初始位置
					img.setImageDrawable(getResources().getDrawable(R.drawable.lock_slide_icon_normal_no_quick_launcher));// ③将圆环 换回原来的 大圆环
					break;
				}

				return true;
			}
		});

touch  事件 主要 就是  三个动作 手  按下    手移动   手 抬起 。

对应  

MotionEvent.ACTION_DOWN     
MotionEvent.ACTION_MOVE         
<strong style="font-family: KaiTi_GB2312; background-color: rgb(255, 255, 255);"></strong><pre name="code" class="java" style="display: inline !important;">MotionEvent.ACTION_UP

<strong style="font-family: KaiTi_GB2312; background-color: rgb(255, 255, 255);"></strong><pre name="code" class="java" style="display: inline !important;">

<strong style="font-family: KaiTi_GB2312; background-color: rgb(255, 255, 255);"></strong><pre name="code" class="java" style="display: inline !important;"><span style="font-family: KaiTi_GB2312;"></span>

<strong style="font-family: KaiTi_GB2312; background-color: rgb(255, 255, 255);"></strong><pre name="code" class="java" style="display: inline !important;"><span style="font-family: KaiTi_GB2312;">
</span>

这里要介绍一下 get

RawX()


与getX() 区别。 一张图

 很明白的一张图, R 是 取得 距离 屏幕 边距的距离 不带Raw 的是取得距离父布局 的边界距离。

按下 的动作中我们需要做什么? 按下时 主要操作 看代码 中的① 注释


手移动
 的动作中我们需要做什么? 按下时 主要操作 看代码 中的② 注释

在抬起 的动作中我们需要做什么? 按下时 主要操作 看代码 中的③ 注释

OK
实现 手可以控制 圆环 左右滑动后, 我们去实现 解锁屏幕

这个功能在服务里面实现

关键代码如下 :

public int onStartCommand(Intent intent, int flags, int startId) {

		if(intent!=null){
			System.out.println("intent------------intent.getAction()-==null?????--"+(intent==null));
			String action = intent.getAction();
			if(TextUtils.equals(action, LOCK_ACTION)) // 这是屏蔽 home 键的关键
				addView();
			else if(TextUtils.equals(action, UNLOCK_ACTION))   // 这里是解锁屏幕
			{
				removeView();
//				stopSelf();
			}
		}
		return Service.START_STICKY;
	}

屏蔽home键的原理  上面说过  是  在加载一次 当前布局。   也就是通过action 判断的。

在 我们上面 手滑动到左右两边的时候 我们 做的操作是

Intent i = new Intent(mContext, MyService.class);
i.setAction(MyService.UNLOCK_ACTION); // ***********************这里 是解锁的关键。 到服务里面详细说*************
mContext.startService(i);

传过去一个 Action 代表 是解锁

其他情况下 的Action 都是 锁定。

那么 还剩下一个问题 就是保持  手机    唤醒屏幕时候能用弹出锁屏界面

同样 在服务里面 注册两个广播保证 手机唤醒的时候  开启服务

public void onCreate() {
		super.onCreate();

		mContext = getApplicationContext();
		mWinMng = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);

		i = new Intent(mContext, MyService.class);
		i.setAction(MyService.LOCK_ACTION);
		zdLockIntent = new Intent(MyService.this , MyService.class);
		zdLockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

		/*注册广播*/
		IntentFilter mScreenOnFilter = new IntentFilter("android.intent.action.SCREEN_ON");
		MyService.this.registerReceiver(mScreenOnReceiver, mScreenOnFilter);

		/*注册广播*/
		IntentFilter mScreenOffFilter = new IntentFilter("android.intent.action.SCREEN_OFF");
		MyService.this.registerReceiver(mScreenOffReceiver, mScreenOffFilter);
	}

广播 中 判断 当Action  是  唤醒屏幕的时候   去开启一下服务。

	//屏幕变暗/变亮的广播 , 我们要调用KeyguardManager类相应方法去解除屏幕锁定
	private BroadcastReceiver mScreenOffReceiver = new BroadcastReceiver(){
		@Override
		public void onReceive(Context context , Intent intent) {
			String action = intent.getAction() ;

		    Log.i(TAG, intent.toString());

			if(action.equals("android.intent.action.SCREEN_OFF")
					|| action.equals("android.intent.action.SCREEN_ON") ){
				mKeyguardManager = (KeyguardManager)context.getSystemService(Context.KEYGUARD_SERVICE);
				mKeyguardLock = mKeyguardManager.newKeyguardLock("zdLock 1");
				mKeyguardLock.disableKeyguard();
//				startService(zdLockIntent);

		        //Intent.FLAG_ACTIVITY_NEW_TASK. This flag is generally used by activities that want to present a "launcher" style behavior
				startService(i);
			}
		}

	};

	//屏幕变亮的广播,我们要隐藏默认的锁屏界面
	private BroadcastReceiver mScreenOnReceiver = new BroadcastReceiver(){

		@Override
		public void onReceive(Context context , Intent intent) {

            Log.i(TAG, intent.getAction());

			if(intent.getAction().equals("android.intent.action.SCREEN_ON")){
				Log.i(TAG, "----------------- android.intent.action.SCREEN_ON------");
				mKeyguardManager = (KeyguardManager)context.getSystemService(Context.KEYGUARD_SERVICE);
				mKeyguardLock = mKeyguardManager.newKeyguardLock("zdLock 1");
				mKeyguardLock.disableKeyguard();

		        //Intent.FLAG_ACTIVITY_NEW_TASK. This flag is generally used by activities that want to present a "launcher" style behavior
				startService(i);

			}
		}

	};

//
这里注意把 手机系统自带的 锁屏 屏蔽掉。

最后别忘了
权限, 看下 清单文件:

<uses-permission android:name = "android.permission.DISABLE_KEYGUARD"/><!-- 屏蔽HOME键需要的权限 -->
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.DISABLE_KEYGUARD"/>
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:theme="@android:style/Theme.Translucent"
            android:name="com.example.mylock.MainActivity"
            android:label="@string/app_name" >
          <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <receiver android:name=".BootCompletedReciever" android:permission="android.permission.RECEIVE_BOOT_COMPLETED" >
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </receiver>
            <service android:name=".MyService" >
        </service>
    </application>

OK
最后 上代码 : 下载地址----------*******************-------------

时间: 2024-10-08 12:13:11

仿 惠锁屏 侧滑锁屏的原理的相关文章

仿QQ黑屏、锁屏、程序切换等手势密码

仿QQ黑屏.锁屏.程序切换等手势密码 仿九宫格绘制手势锁屏,设置手势时,两次一样才成功,黑屏后即锁屏,需绘制手势解锁 下载地址:http://www.devstore.cn/code/info/1056.html 运行截图:     版权声明:本文为博主原创文章,未经博主允许不得转载.

sql server对并发的处理-乐观锁和悲观锁

假如两个线程同时修改数据库同一条记录,就会导致后一条记录覆盖前一条,从而引发一些问题. 例如: 一个售票系统有一个余票数,客户端每调用一次出票方法,余票数就减一. 情景: 总共300张票,假设两个售票点,恰好在同一时间出票,它们做的操作都是先查询余票数,然后减一. 一般的sql语句: 1 2 3 4 5 6 7 8 9 declare @count as int begin tran     select @count=count from ttt     WAITFOR DELAY '00:0

一分钟教你知道乐观锁和悲观锁的区别

悲观锁(Pessimistic Lock), 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁.传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁. 乐观锁(Optimistic Lock), 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制.乐观锁适用于

【锁】Oracle锁系列

[锁]Oracle锁系列 1  BLOG文档结构图 2  前言部分 2.1  导读和注意事项 各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到一些其它你所不知道的知识,~O(∩_∩)O~: ① 锁的概念.分类.及其模拟 ② 查询锁的视图及视图之间的关联 ③ 锁的参数(DML_LOCKS.DDL_LOCK_TIMEOUT) ④ FOR UPDATE及FOR UPDATE OF系列 ⑤ 带ONLINE和不带ONLINE创建索引的锁情况(是否阻塞DML操作) ⑥ 包或存过不能编译的解决方法

悲观锁与乐观锁的区别

悲观锁(Pessimistic Lock), 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁.传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁. 乐观锁(Optimistic Lock), 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制.乐观锁适用于

redis锁 和悲观锁的并发问题

1.在业务流程前后中,用到了redis锁 和 悲观锁两种不同的锁. 2.汇总账单的时候,从库中读取数据,将读取到的实收额也跟着更新,而在收费的时候添加了悲观锁, 在读账单表的时候 用到了 forupdate,但是redis锁那块同样会产生并发,因为redis锁那块在查询库的时候也需要对账单for update,这样可以防止并发,在悲观锁里若还没更新 则redis锁不去执行更新 3.解决方案 有上面的一个在 redis锁中的查询账单表的时候同样 for update,另外一种则是 对与我们业务相关

原子属性与非原子属性,互斥锁与自旋锁介绍

nonatomic 非原子属性 非线程安全,适合内存小的移动设备(手机,平板...) atomic 原子属性(线程安全,但需要消耗大量资源)针对多线程设计的,为默认值,保证同一时间只有一个线程能够写入;本身就是一把自旋锁;单写多读,单个线程写入,多个线程读取 注意:当重写属性的get与set方法时需要在@implementation后添加:@synthesiae 属性名 = _属性名; 互斥锁与自旋锁对比 互斥锁:如果发现其他线程正在执行锁定代码,线程会进入休眠(就绪状态),等其他线程时间到打开

[数据库事务与锁]详解七: 深入理解乐观锁与悲观锁

注明: 本文转载自http://www.hollischuang.com/archives/934 在数据库的锁机制中介绍过,数据库管理系统(DBMS)中的并发控制的任务是确保在多个事务同时存取数据库中同一数据时不破坏事务的隔离性和统一性以及数据库的统一性. 乐观并发控制(乐观锁)和悲观并发控制(悲观锁)是并发控制主要采用的技术手段. 无论是悲观锁还是乐观锁,都是人们定义出来的概念,可以认为是一种思想.其实不仅仅是关系型数据库系统中有乐观锁和悲观锁的概念,像memcache.hibernate.

(转)java并发对象锁、类锁、私有锁

转自:http://ifeve.com/java-locks/ 建议参考:http://www.zhihu.com/question/28113814 Java类锁和对象锁实践 感谢[jiehao]同学的投稿,投稿可将文章发送到[email protected] 类锁和对象锁是否会冲突?对象锁和私有锁是否会冲突?通过实例来进行说明. 一.相关约定 为了明确后文的描述,先对本文涉及到的锁的相关定义作如下约定: 1. 类锁:在代码中的方法上加了static和synchronized的锁,或者sync