Android锁屏页功能的实现

做完蓝牙功能,客户说其他的音乐播放器都有锁屏页功能,我也想要。对于难缠的客户的要求只能面向百度的编程,在百度一些东西后有一些思路。思路来源链接
首先在清单文件添加权限:

 <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中添加锁屏页activity的注册:
<activity android:name=".LockActivity"
            android:excludeFromRecents="true"
            android:exported="false"
            android:launchMode="singleInstance"
            android:noHistory="true"
            android:screenOrientation="portrait"
            android:taskAffinity="com.package.name.lockscreen"
            android:theme="@style/LockScreenTheme"></activity>

在styles.xml文件中添加效果:

<style name="LockScreenTheme" parent="AppTheme">
        <item name="android:windowIsTranslucent">true</item>
        <item name="android:windowBackground">@android:color/transparent</item>
        <item name="android:colorBackgroundCacheHint">@null</item>
        <item name="android:backgroundDimEnabled">false</item>
        <item name="android:windowAnimationStyle">@null</item>
        <item name="android:windowContentOverlay">@null</item>
    </style>

写LockActivity的代码:

public class LockActivity extends AppCompatActivity  implements SlidingFinishLayout.OnSlidingFinishListener{

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.getWindow().addFlags(
                WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
                        | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);

        fullScreen(this);
        setContentView(R.layout.activity_locks);
        initView();


    }

    /**
     * 通过设置全屏,设置状态栏透明
     *
     * @param activity
     */
    public static void fullScreen(Activity activity) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                //5.x开始需要把颜色设置透明,否则导航栏会呈现系统默认的浅灰色
                Window window = activity.getWindow();
                View decorView = window.getDecorView();
                //两个 flag 要结合使用,表示让应用的主体内容占用系统状态栏的空间
                int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                        | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
                decorView.setSystemUiVisibility(option);
                window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
                window.setStatusBarColor(Color.TRANSPARENT);

            } else {
                Window window = activity.getWindow();
                WindowManager.LayoutParams attributes = window.getAttributes();
                int flagTranslucentStatus = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
                attributes.flags |= flagTranslucentStatus;
                window.setAttributes(attributes);
            }
        }
    }


    private void initView() {
        TextView tvLockTime = findViewById(R.id.lock_time);
        TextView tvLockDate = findViewById(R.id.lock_date);
        SlidingFinishLayout vLockRoot = findViewById(R.id.lock_root);
        vLockRoot.setOnSlidingFinishListener(this);

        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm-M月dd日 E", Locale.CHINESE);
        String[] date = simpleDateFormat.format(new Date()).split("-");
        tvLockTime.setText(date[0]);
        tvLockDate.setText(date[1]);
    }

    /**
     * 重写物理返回键,使不能回退
     */
    @Override
    public void onBackPressed() {
    }

    /**
     * 滑动销毁锁屏页面
     */
    @Override
    public void onSlidingFinish() {
        finish();
    }


}

对应xml文件 activity_locks.xml布局:(按钮的事件监听没有写,根据自己需要自己添加)

