android 自定义拍照录像
自定义拍照和录像功能。拍完照或录完视频后,弹出另一界面,显示拍的照片或录制的视频:
拍照界面:
界面中的按钮,点击是拍照,长按是摄像,摄像时,按钮周围有圆形进度条显示进度
TakePicActivity.java
package com.haier.uhome.appliance.newVersion.module.messageboard;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class TakePicActivity extends AppCompatActivity {
private static final String TAG = "TakePicActivity";
SurfaceView surfaceView;
SurfaceHolder surfaceHolder;
RelativeLayout rl_btn;
@BindView(R.id.fl_content)
FrameLayout flContent;
//进度条
@BindView(R.id.circleProgress)
CircleProgressView circleProgress;
@BindView(R.id.iv_turn)
ImageView ivTurn;
private Camera camera;
private Camera.Parameters parameters = null;
Bundle bundle = null; // 声明一个Bundle对象,用来存储数据
Button takepicture;
RelativeLayout rl_playPic;
int w, h;
protected boolean isPreview;
private MediaRecorder mMediaRecorder;
private boolean isRecording = true; // true表示没有录像,点击开始;false表示正在录像,点击暂停
private File mRecVedioPath;
private File mRecAudioFile;
//录制视频时的计时器
private TextView timer;
private int hour = 0;
private int minute = 0;
private int second = 0;
private boolean bool;
private Animator animator;
private boolean isRecordState = false;//是否是视频录制状态
private int progress;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_take_pic);
ButterKnife.bind(this);
takepicture = (Button) findViewById(R.id.takepicture);
surfaceView = (SurfaceView) this
.findViewById(R.id.surfaceView);
rl_btn = (RelativeLayout) this.findViewById(R.id.buttonLayout);
timer = (TextView) this.findViewById(R.id.show_time);
// 设置计时器不可见
// timer.setVisibility(View.GONE);
// 设置缓存路径
mRecVedioPath = new File(Environment.getExternalStorageDirectory()
.getAbsolutePath() + "/hfdatabase/video/temp/");
if (!mRecVedioPath.exists()) {
mRecVedioPath.mkdirs();
}
//圆形进度条设置
circleProgress.setBgColor(getResources().getColor(R.color.text_white));
circleProgress.setProgressColor(getResources().getColor(R.color.colorPrimaryDark));
ViewTreeObserver observerCircle = circleProgress.getViewTreeObserver();
observerCircle.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
progress = circleProgress.getmProgress();
return true;
}
});
surfaceView.getHolder()
.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
surfaceView.getHolder().setFixedSize(176, 144); //设置Surface分辨率
surfaceView.getHolder().setKeepScreenOn(true);// 屏幕常亮
surfaceView.getHolder().addCallback(new SurfaceCallback());//为SurfaceView的句柄添加一个回调函数
//长按录制
takepicture.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
isRecordState = true;
if (isRecording) {
/*
* 点击开始录像
*/
if (isPreview) {
camera.stopPreview();
camera.release();
camera = null;
}
second = 0;
minute = 0;
hour = 0;
bool = true;
if (mMediaRecorder == null)
mMediaRecorder = new MediaRecorder();
else
mMediaRecorder.reset();
//拍摄视频时的相机配置
if (camera != null) {
freeCameraResource();
}
camera = Camera.open();
camera.setDisplayOrientation(90);
camera.startPreview();
camera.unlock();
mMediaRecorder.setCamera(camera);
mMediaRecorder.setOnErrorListener(null);
mMediaRecorder.setPreviewDisplay(surfaceHolder.getSurface());
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
mMediaRecorder.setMaxDuration(60 * 1000);
mMediaRecorder.setVideoSize(320, 240);
mMediaRecorder.setVideoEncodingBitRate(1 * 1024 * 1024);// 设置帧频率,然后就清晰了
// mMediaRecorder.setVideoFrameRate(15);
mMediaRecorder.setOrientationHint(getPreviewDegree(TakePicActivity.this));// 输出旋转90度,保持竖屏录制
try {
mRecAudioFile = File.createTempFile("Vedio", ".mp4", mRecVedioPath);
} catch (IOException e) {
e.printStackTrace();
}
mMediaRecorder.setOutputFile(mRecAudioFile.getAbsolutePath());
try {
mMediaRecorder.prepare();
timer.setVisibility(View.VISIBLE);
handler.postDelayed(task, 1000);
mMediaRecorder.start();
} catch (Exception e) {
e.printStackTrace();
}
showMsg("开始录制");
// scalePic.setBackgroundDrawable(iconStop);
isRecording = !isRecording;
recordAnimater();
}
return false;
}
});
takepicture.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_UP:
Log.d(TAG, "onTouch: takepicture==setOnTouchListener==ACTION_UP");
if(isRecordState){
if(animator.isRunning()){
animator.end();
}
}
break;
}
return false;
}
});
}
/*
* 视频录制时的进度条动画
* */
public void recordAnimater() {
//设置进度条
startAnimator();
animator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
Log.i("animator", "stop");
/*
* 点击停止
*/
try {
bool = false;
// isRecordState = false;
mMediaRecorder.stop();
timer.setText(format(hour) + ":" + format(minute) + ":" + format(second));
mMediaRecorder.release();
mMediaRecorder = null;
//录制完成后播放摄像头
freeCameraResource();
videoRename();
} catch (Exception e) {
e.printStackTrace();
}
isRecording = !isRecording;
// scalePic.setBackgroundDrawable(iconStart);
showMsg("录制完成,已保存");
// Intent backIntent = new Intent();
// backIntent.putExtra("path", mrv_wx.mVecordFile.getAbsoluteFile().toString());
// setResult(RESULT_OK, backIntent);
// finish();
Intent displayIntent = new Intent(TakePicActivity.this, ShowPicActivity.class);
bundle = new Bundle();
bundle.putBoolean("isRecord", isRecordState);
bundle.putString("video_path", out.getAbsolutePath());
displayIntent.putExtras(bundle);
startActivity(displayIntent);
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
}
@OnClick(R.id.iv_turn)
public void onClick() {
}
private final class SurfaceCallback implements SurfaceHolder.Callback {
@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
if (camera != null) {
freeCameraResource();
}
camera = Camera.open(); // 打开摄像头
parameters = camera.getParameters();
//加这句小米手机会黑屏
// parameters.setPreviewFrameRate(5); // 每秒5帧
parameters.setPictureFormat(PixelFormat.JPEG);// 设置照片的输出格式
parameters.set("jpeg-quality", 85);// 照片质量
int PreviewWidth = 0;
int PreviewHeight = 0;
// 选择合适的预览尺寸
List<Camera.Size> sizeList = parameters.getSupportedPreviewSizes();
// 如果sizeList只有一个我们也没有必要做什么了,因为就他一个别无选择
if (sizeList.size() > 1) {
Iterator<Camera.Size> itor = sizeList.iterator();
while (itor.hasNext()) {
Camera.Size cur = itor.next();
if (cur.width >= PreviewWidth
&& cur.height >= PreviewHeight) {
PreviewWidth = cur.width;
PreviewHeight = cur.height;
break;
}
}
}
parameters.setPreviewSize(PreviewWidth, PreviewHeight); // 获得摄像区域的大小
parameters.setPictureSize(PreviewWidth, PreviewHeight); // 获得保存图片的大小
// parameters.setPreviewSize(320, 240); // 设置预览大小
// parameters.setPictureSize(320,240);
// parameters.set("orientation", "portrait");
camera.setParameters(parameters);
camera.setPreviewDisplay(holder); // 设置用于显示拍照影像的SurfaceHolder对象
camera.setDisplayOrientation(getPreviewDegree(TakePicActivity.this));
camera.startPreview(); // 开始预览
isPreview = true;
// camera.autoFocus(null);
} catch (Exception e) {
e.printStackTrace();
}
surfaceHolder = holder;
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
surfaceHolder = holder;
LogUtil.d(TAG,"surfaceChanged======");
camera.autoFocus(new Camera.AutoFocusCallback() {
@Override
public void onAutoFocus(boolean success, Camera camera) {
// camera.setOneShotPreviewCallback(null);
initCamera(width, height);
camera.cancelAutoFocus();//只有加上了这一句,才会自动对焦。
}
});
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (camera != null) {
if (isPreview) {
camera.stopPreview();
isPreview = false;
}
camera.release(); // 释放照相机
camera = null;
}
surfaceHolder = null;
surfaceView = null;
mMediaRecorder = null;
}
}
// 提供一个静态方法,用于根据手机方向获得相机预览画面旋转的角度
public static int getPreviewDegree(Activity activity) {
// 获得手机的方向
int rotation = activity.getWindowManager().getDefaultDisplay()
.getRotation();
int degree = 0;
// 根据手机的方向计算相机预览画面应该选择的角度
switch (rotation) {
case Surface.ROTATION_0:
degree = 90;
break;
case Surface.ROTATION_90:
degree = 0;
break;
case Surface.ROTATION_180:
degree = 270;
break;
case Surface.ROTATION_270:
degree = 180;
break;
}
return degree;
}
/**
* 按钮被点击触发的事件
*
* @param v
*/
public void btnOnclick(View v) {
if (camera != null) {
switch (v.getId()) {
case R.id.takepicture:
// 拍照
camera.takePicture(null, null, new MyPictureCallback());
break;
}
}
}
byte[] picData;
private final class MyPictureCallback implements Camera.PictureCallback {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
try {
bundle = new Bundle();
bundle.putByteArray("bytes", data);//将图片字节数据保存在bundle中,实现数据交换
picData = data;
// saveToSDCard(data);
// camera.startPreview();//拍完照后,重新开始预览
if (bundle == null) {
Toast.makeText(getApplicationContext(), "请先拍照",
Toast.LENGTH_SHORT).show();
} else {
Intent intent = new Intent();
intent.setClass(getApplicationContext(), ShowPicActivity.class);
bundle.putBoolean("isRecord", isRecordState);
intent.putExtras(bundle);
startActivity(intent);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void initCamera(int width, int height) {
parameters = camera.getParameters(); // 获取各项参数
parameters.setPictureFormat(PixelFormat.JPEG); // 设置图片格式
parameters.setPreviewSize(width, height); // 设置预览大小
// List<Camera.Size> sizes =parameters.getSupportedPreviewSizes();
// Camera.Size optimalSize = getOptimalPreviewSize(sizes, 320,240);
// parameters.setPreviewSize(optimalSize.width, optimalSize.height);
parameters.setPreviewFrameRate(5); //设置每秒显示4帧
parameters.setPictureSize(width, height); // 设置保存的图片尺寸
parameters.setJpegQuality(80); // 设置照片质量
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);//1连续对焦
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
camera.startPreview();
camera.cancelAutoFocus();// 2如果要实现连续的自动对焦,这一句必须加上
}
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
if (!isRecordState) {
camera.autoFocus(new Camera.AutoFocusCallback() {
@Override
public void onAutoFocus(boolean success, Camera camera) {
if (success) {
Log.d("TakePicActivity", "success");
w = (int) event.getX();
h = (int) event.getY();
// setLayout(rlFocus,w-50,h-50);
// Rect focusRect = calculateTapArea(w,h,100);
mHandler.obtainMessage(0).sendToTarget();
initCamera(w, h);
camera.cancelAutoFocus();//只有加上了这一句,才会自动对焦。
}
}
});
}
}else if(event.getAction() == MotionEvent.ACTION_UP){
Log.d(TAG, "onTouchEvent: ACTION_UP");
}
else if(event.getAction() == MotionEvent.ACTION_MOVE){
Log.d(TAG, "onTouchEvent: ACTION_MOVE");
}
return super.onTouchEvent(event);
}
/*
* 覆写返回键监听
*/
@Override
public void onBackPressed() {
if (mMediaRecorder != null) {
mMediaRecorder.stop();
mMediaRecorder.release();
mMediaRecorder = null;
// videoRename();
}
finish();
}
@Override
protected void onPause() {
super.onPause();
onBackPressed();
}
View view;
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 0:
flContent.invalidate();
view = new MyView(TakePicActivity.this, w, h);
flContent.addView(view);
mHandler.sendEmptyMessageDelayed(1, 1000);//使选框停留1秒后消失
break;
case 1:
flContent.removeView(view);
break;
}
}
};
/*
* 设置控件所在的位置YY,并且不改变宽高,
* XY为绝对位置
*/
public void setLayout(View view, int x, int y) {
ViewGroup.MarginLayoutParams margin = new ViewGroup.MarginLayoutParams(view.getLayoutParams());
margin.setMargins(x, y, x + margin.width, y + margin.height);
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(margin);
view.setLayoutParams(layoutParams);
}
File out;
/*
* 生成video文件名字
*/
protected void videoRename() {
String path = Environment.getExternalStorageDirectory()
.getAbsolutePath() + "/hfdatabase/video/0/";
String fileName = new SimpleDateFormat("yyyyMMddHHmmss")
.format(new Date()) + ".mp4";
out = new File(path);
if (!out.exists()) {
out.mkdirs();
}
out = new File(path, fileName);
if (mRecAudioFile.exists())
mRecAudioFile.renameTo(out);
}
/*
* 消息提示
*/
private Toast toast;
public void showMsg(String arg) {
if (toast == null) {
toast = Toast.makeText(this, arg, Toast.LENGTH_SHORT);
} else {
toast.cancel();
toast.setText(arg);
}
toast.show();
}
/*
* 格式化时间
*/
public String format(int i) {
String s = i + "";
if (s.length() == 1) {
s = "0" + s;
}
return s;
}
/*
* 定时器设置,实现计时
*/
private Handler handler = new Handler();
private Runnable task = new Runnable() {
public void run() {
if (bool) {
handler.postDelayed(this, 1000);
second++;
if (second >= 60) {
minute++;
second = second % 60;
}
if (minute >= 60) {
hour++;
minute = minute % 60;
}
timer.setText(format(hour) + ":" + format(minute) + ":" + format(second));
}
}
};
private void startAnimator() {
circleProgress.setVisibility(View.VISIBLE);
animator = ObjectAnimator.ofInt(circleProgress, "progress", progress);
animator.setDuration(60000);
animator.setInterpolator(new LinearInterpolator());
animator.start();
}
/**
* 释放摄像头资源
*/
private void freeCameraResource() {
if (camera != null) {
camera.setPreviewCallback(null);
camera.stopPreview();
camera.lock();
camera.release();
camera = null;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
freeCameraResource();
if(mMediaRecorder != null){
mMediaRecorder.release();
mMediaRecorder = null;
}
}
}
显示图片或视频:
ShowPicActivity.java
package com.haier.uhome.appliance.newVersion.module.messageboard;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class ShowPicActivity extends AppCompatActivity {
private final static String ALBUM_PATH = Environment.getExternalStorageDirectory() + "/download_img/";
private static final String TAG = "ShowPicActivity";
String imgName;
ImageView iv_play;
@BindView(R.id.iv_back2)
ImageView ivBack2;
@BindView(R.id.iv_confirm)
ImageView ivConfirm;
@BindView(R.id.tv_repeat)
TextView tvRepeat;
@BindView(R.id.rl_confirm)
RelativeLayout rlConfirm;
String videoPath;
@BindView(R.id.sfv_display)
SurfaceView sfvDisplay;
private SurfaceHolder sfh_display2;
MediaPlayer player;
boolean isRecord = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_show_pic);
ButterKnife.bind(this);
iv_play = (ImageView) findViewById(R.id.iv_playPic);
Intent intent = getIntent();
Bundle data = intent.getExtras();
if (data.getBoolean("isRecord")) {
isRecord = true;
videoPath = data.getString("video_path");
iv_play.setVisibility(View.GONE);
sfvDisplay.setVisibility(View.VISIBLE);
Log.d(TAG, "videoPath=" + videoPath);
showVideo();
} else {
isRecord = false;
iv_play.setVisibility(View.VISIBLE);
sfvDisplay.setVisibility(View.GONE);
setImageBitmap(data.getByteArray("bytes"));
}
}
/**
* 将MainActivity传过来的图片显示在界面当中
*
* @param bytes
*/
public void setImageBitmap(byte[] bytes) {
Bitmap cameraBitmap = byte2Bitmap();
// 根据拍摄的方向旋转图像(纵向拍摄时要需要将图像选择90度)
Matrix matrix = new Matrix();
matrix.setRotate(TakePicActivity.getPreviewDegree(this));
cameraBitmap = Bitmap
.createBitmap(cameraBitmap, 0, 0, cameraBitmap.getWidth(),
cameraBitmap.getHeight(), matrix, true);
imgName = Calendar.getInstance().getTimeInMillis() + ".jpg";
saveFile(cameraBitmap, imgName);
iv_play.setScaleType(ImageView.ScaleType.CENTER_CROP);
iv_play.setImageBitmap(cameraBitmap);
}
//保存图片到本地
public void saveFile(Bitmap bm, String imgName) {
File dirFile = new File(ALBUM_PATH);
if (!dirFile.exists()) {
dirFile.mkdir();
}
File myFile = new File(ALBUM_PATH + imgName);
try {
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(myFile));
bm.compress(Bitmap.CompressFormat.JPEG, 80, bos);
bos.flush();
bos.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
/**
* 从Bundle对象中获取数据
*
* @return
*/
public byte[] getImageFormBundle() {
Intent intent = getIntent();
Bundle data = intent.getExtras();
byte[] bytes = data.getByteArray("bytes");
return bytes;
}
/**
* 将字节数组的图形数据转换为Bitmap
*
* @return
*/
private Bitmap byte2Bitmap() {
byte[] data = getImageFormBundle();
// 将byte数组转换成Bitmap对象
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
return bitmap;
}
@OnClick({R.id.iv_back2, R.id.iv_confirm, R.id.tv_repeat})
public void onClick(View view) {
switch (view.getId()) {
case R.id.iv_back2:
finish();
break;
case R.id.iv_confirm:
Intent i = new Intent(this, MainMessageBoard.class);
if(isRecord){
i.putExtra("toMainPath", videoPath);
}else{
i.putExtra("toMainPath", ALBUM_PATH + imgName);
}
i.putExtra("isRecord",isRecord);
//要启动的activity已经在当前的任务中,那么在该activity之上的activity都会关闭,并且intent会传递给在栈顶的activity
//如果 Activity 已经是运行在 Task 的 top,则该 Activity 将不会再被启动
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(i);
break;
case R.id.tv_repeat:
finish();
break;
}
}
//显示并播放录制的视频
public void showVideo(){
sfh_display2 = sfvDisplay.getHolder();
sfh_display2.addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
player = new MediaPlayer();
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
player.setDisplay(sfh_display2);
try {
player.setDataSource(videoPath);
player.prepare();
player.start();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
});
sfh_display2.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
}
圆形进度条
package com.haier.uhome.appliance.newVersion.module.messageboard.view;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;
/**
* Created by wangchm on 2017/1/23 0023.
*/
public class CircleProgressView extends View {
private static final String TAG = "CircleProgressView";
private int mMaxProgress = 100;
private int mProgress = 100;
private final int mCircleLineStrokeWidth = 22;
private final int mTxtStrokeWidth = 2;
// 画圆所在的距形区域
private final RectF mRectF;
private final Paint mPaint;
private final Context mContext;
private String mTxtHint1;
private String mTxtHint2;
private int bgColor;
private int progressColor;
public CircleProgressView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
mRectF = new RectF();
mPaint = new Paint();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int width = this.getWidth();
int height = this.getHeight();
if (width != height) {
int min = Math.min(width, height);
width = min;
height = min;
}
// 设置画笔相关属性
mPaint.setAntiAlias(true);
// mPaint.setColor(Color.GRAY);
mPaint.setColor(bgColor);
canvas.drawColor(Color.TRANSPARENT);
mPaint.setStrokeWidth(mCircleLineStrokeWidth);
mPaint.setStyle(Paint.Style.STROKE);
// 位置
mRectF.left = mCircleLineStrokeWidth / 2; // 左上角x
mRectF.top = mCircleLineStrokeWidth / 2; // 左上角y
mRectF.right = width - mCircleLineStrokeWidth / 2; // 左下角x
mRectF.bottom = height - mCircleLineStrokeWidth / 2; // 右下角y
// 绘制圆圈,进度条背景
canvas.drawArc(mRectF, -90, 360, false, mPaint);
// mPaint.setColor(Color.RED);
mPaint.setColor(progressColor);
canvas.drawArc(mRectF, -90, ((float) mProgress / mMaxProgress) * 360, false, mPaint);
// 绘制进度文案显示
mPaint.setStrokeWidth(mTxtStrokeWidth);
String text = mProgress + "%";
int textHeight = height / 4;
mPaint.setTextSize(textHeight);
int textWidth = (int) mPaint.measureText(text, 0, text.length());
mPaint.setStyle(Paint.Style.FILL);
canvas.drawText(text, width / 2 - textWidth / 2, height / 2 + textHeight / 2, mPaint);
if (!TextUtils.isEmpty(mTxtHint1)) {
mPaint.setStrokeWidth(mTxtStrokeWidth);
text = mTxtHint1;
textHeight = height / 8;
mPaint.setTextSize(textHeight);
mPaint.setColor(Color.rgb(0x99, 0x99, 0x99));
textWidth = (int) mPaint.measureText(text, 0, text.length());
mPaint.setStyle(Paint.Style.FILL);
canvas.drawText(text, width / 2 - textWidth / 2, height / 4 + textHeight / 2, mPaint);
}
if (!TextUtils.isEmpty(mTxtHint2)) {
mPaint.setStrokeWidth(mTxtStrokeWidth);
text = mTxtHint2;
textHeight = height / 8;
mPaint.setTextSize(textHeight);
textWidth = (int) mPaint.measureText(text, 0, text.length());
mPaint.setStyle(Paint.Style.FILL);
canvas.drawText(text, width / 2 - textWidth / 2, 3 * height / 4 + textHeight / 2, mPaint);
}
}
public int getMaxProgress() {
return mMaxProgress;
}
public void setMaxProgress(int maxProgress) {
this.mMaxProgress = maxProgress;
}
public void setProgress(int progress) {
this.mProgress = progress;
this.invalidate();
}
public int getmProgress(){
return mProgress;
}
public void setProgressNotInUiThread(int progress) {
this.mProgress = progress;
this.postInvalidate();
}
public String getmTxtHint1() {
return mTxtHint1;
}
public void setmTxtHint1(String mTxtHint1) {
this.mTxtHint1 = mTxtHint1;
}
public String getmTxtHint2() {
return mTxtHint2;
}
public void setmTxtHint2(String mTxtHint2) {
this.mTxtHint2 = mTxtHint2;
}
public int getBgColor() {
return bgColor;
}
public void setBgColor(int bgColor) {
this.bgColor = bgColor;
}
public int getProgressColor() {
return progressColor;
}
public void setProgressColor(int progressColor) {
this.progressColor = progressColor;
}
}
android 自定义拍照录像相关推荐
- Android 自定义拍照,解决图片旋转,拍照参数设置兼容问题
Android 自定义拍照,解决图片旋转,拍照参数设置兼容问题 参考文章: (1)Android 自定义拍照,解决图片旋转,拍照参数设置兼容问题 (2)https://www.cnblogs.com/ ...
- Android自定义拍照解决部分手机拍完之后图片不清楚的问题
昨天同事跟我说了一个bug,让我整了一天,从昨天下午这个时间到今天下午这个时间,哎... 大家都懂的 首先我来说一个bug,我用surfaceView来实现自定义拍照的功能,先来张在genymotio ...
- Android自定义拍照上传界面,Android自定义dialog——设置头像(拍照,相册)
Android自定义dialog--设置头像(拍照,相册) 需求场景:个人信息设置,点击头像,在界面上弹出一个弹框,用户选择"拍照"/"从图库选择",选择照片后 ...
- Android自定义拍照小米手机拍照照片模糊的问题
原文地址 昨天同事跟我说了一个bug,让我整了一天,从昨天下午这个时间到今天下午这个时间,哎... 大家都懂的 首先我来说一个bug,我用surfaceView来实现自定义拍照的功能,先来张在geny ...
- android 自定义拍照模糊,Android自定义相机拍照模糊处理
问题分析:随着用户对于拍照清晰度的需求,android手机对于摄像头也是一升再升,这就导致了作为android开发工程师对于兼容性维护的继续跟进以及问题处理. 针对于自定义相机拍照模糊的问题,经过几天 ...
- Android自定义拍照实现
前言 由于网上大部分自定义相机的实现,都是耦合性比较强的,不方便今后的复用,所以我自己实现了一套自定义相机,方便以后的扩展.自定义相机分为以下3个部分.文末有免费福利哦 相机的预览布局SurfaceV ...
- uni-app 自定义相机拍照录像,可设置分辨率、支持横竖屏(ios、android)
插件市场:uni-app 自定义相机拍照录像,可设置分辨率.支持横竖屏(ios.android)
- Android自定义照相机实现 拍照 录像
文档中的Camera 要使用Camera,首先我们先看一下文档(http://androiddoc.qiniudn.com/reference/android/hardware/Camera.html ...
- android 拍照插件,拍照录像,android原生插件
更新记录 1.0.1(2021-03-31) 拍照录像模式,轻触拍照,长按录像:只录像模式,轻触即可录像 支持录像,设置视频的比特率,最长/最短录制时间等 支持录像时,输出视频第一帧图片 支持自定义图 ...
最新文章
- 【C++】log(n)斐波那契数列计算
- 多篇顶会看个体因果推断(ITE)的前世今生
- C语言分区排序partition sort 算法(附完整源码)
- Maven学习笔记(2) --mvn archetype:create 说明
- C语言中变量的储存类别
- python中pip不是内部或外部命令_‘pip’不被识别为内部或外部命令。
- 值不值得入手_看好三阳的小拉力,但不知道值不值得入手?
- getBoundingClientRect使用指南
- [线程安全问题] 多线程到底可能会带来哪些风险?
- Python获取实时的时间
- 【深度学习】卷积神经网络(CNN)原理
- 华为Eudumon1000配置PORTAL认证
- trajan算法(离线做法) LCA详解
- 即将到来的交通革命——出行即服务(MaaS)
- 2011年好莱坞大片索引
- iOS转向Flutter学习日记
- 命令启动edge浏览器且全屏
- HTML特殊字符编码对照表 —— (二)
- 升级Windows10,安装程序无法正常启动无法初始化工作目录
- 坑:vuex中的mutations不能使用return获取数据
热门文章
- Equalization Loss论文小结(CVPR2020)
- TortoiseGit
- sql 语句 中的 exits 和 in 关键字
- Android 面试题 200 道 :全面解析
- 如何做一个小程序口令红包功能
- 苹果cms去掉链接index.php,如何去除苹果cms链接中的index.php
- [项目管理入门系列] 师傅领进门-------项目运作的一般流程(四)
- 感觉犹太人最有名的这十句话也挺有感悟的!不妨你来看看!
- CGD全局并发队列和主队列的应用
- 【实时PPP】对比CNES的实时数据流与CNT产品之间的差异