惠锁屏实现侧滑锁屏(侧滑锁屏的原理)


上面是效果图。
锁屏总体来说 注意的地方就两点 
 ①  关闭电源 重启 的时候 保证锁屏界面可以出现,
 ②  按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();
					//① 左边图片 右边界 距离屏幕左边的距离
				    leftImageView_right = leftImageView.getRight();
					//① 右两边图片的右边界距离屏幕左边的距离
					rightImageView_right = rightImageView.getRight();
					//① 右两边图片的左边 距离屏幕左边的距离
					rightImageView_left = rightImageView.getLeft();
					//改一下 圆环  大的 变成小的
					img.setImageDrawable(getResources().getDrawable(R.drawable.lock_slide_icon_pressed));
					height = (int) (event.getRawY() - 50);
					left = v.getLeft();
					right = v.getRight();
					top = v.getTop();
					bottom = v.getBottom();
					break;
				case MotionEvent.ACTION_MOVE:
				//② 记录 中间圆环距离屏幕左边界距离 
					mx = (int) (event.getRawX()); 
					//② 记录 中间圆环距离屏幕上边界距离
					my = (int) (event.getRawY() - 50);
					// ②这里的 with 是手机屏幕的宽度,如果 圆环距离屏幕左边距离小于手机屏幕宽度的二分之一  说明向左滑动 
					if (mx < width / 2) {
					    // ②这里是判断  有没有滑动到左边图片的右边,如果 小于 说明 圆环 跟左边的图片 已经发生了接触,一旦接触 让 圆环移动到已左边图片中心的位置。
						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) {
                        //②这里的 with 是手机屏幕的宽度,如果 圆环距离屏幕左边距离大于手机屏幕宽度的二分之一  说明向右滑动 
						if ((mx + img.getWidth() / 2) < rightImageView_right) { // 右边跟左边同理,。。。
							v.layout(mx - img.getWidth() / 2, top, mx + img.getWidth() / 2, bottom);
						}
						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  、MotionEvent.ACTION_UP
这里要介绍一下 getRawX() 与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 最后 上代码 :下载地址----------*******************-------------


  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值