需求:
做一个手电筒APK,要求如下:
1:手电筒应用打开后需要有具体的界面打开和关闭按钮。按Home,Recent键保持长亮,按 Back键关闭
2:手电筒的状态必须和下拉栏的手电筒状态一致
3:手电筒打开和关闭,需要有一个弹框提醒用户确认或者取消,弹框风格请自定义view来写
4:APK要经过测试通过且代码规范方可视作完成
最终效果:
FlashlightActivity.java
package com.example.flashlight;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraManager;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.ImageView;
import com.example.flashlight.view.CustomDialog;
public class FlashlightActivity extends AppCompatActivity implements View.OnClickListener {
private static ImageView iv;
private CameraManager mCameraManager;
public static boolean isOpen = false;
private static final CameraManager.TorchCallback torchCallback = new CameraManager.TorchCallback() {
@Override
public void onTorchModeUnavailable(@NonNull String cameraId) {
super.onTorchModeUnavailable(cameraId);
}
@Override
public void onTorchModeChanged(@NonNull String cameraId, boolean enabled) {
super.onTorchModeChanged(cameraId, enabled);
if (isOpen != enabled) {
if (isOpen) {
iv.setImageResource(R.drawable.off_img);
} else {
iv.setImageResource(R.drawable.on_img);
}
}
isOpen = enabled;
}
@Override
public void onTorchStrengthLevelChanged(@NonNull String cameraId, int newStrengthLevel) {
super.onTorchStrengthLevelChanged(cameraId, newStrengthLevel);
}
};
@Override
public void onBackPressed() {
super.onBackPressed();
close();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
iv = findViewById(R.id.iv_led);
findViewById(R.id.on_btn).setOnClickListener(this);
findViewById(R.id.off_btn).setOnClickListener(this);
mCameraManager = (CameraManager) getApplicationContext().getSystemService(Context.CAMERA_SERVICE);
mCameraManager.registerTorchCallback(torchCallback, new Handler());
mCameraManager.registerTorchCallback(new CameraManager.TorchCallback() {
@Override
public void onTorchModeChanged(@NonNull String cameraId, boolean enabled) {
super.onTorchModeChanged(cameraId, enabled);
if (isOpen != enabled) {
if (isOpen) {
iv.setImageResource(R.drawable.off_img);
} else {
iv.setImageResource(R.drawable.on_img);
}
}
isOpen = enabled;
}
}, new Handler());
}
@Override
public void onClick(View view) {
if (view.getId() == R.id.on_btn) {
if (!isOpen) {
CustomDialog customDialog = new CustomDialog(this);
customDialog.setTitle("警告!");
customDialog.setMessage("确定开启手电筒?");
customDialog.setCustomOnClickListener(new CustomDialog.OnCustomClickListener() {
@Override
public void onCancelClick() {
}
@Override
public void onConfirmClick() {
//开的时候改变图片为开
open();
isOpen = true;
}
});
customDialog.show();
}
} else if (view.getId() == R.id.off_btn) {
if (isOpen) {
CustomDialog customDialog = new CustomDialog(this);
customDialog.setTitle("警告!");
customDialog.setMessage("确定开启手电筒?");
customDialog.setCustomOnClickListener(new CustomDialog.OnCustomClickListener() {
@Override
public void onCancelClick() {
}
@Override
public void onConfirmClick() {
//关的时候改变图片为关
close();
isOpen = false;
}
});
customDialog.show();
}
}
}
public void open() {
iv.setImageResource(R.drawable.on_img);
try {
mCameraManager.setTorchMode("0", true);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
public void close() {
iv.setImageResource(R.drawable.off_img);
try {
mCameraManager.setTorchMode("0", false);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
}
布局文件:activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
tools:context=".FlashlightActivity"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="40sp"
android:background="@color/black"
android:text="手电筒"
android:textSize="25sp"
android:textColor="@color/white"
android:textStyle="bold"
android:gravity="center"/>
<ImageView
android:id="@+id/iv_led"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="8"
android:src="@drawable/off_img"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="2">
<Button
android:id="@+id/on_btn"
android:layout_width="0dp"
android:layout_weight="1"
android:text="ON"
android:layout_height="match_parent"
android:textSize="26sp" />
<Button
android:id="@+id/off_btn"
android:layout_width="0dp"
android:layout_weight="1"
android:text="OFF"
android:layout_height="match_parent"
android:textSize="26sp"/>
</LinearLayout>
</LinearLayout>
自定义View CustomDialog
package com.example.flashlight.view;
import android.app.AlertDialog;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import com.example.flashlight.R;
public class CustomDialog extends AlertDialog {
private OnCustomClickListener listener;
private TextView tvCancel;
private TextView tvConfirm;
private TextView tvTitle;
private TextView tvContent;
private String title;
private String message;
public CustomDialog(Context context) {
super(context, R.style.CustomDialog);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//布局
setContentView(R.layout.custom_dialog);
//绑定控件
tvCancel = findViewById(R.id.tv_cancel);
tvConfirm = findViewById(R.id.tv_confirm);
tvTitle = findViewById(R.id.tv_title);
tvContent = findViewById(R.id.tv_content);
//点击外部不关闭
setCanceledOnTouchOutside(false);
//设置dialog的位置
//setDialogLocation();
init();
}
public void setMessage(String message) {
this.message = message;
}
public void setTitle(String title) {
this.title = title;
}
//设置dialog的位置
/*private void setDialogLocation(){
Window window = getWindow();
if (window != null){
WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
layoutParams.copyFrom(window.getAttributes());
layoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
//设置起始位置
// lp.x = 100;
// lp.y = 100;
layoutParams.gravity = Gravity.BOTTOM;
window.setAttributes(layoutParams);
}
}*/
private void init() {
if (title != null) tvTitle.setText(title);
if (message != null) tvContent.setText(message);
tvCancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (listener != null)
listener.onCancelClick();
dismiss();
}
});
tvConfirm.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (listener != null)
listener.onConfirmClick();
dismiss();
}
});
}
public CustomDialog setCustomOnClickListener(OnCustomClickListener listener){
this.listener = listener;
return this;
}
public interface OnCustomClickListener {
void onCancelClick();
void onConfirmClick();
}
}
布局文件:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="300dp"
android:layout_height="200dp"
android:padding="10dp"
android:background="@drawable/custom_dialog_bg">
<TextView
android:id="@+id/tv_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="Title"
android:textColor="#000000"
android:textSize="25sp">
</TextView>
<TextView
android:id="@+id/tv_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/tv_title"
android:layout_marginTop="15dp"
android:layout_marginStart="20dp"
android:layout_marginEnd="20dp"
android:text="message"
android:textColor="#000000"
android:textSize="25sp">
</TextView>
<Button
android:id="@+id/tv_cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentBottom="true"
android:layout_marginLeft="20dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="20dp"
android:text="取 消"
android:textColor="#2196F3"
android:textSize="25sp">
</Button>
<Button
android:id="@+id/tv_confirm"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:layout_marginLeft="5dp"
android:layout_marginRight="20dp"
android:layout_marginBottom="20dp"
android:text="确 认"
android:textColor="#2196F3"
android:textSize="25sp">
</Button>
</RelativeLayout>
style
<style name="CustomDialog" parent="android:style/Theme.Dialog">
<!--背景颜色及和透明程度-->
<item name="android:windowBackground">@android:color/transparent</item>
<!--是否去除标题 -->
<item name="android:windowNoTitle">true</item>
<!--是否去除边框-->
<item name="android:windowFrame">@null</item>
<!--是否浮现在activity之上-->
<item name="android:windowIsFloating">true</item>
<!--是否模糊-->
<item name="android:backgroundDimEnabled">true</item>
</style>
图片资源: