澳门新葡亰娱乐网站-www.142net-欢迎您

澳门新葡亰娱乐网站是因为你还没有找到一条正确的致富之路,www.142net是将所有的游戏都汇集在一起的官方平台,因为澳门新葡亰娱乐网站这个网站当中有着大量的游戏攻略,托IP定位技术,传达终端直接到达的精准传播方式。

仿微信录制小视频,Android仿微信录制小视频的进

来源:http://www.bhtsgq.com 作者:计算机知识 人气:193 发布时间:2020-03-14
摘要:在 仿Wechat摄像短录制库中有四个自定义的View,正是录像录制时的进程条。其落到实处的法规很简短。 Demo 地址 JCVideoRecord 支付从前 这段时间接触了眨眼间间和录像相关的控件, 所以,继

在 仿Wechat摄像短录制库中有四个自定义的View,正是录像录制时的进程条。其落到实处的法规很简短。

Demo 地址
JCVideoRecord

支付从前

这段时间接触了眨眼间间和录像相关的控件, 所以, 继从前的微信摇一摇, 笔者想开了来落到实处一下Wechat小摄像摄像的功效, 它的效应点相当多, 小编每一日都收取点时间来写写, 说真的, 有个别东西依旧比较费力, 希望大家认真看看, 说得格外的地点还请我们在评价中指正. 废话非常的少说, 进入正题.

Wechat交际圈摄像小录像,效果图如下:

澳门葡萄京官方网站 1progress.gif

日前有个要求涉及到录像一个小摄像上传服务器,所以写了那些德姆o,在这里记录下,供就学用,主要使用的是AVFoundation 框架。

支出条件

这段时间刚更新的, 没更新的小同伴们牢牢抓紧了

  • Android Studio 2.2.2
  • JDK1.7
  • API 24
  • Gradle 2.2.2

澳门葡萄京官方网站 2拍照小录制.png

可以纵然进度条是一段间距,甲从侧面出发,乙侧面出发,以相通的快慢跑向中央。如图:

澳门葡萄京官方网站 3