<com.apps.utils.view.SlidingFinishLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:nono="http://com.demo0.nono"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/lock_root"
    android:background="#242424"
    tools:context=".LockActivity">

    <TextView
        android:textColor="#ffffff"
        android:layout_marginTop="50dp"
        android:layout_marginLeft="39dp"
        android:layout_alignParentTop="true"
        android:text="17:30"
        android:textSize="38sp"
        android:id="@+id/lock_time"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:textColor="#ffffff"
        android:layout_marginTop="5dp"
        android:layout_alignLeft="@id/lock_time"
        android:layout_below="@id/lock_time"
        android:text="12月21日 星期三"
        android:includeFontPadding="false"
        android:textSize="20sp"
        android:id="@+id/lock_date"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <ImageView
        android:id="@+id/imageView_noti"
        android:layout_width="200dp"
        android:layout_height="220dp"
        android:layout_marginTop="180dp"
        android:layout_centerHorizontal="true"
        app:srcCompat="@mipmap/app_icon"/>


    <TextView
        android:id="@+id/textView_noti_name"
        android:layout_below="@+id/imageView_noti"
        android:layout_marginTop="40dp"
        android:layout_centerHorizontal="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="歌曲名称"
        android:textSize="20sp"
        android:textColor="#ffffff"/>
    <TextView
        android:id="@+id/textView_noti_artist"
        android:layout_below="@+id/textView_noti_name"
        android:layout_marginTop="16dp"
        android:layout_centerHorizontal="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="专辑名称"
        android:textSize="16sp"
        android:textColor="#ffffff"/>

    <LinearLayout
        android:gravity="center_vertical"
        android:orientation="horizontal"
        android:id="@+id/buttons"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:divider="?android:listDivider"
        android:layout_below="@id/textView_noti_name"
        android:layout_above="@id/hinttextview"
        android:layout_centerHorizontal="true"
        android:showDividers="middle"
        android:dividerPadding="12dp">

        <ImageButton
            android:id="@+id/imageView_noti_prev"
            android:background="?android:selectableItemBackground"
            android:padding="10dp"
            android:layout_width="0dp"
            android:layout_height="58dp"
            android:src="@android:drawable/ic_media_previous"
            android:scaleType="fitCenter"
            android:layout_weight="1.0" />

        <ImageButton
            android:id="@+id/imageView_noti_play"
            android:background="?android:selectableItemBackground"
            android:padding="10dp"
            android:layout_width="0dp"
            android:layout_height="58dp"
            android:src="@android:drawable/ic_media_play"
            android:scaleType="fitCenter"
            android:layout_weight="1.0" />

        <ImageButton
            android:id="@+id/imageView_noti_next"
            android:background="?android:selectableItemBackground"
            android:padding="10dp"
            android:layout_width="0dp"
            android:layout_height="58dp"
            android:src="@android:drawable/ic_media_next"
            android:scaleType="fitCenter"
            android:layout_weight="1.0" />

    </LinearLayout>

    <com.apps.utils.view.HintTextView
        android:id="@+id/hinttextview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_alignParentBottom="true"
        android:layout_marginBottom="30dp"
        android:includeFontPadding="false"
        android:text=">>> 滑动解锁"
        android:textColor="#ffffff"
        android:textSize="18sp"/>
</com.apps.utils.view.SlidingFinishLayout>

其中用到的两个工具类,可根据自己工程的位置更换布局中的路径:
HintTextView.class

public class HintTextView extends AppCompatTextView {

    private Paint paint;
    
    private int mWidth;
    private LinearGradient gradient;
    private Matrix matrix;
    /**
     * 渐变的速度
     */
    private int deltaX;

    public HintTextView(Context context) {
        super(context, null);
    }

    public HintTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    {
        paint = getPaint();
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        if(mWidth == 0 ){
            mWidth = getMeasuredWidth();
            //颜色渐变器
            gradient = new LinearGradient(0, 0, mWidth, 0, new int[]{Color.GRAY, Color.WHITE, Color.GRAY}, new float[]{
                    0.3f,0.5f,1.0f
            }, Shader.TileMode.CLAMP);
            paint.setShader(gradient);

            matrix = new Matrix();
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        if(matrix !=null){
            deltaX += mWidth / 8;
            if(deltaX > 2 * mWidth){
                deltaX = -mWidth;
            }
        }
        //通过矩阵的平移实现
        matrix.setTranslate(deltaX, 0);
        gradient.setLocalMatrix(matrix);
        postInvalidateDelayed(100);
    }
}

SlidingFinishLayout.class

public class SlidingFinishLayout extends RelativeLayout {
    /**
     * 滑动的最小距离
     */
    private int mTouchSlop;

    private Scroller mScroller;

    /**
     * 父布局
     */
    private ViewGroup mParentView;

