做完蓝牙功能,客户说其他的音乐播放器都有锁屏页功能,我也想要。对于难缠的客户的要求只能面向百度的编程,在百度一些东西后有一些思路。思路来源链接
首先在清单文件添加权限:
<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);
}
到这算结束了。
—— ——— —— ——— —— ——— —— —— ——— ——
日常感谢帅气的师傅提供技术支持。
&
随心随性,佛系每一天。