有关知识点

  • 录像摄像分界面 SurfaceView 的选用

  • Camera的使用

  • 相机的对焦, 定焦

  • 摄像摄像控件MediaRecorder的选拔

  • 澳门葡萄京官方网站,仿微信录制小视频,Android仿微信录制小视频的进度条。简短自定义View

  • GestureDetector(手势检查测试State of Qatar的施用

用到的事物真不菲, 可是别焦急, 我们叁个八个来.

怎么接收,大家应该不面生了。个中关键能力有三个:

澳门葡萄京官方网站 4WechatIMG23.jpeg

IMB_AX2vxc.GIF

起来开垦

  1. 摄像录像本事;
  2. “按住拍”的卡通效果;

那只需总计出甲只怕乙每秒行走的相距,重新绘制进程条就能够。

使用

- (void)present{
    _recordView = [[JCVideoRecordView alloc]initWithFrame:[UIScreen mainScreen].bounds];
    _recordView.cancelBlock = ^{

    };
    _recordView.completionBlock = ^(NSURL *fileUrl) {

    };
    [_recordView present];
}

案例预览

请见谅Gif图的粗糙

澳门葡萄京官方网站 5

Wechat小摄像

在互连网搜了多少个demo,最后发掘上边四个开源项目比较可信:

 @Override protected void onDraw(Canvas canvas) { super.onDraw; long currTime = System.currentTimeMillis(); if(mState == State.START){ int measuredWidth = getMeasuredWidth(); float mSpeed = measuredWidth / 2.0f / maxTime; //速度 = 甲的距离 / 总时间 float druTime = (currTime - startTime); // 时间 if(druTime >= minTime){ //如果时间 大于 设置的最少时间 改变进度的颜色 mPaint.setColor(progressColor); } float dist = mSpeed * druTime; // s= v * t 甲 在druTime 行走的距离 if(dist < measuredWidth/2.0f){ //判断是否到达终点 canvas.drawRect(dist,0.0f,measuredWidth - dist,getMeasuredHeight;//绘制进度条 invalidate();//重绘 } }else{ return; } canvas.drawRect(0.0f, 0.0f, 0.0f, getMeasuredHeight(), mPaint); } 

简易介绍

案例深入分析

世家能够张开本身Wechat里面包车型的士小录制, 一块轻松的分析一下它的功用点有哪些 ?

  • 主干的摄像预览功效

  • 长按 "按住拍" 完毕摄像的摄像

  • 录制进程中的进程条从两边向中档变短

  • 当松开恐怕进程条走到尽头摄像截止摄像 并保留

  • 从 "按住拍" 上海滑稽剧团取消视频的摄像

  • 双击显示屏 定焦 放大

依照上述的分析, 大家一步一步的成就

  1. RecordVideo德姆o ← 注重推荐
  2. WeiXinCamera

官方文书档案定义

1.索引构造

澳门葡萄京官方网站 6

显示器快照 2017-09-29 早晨1.29.07.png

搭建布局

布局分界面包车型客车兑现还能, 难度相当的小

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:id="@ id/main_tv_tip"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|center_horizontal"
        android:layout_marginBottom="150dp"
        android:elevation="1dp"
        android:text="双击放大"
        android:textColor="#FFFFFF"/>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <SurfaceView
            android:id="@ id/main_surface_view"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="3"/>
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:background="@color/colorApp"
            android:orientation="vertical">
            <RelativeLayout
                android:id="@ id/main_press_control"
                android:layout_width="match_parent"
                android:layout_height="match_parent">
                <com.lulu.weichatsamplevideo.BothWayProgressBar
                    android:id="@ id/main_progress_bar"
                    android:layout_width="match_parent"
                    android:layout_height="2dp"
                    android:background="#000"/>
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_centerInParent="true"
                    android:text="按住拍"
                    android:textAppearance="@style/TextAppearance.AppCompat.Large"
                    android:textColor="#00ff00"/>
            </RelativeLayout>
        </LinearLayout>
    </LinearLayout>
</FrameLayout>

RecordVideoDemo中落到实处了二种摄像方法:a. 接收系统类MediaRecorder。b. 直接访谈录像头画面和声卡的响声,再保存为摄像格式。

drawRect(float left, float top, float right, float bottom, Paint paint)

2. 流程

创建JCVideoRecordView时,伊始化JCVideoRecordManager, JCVideoRecordManager肩负管理录像访谈,摄像,压缩等操作,摄像截止后创设JCRecordPlayerView 来循环播放摄像的录像,点击鲜明回调给VCL。

录像预览的兑现

step1: 获得SufaceView控件, 设置基脾性能和对应监听(该控件的成立是异步的, 唯有在真正"希图"好以往工夫调用卡塔尔(قطر‎

mSurfaceView = (SurfaceView) findViewById(R.id.main_surface_view);
 //设置屏幕分辨率
mSurfaceHolder.setFixedSize(videoWidth, videoHeight);
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
mSurfaceHolder.addCallback(this);

step2: 完结接口的法子, 华为平板Created方法中开启录制的预览, 在平板电脑Destroyed中销毁

//////////////////////////////////////////////
// SurfaceView回调
/////////////////////////////////////////////
@Override
public void surfaceCreated(SurfaceHolder holder) {
    mSurfaceHolder = holder;
    startPreView(holder);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    if (mCamera != null) {
        Log.d(TAG, "surfaceDestroyed: ");
        //停止预览并释放摄像头资源
        mCamera.stopPreview();
        mCamera.release();
        mCamera = null;
    }
    if (mMediaRecorder != null) {
        mMediaRecorder.release();
        mMediaRecorder = null;
    }
}

step3: 完毕录像预览的法门

/**
 * 开启预览
 *
 * @param holder
 */
private void startPreView(SurfaceHolder holder) {
    Log.d(TAG, "startPreView: ");

    if (mCamera == null) {
        mCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);
    }
    if (mMediaRecorder == null) {
        mMediaRecorder = new MediaRecorder();
    }
    if (mCamera != null) {
        mCamera.setDisplayOrientation(90);
        try {
            mCamera.setPreviewDisplay(holder);
            Camera.Parameters parameters = mCamera.getParameters();
            //实现Camera自动对焦
            List<String> focusModes = parameters.getSupportedFocusModes();
            if (focusModes != null) {
                for (String mode : focusModes) {
                    mode.contains("continuous-video");
                    parameters.setFocusMode("continuous-video");
                }
            }
            mCamera.setParameters(parameters);
            mCamera.startPreview();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

Note: 上边增多了全自动对焦的代码, 不过局地手提式无线电话机恐怕不扶助

经过计算,6s的录像,方案a获取的录像极度清楚,大小为32M,方案比为200多k。构思到小录像上传、加载速度的渴求高于清晰度,所以果决选用了方案b。

通过一张图来打听drawRect的参数

$ 重要代码

JCVideoRecordManager.h

@protocol JCVideoRecordManagerDelegate <NSObject>
//录制结束
- (void)captureOutput:(AVCaptureFileOutput *)captureOutput didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL fromConnections:(NSArray *)connections error:(NSError *)error;

//录制时间
- (void)recordTimeCurrentTime:(CGFloat)currentTime totalTime:(CGFloat)totalTime;
@end

@interface JCVideoRecordManager : NSObject
@property (nonatomic, weak) id<JCVideoRecordManagerDelegate> delegate;
//摄像头视图层
@property (nonatomic, strong) AVCaptureVideoPreviewLayer *preViewLayer;

// 准备录制
- (void)prepareForRecord;

// 开始录制
- (void)startRecordToFile:(NSURL *)outPutFile;

// 停止录制
- (void)stopCurrentVideoRecording;

// 切换摄像头
- (void)switchCamera;

// 设置对焦
- (void)setFoucusWithPoint:(CGPoint)point;

//压缩视频
- (void)compressVideo:(NSURL *)inputFileURL complete:(void(^)(BOOL success, NSURL* outputUrl))complete;

JCVideoRecordManager.m

- (instancetype)init{
    self = [super init];
    if (self) {
        self.captureSession = [[AVCaptureSession alloc]init];
        self.movieFileOutput = [[AVCaptureMovieFileOutput alloc]init];
        //后台播放音频时需要注意加以下代码,否则会获取音频设备失败
        [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
        [[AVAudioSession sharedInstance] setMode:AVAudioSessionModeVideoRecording error:nil];
        [[AVAudioSession sharedInstance] setActive:YES withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:nil];
        [self prepareForRecord];
    }
    return self;
}

#pragma mark - 获取权限
  (void)getCameraAuth:(void(^)(BOOL boolValue, NSString *tipText))isAuthorized{
    __weak typeof(self) instance = self;
    //获取视频权限
    AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
    if (authStatus == AVAuthorizationStatusNotDetermined){
        [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo
                                 completionHandler:^(BOOL granted) {
                                     if (granted) {
                                         [instance getCameraAuth:isAuthorized];
                                     }else{
                                         isAuthorized(NO, @"没有获得相机权限");
                                     }
                                 }];
    }else if (authStatus == AVAuthorizationStatusAuthorized){
        [[AVAudioSession sharedInstance] requestRecordPermission:^(BOOL granted) {
            isAuthorized(granted,  @"没有获得麦克风权限");
        }];
    }else{
        isAuthorized(NO, @"没有获得相机权限");
    }
}

#pragma mark - 摄像头视图层
- (AVCaptureVideoPreviewLayer *)preViewLayer{
    if (!_preViewLayer) {
        _preViewLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.captureSession];
        _preViewLayer.masksToBounds = YES;
        _preViewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
    }
    return _preViewLayer;
}

#pragma mark 视频输入
- (AVCaptureDeviceInput *)mediaDeviceInput{
    if (!_mediaDeviceInput) {
        __block AVCaptureDevice *backCamera  = nil;
        NSArray *cameras = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
        [cameras enumerateObjectsUsingBlock:^(AVCaptureDevice *camera, NSUInteger idx, BOOL * _Nonnull stop) {
            if(camera.position == AVCaptureDevicePositionBack){
                backCamera = camera;
            }
        }];
        [self setExposureModeWithDevice:backCamera];
        _mediaDeviceInput = [AVCaptureDeviceInput deviceInputWithDevice:backCamera error:nil];
    }
    return _mediaDeviceInput;
}

#pragma mark 音频输入
- (AVCaptureDeviceInput *)audioDeviceInput{
    if (!_audioDeviceInput) {
        NSError *error;
        _audioDeviceInput = [AVCaptureDeviceInput deviceInputWithDevice:[AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio] error:&error];
    }
    return _audioDeviceInput;
}

#pragma mark - 输入输出对象连接
- (AVCaptureConnection *)captureConnection{
    return _captureConnection = _captureConnection ? : [self.movieFileOutput connectionWithMediaType:AVMediaTypeVideo];
}

#pragma mark 配置曝光模式 设置持续曝光模式
- (void)setExposureModeWithDevice:(AVCaptureDevice *)device{
    //注意改变设备属性前一定要首先调用lockForConfiguration:调用完之后使用unlockForConfiguration方法解锁
    NSError *error = nil;
    [device lockForConfiguration:&error];
    if ([device isExposureModeSupported:AVCaptureExposureModeContinuousAutoExposure]){
        [device setExposureMode:AVCaptureExposureModeContinuousAutoExposure];
    }
    [device unlockForConfiguration];
}

#pragma mark 计时器相关
- (NSTimer *)timer{
    if (!_timer){
        _timer = [NSTimer scheduledTimerWithTimeInterval:KTimerInterval target:self selector:@selector(fire:) userInfo:nil repeats:YES];
    }
    return _timer;
}

- (void)fire:(NSTimer *)timer{
    self.recordTime  = KTimerInterval;
    if ([self.delegate respondsToSelector:@selector(recordTimeCurrentTime:totalTime:)]) {
        [self.delegate recordTimeCurrentTime:self.recordTime totalTime:KMaxRecordTime];
    }
    if(_recordTime >= KMaxRecordTime){
        [self stopCurrentVideoRecording];
    }
}

- (void)startTimer{
    [self.timer invalidate];
    self.timer = nil;
    self.recordTime = 0;
    [self.timer fire];
}

- (void)stopTimer{
    [self.timer invalidate];
    self.timer = nil;
}

#pragma mark 准备录制
- (void)prepareForRecord{
    [self.captureSession beginConfiguration];

    //视频采集质量
    [self.captureSession canSetSessionPreset:AVCaptureSessionPresetHigh] ? [self.captureSession setSessionPreset:AVCaptureSessionPresetHigh] : nil;

    //添加input
    [self.captureSession canAddInput:self.mediaDeviceInput] ? [self.captureSession addInput:self.mediaDeviceInput] : nil;
    [self.captureSession canAddInput:self.audioDeviceInput] ? [self.captureSession addInput:self.audioDeviceInput] : nil;

    //添加output
    [self.captureSession canAddOutput:self.movieFileOutput] ? [self.captureSession addOutput:self.movieFileOutput] : nil;

    [self.captureSession commitConfiguration];

    // 防抖功能
    if ([self.captureConnection isVideoStabilizationSupported] && self.captureConnection.activeVideoStabilizationMode == AVCaptureVideoStabilizationModeOff){
        self.captureConnection.preferredVideoStabilizationMode = AVCaptureVideoStabilizationModeAuto;
    }

    [self.captureSession startRunning];
}

#pragma mark 切换摄像头
- (void)switchCamera{
    [_captureSession beginConfiguration];
    [_captureSession removeInput:_mediaDeviceInput];
    AVCaptureDevice *swithToDevice = [self switchCameraDevice];
    [swithToDevice lockForConfiguration:nil];
    [self setExposureModeWithDevice:swithToDevice];
    self.mediaDeviceInput = [AVCaptureDeviceInput deviceInputWithDevice:swithToDevice error:nil];
    [_captureSession addInput:_mediaDeviceInput];
    [_captureSession commitConfiguration];
}

#pragma mark 获取切换时的摄像头
- (AVCaptureDevice *)switchCameraDevice{
    AVCaptureDevice *currentDevice = [self.mediaDeviceInput device];
    AVCaptureDevicePosition currentPosition = [currentDevice position];
    BOOL isUnspecifiedOrFront = (currentPosition == AVCaptureDevicePositionUnspecified || currentPosition ==AVCaptureDevicePositionFront );
    AVCaptureDevicePosition swithToPosition = isUnspecifiedOrFront ? AVCaptureDevicePositionBack:AVCaptureDevicePositionFront;
    NSArray *cameras = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
    __block AVCaptureDevice *swithCameraDevice = nil;
    [cameras enumerateObjectsUsingBlock:^(AVCaptureDevice *camera, NSUInteger idx, BOOL * _Nonnull stop) {
        if (camera.position == swithToPosition){
            swithCameraDevice = camera;
            *stop = YES;
        };
    }];
    return swithCameraDevice;
}

#pragma mark 开始录制
- (void)startRecordToFile:(NSURL *)outPutFile{

    if (!self.captureConnection) {
        return;
    }

    if ([self.movieFileOutput isRecording]) {
        return;
    }
    if ([self.captureConnection isVideoOrientationSupported]){
        self.captureConnection.videoOrientation =[self.preViewLayer connection].videoOrientation;
    }
    [_movieFileOutput startRecordingToOutputFileURL:outPutFile recordingDelegate:self];
}

#pragma mark  停止录制
- (void)stopCurrentVideoRecording{
    if (self.movieFileOutput.isRecording) {
        [self stopTimer];
        [_movieFileOutput stopRecording];
    }
}

#pragma mark 设置对焦
- (void)setFoucusWithPoint:(CGPoint)point{
    CGPoint cameraPoint= [self.preViewLayer captureDevicePointOfInterestForPoint:point];
    [self focusWithMode:AVCaptureFocusModeContinuousAutoFocus exposureMode:AVCaptureExposureModeContinuousAutoExposure atPoint:cameraPoint];
}

-(void)focusWithMode:(AVCaptureFocusMode)focusMode exposureMode:(AVCaptureExposureMode)exposureMode atPoint:(CGPoint)point{
    [self changeDeviceProperty:^(AVCaptureDevice *captureDevice) {

        if ([captureDevice isFocusModeSupported:focusMode]) {
            [captureDevice setFocusMode:focusMode];
        }

        if ([captureDevice isFocusPointOfInterestSupported]) {
            [captureDevice setFocusPointOfInterest:point];
        }

        if ([captureDevice isExposureModeSupported:exposureMode]) {
            [captureDevice setExposureMode:exposureMode];
        }

        if ([captureDevice isExposurePointOfInterestSupported]) {
            [captureDevice setExposurePointOfInterest:point];
        }
    }];
}
#pragma mark - 改变设备属性方法
- (void)changeDeviceProperty:(void (^)(id obj))propertyChange
{
    AVCaptureDevice *captureDevice = [self.mediaDeviceInput device];
    NSError *error;

    if ([captureDevice lockForConfiguration:&error]) {
        propertyChange(captureDevice);
        [captureDevice unlockForConfiguration];
    }else{

    }
}

#pragma mark - AVCaptureFileOutputRecordignDelegate method

// 录制开始
- (void)captureOutput:(AVCaptureFileOutput *)captureOutput didStartRecordingToOutputFileAtURL:(NSURL *)fileURL fromConnections:(NSArray *)connections{
    [self startTimer];
}

// 录制结束
-(void)captureOutput:(AVCaptureFileOutput *)captureOutput didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL fromConnections:(NSArray *)connections error:(NSError *)error{
    [self stopTimer];
    if (self.delegate && [self.delegate respondsToSelector:@selector(captureOutput:didFinishRecordingToOutputFileAtURL:fromConnections:error:)]) {
        [self.delegate captureOutput:captureOutput didFinishRecordingToOutputFileAtURL:outputFileURL fromConnections:connections error:error];
    }
    [self.captureSession stopRunning];
}

#pragma mark - 压缩视频
- (void)compressVideo:(NSURL *)inputFileURL complete:(void(^)(BOOL success, NSURL* outputUrl))complete{
    NSURL *outPutUrl = [NSURL fileURLWithPath:[JCVideoRecordManager cacheFilePath:NO]];
    [self convertVideoQuailtyWithInputURL:inputFileURL outputURL:outPutUrl completeHandler:^(AVAssetExportSession *exportSession) {
        complete(exportSession.status == AVAssetExportSessionStatusCompleted, outPutUrl);
    }];
}

- (void)convertVideoQuailtyWithInputURL:(NSURL*)inputURL
                               outputURL:(NSURL*)outputURL
                         completeHandler:(void (^)(AVAssetExportSession*))handler{
    AVURLAsset *avAsset = [AVURLAsset URLAssetWithURL:inputURL options:nil];

    AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:avAsset presetName:AVAssetExportPresetMediumQuality];

    exportSession.outputURL = outputURL;
    exportSession.outputFileType = AVFileTypeMPEG4;
    exportSession.shouldOptimizeForNetworkUse= YES;
    [exportSession exportAsynchronouslyWithCompletionHandler:^(void){
         handler(exportSession);
    }];
}

自定义双向裁减的进程条

有一点像自家同样的初读书人一见到自定义某某View, 就感觉比较牛X. 其实呢, Google已经替我们写好了广大代码, 所以我们用就能够了.并且我们的那个进度条也没啥, 不正是一根线, 前天吾就来讲说.

step1: 世襲View, 完毕起头化

private static final String TAG = "BothWayProgressBar";
//取消状态为红色bar, 反之为绿色bar
private boolean isCancel = false;
private Context mContext;
//正在录制的画笔
private Paint mRecordPaint;
//上滑取消时的画笔
private Paint mCancelPaint;
//是否显示
private int mVisibility;
// 当前进度
private int progress;
//进度条结束的监听
private OnProgressEndListener mOnProgressEndListener;

public BothWayProgressBar(Context context) {
     super(context, null);
}
public BothWayProgressBar(Context context, AttributeSet attrs) {
   super(context, attrs);
   mContext = context;
   init();
}
private void init() {
   mVisibility = INVISIBLE;
   mRecordPaint = new Paint();
   mRecordPaint.setColor(Color.GREEN);
   mCancelPaint = new Paint();
   mCancelPaint.setColor(Color.RED);
}

Note: OnProgressEndListener, 首要用于当进程条走到中游了, 好布告相机停止录像, 接口如下:

public interface OnProgressEndListener{
    void onProgressEndListener();
}
/**
 * 当进度条结束后的 监听
 * @param onProgressEndListener
 */
public void setOnProgressEndListener(OnProgressEndListener onProgressEndListener) {
    mOnProgressEndListener = onProgressEndListener;
}

step2 :设置Setter方法用于布告大家的Progress退换状态

/**
 * 设置进度
 * @param progress
 */
public void setProgress(int progress) {
    this.progress = progress;
    invalidate();
}

/**
 * 设置录制状态 是否为取消状态
 * @param isCancel
 */
public void setCancel(boolean isCancel) {
    this.isCancel = isCancel;
    invalidate();
}
/**
 * 重写是否可见方法
 * @param visibility
 */
@Override
public void setVisibility(int visibility) {
    mVisibility = visibility;
    //重新绘制
    invalidate();
}

step3 :最要紧的一步, 画出大家的进程条,使用的就是View中的onDraw(Canvas canvas卡塔尔方法

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    if (mVisibility == View.VISIBLE) {
        int height = getHeight();
        int width = getWidth();
        int mid = width / 2;


        //画出进度条
        if (progress < mid){
            canvas.drawRect(progress, 0, width-progress, height, isCancel ? mCancelPaint : mRecordPaint);
        } else {
            if (mOnProgressEndListener != null) {
                mOnProgressEndListener.onProgressEndListener();
            }
        }
    } else {
        canvas.drawColor(Color.argb(0, 0, 0, 0));
    }
}

WeiXinCamera内部达成“按住拍、线条稳步变窄为0”的动漫效果,抽出封装一下也足以用。

本文由澳门新葡亰发布于计算机知识,转载请注明出处:仿微信录制小视频,Android仿微信录制小视频的进

关键词: 日记本 Android 进度条 小视频 iOS分享的demo

上一篇:安卓开发,的最佳实践

下一篇:没有了

最火资讯