    /**
     * 按下X坐标
     */
    private int downX;
    /**
     * 按下Y坐标
     */
    private int downY;
    /**
     * 临时存X坐标
     */
    private int tempX;

    private int viewWidth;
    /**
     * 是否正在滑动
     */
    private boolean isSliding;

    private OnSlidingFinishListener onSlidingFinishListener;
    private boolean isFinish;
    public SlidingFinishLayout(Context context) {
        super(context);
    }

    public SlidingFinishLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    {
        mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
        mScroller = new Scroller(getContext());
    }

    public interface OnSlidingFinishListener {
        /**
         * 滑动销毁页面回调
         */
        void onSlidingFinish();
    }

    public void setOnSlidingFinishListener(OnSlidingFinishListener onSlidingFinishListener) {
        this.onSlidingFinishListener = onSlidingFinishListener;
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        if (changed) {
            // 获取SlidingFinishLayout布局的父布局
            mParentView = (ViewGroup) this.getParent();
            viewWidth = this.getWidth();
        }
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getActionMasked()) {
            case MotionEvent.ACTION_DOWN:
                downX = tempX = (int) event.getRawX();
                downY = (int) event.getRawY();
                break;
            case MotionEvent.ACTION_MOVE:
                int moveX = (int) event.getRawX();
                int deltaX = tempX - moveX;
                tempX = moveX;
                if (Math.abs(moveX - downX) > mTouchSlop
                        && Math.abs((int) event.getRawY() - downY) < mTouchSlop) {
                    isSliding = true;

                }

                if (moveX - downX >= 0 && isSliding) {
                    mParentView.scrollBy(deltaX, 0);

                }
                break;
            case MotionEvent.ACTION_UP:
                isSliding = false;
                if (mParentView.getScrollX() <= -viewWidth / 4) {
                    isFinish = true;
                    scrollRight();
                } else {
                    scrollOrigin();
                    isFinish = false;
                }
                break;
            default:
                break;
        }
        return true;
    }

    private void scrollRight() {
        final int delta = (viewWidth + mParentView.getScrollX());
        //滚动出界面
        mScroller.startScroll(mParentView.getScrollX(), 0, -delta + 1, 0,
                Math.abs(delta));
        postInvalidate();
    }

    private void scrollOrigin() {
        int delta = mParentView.getScrollX();
        //滚动到起始位置
        mScroller.startScroll(mParentView.getScrollX(), 0, -delta, 0,
                Math.abs(delta));
        postInvalidate();
    }

    @Override
    public void computeScroll() {
        // 调用startScroll的时候scroller.computeScrollOffset()返回true,
        if (mScroller.computeScrollOffset()) {
            mParentView.scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
            postInvalidate();

            if (mScroller.isFinished()) {
                if (onSlidingFinishListener != null && isFinish) {
                    onSlidingFinishListener.onSlidingFinish();
                }
            }
        }
    }
}

在PlayerService中注册广播:

 private BroadcastReceiver ScreenReceiver;

    private void initScreenBroadcast() {
        ScreenReceiver = new BroadcastReceiver() {

            @Override
            public void onReceive(Context context, Intent intent) {
                if (intent.getAction() != null && intent.getAction().equals(Intent.ACTION_SCREEN_OFF)){
                    Log.e("onReceive","收到锁屏广播");
                    Intent lockScreen = new Intent(PlayerService.this, LockActivity.class);
                    lockScreen.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    startActivity(lockScreen);
                }

            }
        };
        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_SCREEN_OFF);
        registerReceiver(ScreenReceiver, filter);
    }

在onDestory中注销广播:

@Override
    public void onDestroy() {
      
        unregisterReceiver(ScreenReceiver);
    }

到这算结束了。
—— ——— —— ——— —— ——— —— —— ——— ——
日常感谢帅气的师傅提供技术支持。
&
随心随性,佛系每一天。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值