最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android錄制按鈕源碼解析

 更新時間:2021年08月25日 11:28:23   作者:碧云天丶  
這篇文章主要為大家詳細解析了Android錄制按鈕源碼,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

本文實例為大家分享了Android實現(xiàn)錄制按鈕的具體代碼,供大家參考,具體內(nèi)容如下

初始化

布局文件中參數(shù)

private void initParame(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RButtonY, defStyleAttr, 0);
    //外圓和內(nèi)部正方形之間的間距
    mCircleOutMarginSize = typedArray.getDimensionPixelSize(R.styleable.RButtonY_rby_circle_out_margin, 5);
    //外圓畫筆的寬度
    mCircleWidth = typedArray.getDimensionPixelSize(R.styleable.RButtonY_rby_circle_width, 5);
    //外圓畫筆的顏色
    mCirclePaintColor = typedArray.getColor(R.styleable.RButtonY_rby_circle_paint_color, Color.YELLOW);
    //內(nèi)部正方形畫筆的顏色
    mRectPaintColor = typedArray.getColor(R.styleable.RButtonY_rby_rect_paint_color, Color.RED);
    //內(nèi)部正方形初始邊長相對于外圓內(nèi)切正方形邊長比率 0-1 
    mRectRateStart = typedArray.getFloat(R.styleable.RButtonY_rby_rect_rate_start, 0.9f);
    //內(nèi)部正方形結(jié)束邊長相對于外圓內(nèi)切正方形邊長比率 0-1 
    mRectRateFinish = typedArray.getFloat(R.styleable.RButtonY_rby_rect_rate_fnish, 0.5f);
    //錄制規(guī)定最短時間
    mShortest = typedArray.getInteger(R.styleable.RButtonY_rby_short_time, 3);
    //錄制規(guī)定最長時間
    mLongest = typedArray.getInteger(R.styleable.RButtonY_rby_long_time, 10);
    typedArray.recycle();
}

畫筆初始化

// Paint.Style.FILL設(shè)置只繪制圖形內(nèi)容
// Paint.Style.STROKE設(shè)置只繪制圖形的邊
// Paint.Style.FILL_AND_STROKE設(shè)置都繪制
private void initPaint() {
    //外圓畫筆
    mCirclePaint = new Paint();
    mCirclePaint.setAntiAlias(true);
    mCirclePaint.setColor(mCirclePaintColor);
    mCirclePaint.setStyle(Paint.Style.STROKE);
    mCirclePaint.setStrokeWidth(mCircleWidth);
    //內(nèi)部正方形畫筆
    mRectPaint = new Paint();
    mRectPaint.setAntiAlias(true);
    mRectPaint.setColor(mRectPaintColor);
    mRectPaint.setStyle(Paint.Style.FILL_AND_STROKE);
}

內(nèi)部正方形RectF初始化

private void initRect() {
        mRectF = new RectF();
}

內(nèi)部正方形所需動畫初始化, 當(dāng)開始錄制或者結(jié)束錄制時候,內(nèi)部正方形會有一個動畫效果,這個動畫效果需要內(nèi)部正方形邊長改變才能實現(xiàn).

/**
 * 初始化動畫
 * 這里對動畫進行監(jiān)聽, 獲取正方形邊長隨動畫改變的值,然后重繪
 */
private void initAnimator() {
    mAnimator = new ValueAnimator();
    /**
     * onAnimationStart() - 當(dāng)動畫開始的時候調(diào)用.
     * onAnimationEnd() - 動畫結(jié)束時調(diào)用.
     * onAnimationRepeat() - 動畫重復(fù)時調(diào)用.
     * onAnimationCancel() - 動畫取消時調(diào)用.取消動畫也會調(diào)用onAnimationEnd,它不會關(guān)系動畫是怎么結(jié)束的。
     */
    mAnimator.addListener(new AnimatorListenerAdapter() {
        @Override
        public void onAnimationEnd(Animator animation) {
            //動畫結(jié)束
            isAnimRuning = false;
        }
        @Override
        public void onAnimationStart(Animator animation) {
            //動畫開始
            isAnimRuning = true;
        }
    });
    //動畫進度監(jiān)聽,獲取正方形隨動畫變化的邊長,然后重繪
    mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            //動態(tài)獲取正方形邊長
            mTempRectSize = (float) animation.getAnimatedValue();
            invalidate();//重繪
        }
    });
}

確定圓形半徑,圓心坐標(biāo),內(nèi)部正方形邊長等

 @Override
 protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
     super.onLayout(changed, left, top, right, bottom);
     int width = getWidth();
     int height = getHeight();
     //圓心坐標(biāo)
     centerX = width / 2;
     centerY = height / 2;
     //半徑
     radius = Math.min(centerX, centerY) - mCircleOutMarginSize / 2;
     //pow 平方,sqrt 開方
     //正方形開始邊長,圓形直徑的平方除以二再開放,為正方形邊長.
     mRectStartSize = (int) (Math.sqrt(Math.pow(radius * 2, 2) / 2) * mRectRateStart);
     //正方形結(jié)束邊長
     mRectEndSize = (int) (mRectStartSize * mRectRateFinish);
    //mTempRectSize == 0 時, 即第一創(chuàng)建該View.
    if (mTempRectSize == 0) {
        //如果屏幕旋轉(zhuǎn),onLayout將被回調(diào),此時并不希望mTempRectSize被重新賦值為mRectStartSize(開始狀態(tài)).
        //所以只有當(dāng)?shù)谝淮蝿?chuàng)建時,才需要為mTempRectSize賦值為mRectStartSize(開始狀態(tài))
        mTempRectSize = mRectStartSize;
    }
 }

繪制內(nèi)部正方形和外圓

@Override
 protected void onDraw(Canvas canvas) {
     super.onDraw(canvas);
     //外圓繪制
     canvas.drawCircle(centerX, centerY, radius, mCirclePaint);
     //正方形四點坐標(biāo)
     int mLeftRectTemp = (int) (centerX - mTempRectSize / 2);
     int mRightRectTemp = (int) (centerX + mTempRectSize / 2);
     int mTopRectTemp = (int) (centerY + mTempRectSize / 2);
     int mButtonRectTemp = (int) (centerY - mTempRectSize / 2);
     //繪制正方形
     mRectF.set(mLeftRectTemp, mTopRectTemp, mRightRectTemp, mButtonRectTemp);
     //(float) Math.sqrt(radius): 圓角半徑
     canvas.drawRoundRect(mRectF, (float) Math.sqrt(radius), (float) Math.sqrt(radius), mRectPaint);
 }

錄制開始和結(jié)束方法以及動畫執(zhí)行方法

/**
 * 錄制開始
 */
private void recordStart() {
    //正方形開始動畫
    startAnimation(mRectStartSize, mRectEndSize);
    if (rbyCb != null) {
        //錄制開始的回調(diào)
        rbyCb.startCb(String.valueOf(mCurrent));
    }
    //開始計時
    mHandler.sendEmptyMessage(0);
    //錄制標(biāo)識為開始
    up = true;
    mTempRectSize = mRectEndSize;
}
/**
 * 錄制結(jié)束
 */
private void recordFinish() {
    //正方形結(jié)束動畫
    startAnimation(mRectEndSize, mRectStartSize);
    if (rbyCb != null) {
        //結(jié)束時回調(diào)
        rbyCb.finishCb(String.valueOf(mCurrent));
    }
    //錄制結(jié)束,當(dāng)前時間歸0
    mCurrent = 0;
    mHandler.removeCallbacksAndMessages(null);
    //錄制標(biāo)識為結(jié)束
    up = false;
    mTempRectSize = mRectStartSize;
}
/**
 * 開始動畫
 *
 * @param startValue
 * @param endValue
 */
private void startAnimation(float startValue, float endValue)
    mAnimator.setFloatValues(startValue, endValue);
    mAnimator.setDuration(100);
    mAnimator.setInterpolator(new LinearInterpolator());
    mAnimator.start();
}

回調(diào)接口

public interface RBYCallback {
    /**
     * 記錄結(jié)束的回調(diào)
     *
     * @param current
     */
    void finishCb(String current);
    /**
     * 每一秒 都會觸發(fā)該回調(diào)
     *
     * @param current
     */
    void eventCb(String current);
    /**
     * 開始記錄的回調(diào)
     */
    void startCb(String current);
    /**
     * 錄制時長小于錄制最短要求時間之時,用戶點擊按鈕時候,回調(diào)該方法
     */
    void lessShortTimeRecode(String current);
}

對控件點擊事件進行處理

@Override
public boolean onTouchEvent(MotionEvent event) {
    switch (event.getAction()) {
        case MotionEvent.ACTION_UP:
            //如果正方形動畫正在播放,就拒絕按鈕點擊
            if (isAnimRuning) return true;
            //up為false代表未開始記錄,true 代表開始記錄
            //未開始記錄時,mCurrent是等于0
            if (!up && mCurrent == 0) {
                recordStart();
            }
            //已開始記錄,并且當(dāng)前錄制時間大于或者等于所設(shè)置的最短記錄時長,則按鈕可以手動結(jié)束
            if (up && mCurrent >= mShortest) {
                recordFinish();
            }
            //已開始記錄,當(dāng)前錄制時間小于所設(shè)置的最短記錄時長,并且錄制時間大于1,則回調(diào)方法通知當(dāng)前還不能手動結(jié)束錄制
            if (up && mCurrent < mShortest && mCurrent >= 1) {
                if (rbyCb != null) {
                    rbyCb.lessShortTimeRecode(String.valueOf(mCurrent));
                }
            }
            break;
    }
    return true;//消費事件
}

屏幕旋轉(zhuǎn)保存與還原數(shù)據(jù)

//屏幕旋轉(zhuǎn)時候保存必要的數(shù)據(jù)
@Nullable
@Override
protected Parcelable onSaveInstanceState() {
    if (mCurrent != 0) {
        Bundle bundle = new Bundle();
        //保存系統(tǒng)其他原有的狀態(tài)信息
        bundle.putParcelable("instance", super.onSaveInstanceState());
        //保存當(dāng)前的一些狀態(tài)
        bundle.putFloat("rect_size", mTempRectSize);//保存方形邊長
        bundle.putBoolean("up", up);//當(dāng)前錄制狀態(tài)
        bundle.putInt("mCurrent", mCurrent);//當(dāng)前錄制時間
        return bundle;
    } else {
        return super.onSaveInstanceState();
    }
}
@Override
protected void onRestoreInstanceState(Parcelable state) {
    //判斷state的類型是否為bundle,若是則從bundle中取數(shù)據(jù)
    if (state instanceof Bundle) {
        Bundle bundle = (Bundle) state;
        mTempRectSize = bundle.getFloat("rect_size");
        up = bundle.getBoolean("up");
        mCurrent = bundle.getInt("mCurrent");
        //開始計時
        mHandler.sendEmptyMessage(0);
        super.onRestoreInstanceState(bundle.getParcelable("instance"));
        return;
    }
    super.onRestoreInstanceState(state);
}

定時mHandler

@SuppressLint("HandlerLeak")
private Handler mHandler = new Handler() {
    @Override
    public void handleMessage(@NonNull Message msg) {
        super.handleMessage(msg);
        mCurrent++;
        if (rbyCb != null) {
            rbyCb.eventCb(String.valueOf(mCurrent));
        }
        if (mCurrent >= mLongest) {//當(dāng)前記錄時間大于或等于最大記錄時間,將自動結(jié)束記錄
            recordFinish();
        } else {
            mHandler.sendEmptyMessageDelayed(0, 1000);
        }
    }
};

頁面銷毀處理

//頁面銷毀,清空消息,防止內(nèi)存泄漏
@Override
protected void onDetachedFromWindow() {
    super.onDetachedFromWindow();
    mHandler.removeCallbacksAndMessages(null);
    mHandler = null;
}

效果圖

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Android性能優(yōu)化getResources()與Binder導(dǎo)致界面卡頓優(yōu)化

    Android性能優(yōu)化getResources()與Binder導(dǎo)致界面卡頓優(yōu)化

    這篇文章主要為大家介紹了Android性能優(yōu)化getResources()與Binder導(dǎo)致界面卡頓優(yōu)化示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-02-02
  • android 簡單圖片動畫播放的實例代碼

    android 簡單圖片動畫播放的實例代碼

    android 簡單圖片動畫播放的實例代碼,需要的朋友可以參考一下
    2013-06-06
  • android studio 新建項目報錯的解決之路

    android studio 新建項目報錯的解決之路

    這篇文章主要介紹了android studio 新建工程報錯,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-03-03
  • Android 保存文件路徑方法

    Android 保存文件路徑方法

    今天小編就為大家分享一篇Android 保存文件路徑方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-08-08
  • 詳解Android Handler機制和Looper Handler Message關(guān)系

    詳解Android Handler機制和Looper Handler Message關(guān)系

    Handler是Android線程之間的消息機制,主要的作用是將一個任務(wù)切換到指定的線程中去執(zhí)行,準(zhǔn)確的說是切換到構(gòu)成Handler的looper所在的線程中去出處理。本文將詳細介紹Android Handler機制和Looper Handler Message關(guān)系。
    2021-06-06
  • 使用Chrome瀏覽器調(diào)試Android App詳解

    使用Chrome瀏覽器調(diào)試Android App詳解

    這篇文章主要介紹了使用Chrome瀏覽器調(diào)試Android App詳解,本網(wǎng)講解了使用Facebook開源Stetho實現(xiàn)在Chrome中調(diào)試Android App中,需要的朋友可以參考下
    2015-05-05
  • Android MediaPlayer音頻播放器封裝示例淺析

    Android MediaPlayer音頻播放器封裝示例淺析

    Android提供了許多方法來控制播放的音頻/視頻文件和流。其中該方法是通過一類稱為MediaPlayer。Android是提供MediaPlayer類訪問內(nèi)置的媒體播放器的服務(wù),如播放音頻,視頻等為了使用MediaPlayer,我們要調(diào)用這個類的靜態(tài)create()方法
    2023-04-04
  • Android?Studio中使用SQLite數(shù)據(jù)庫實現(xiàn)登錄和注冊功能

    Android?Studio中使用SQLite數(shù)據(jù)庫實現(xiàn)登錄和注冊功能

    SQLite是一款輕型的數(shù)據(jù)庫,是遵守ACID的關(guān)系型數(shù)據(jù)庫管理系統(tǒng),它包含在一個相對小的C庫中,下面這篇文章主要給大家介紹了關(guān)于Android?Studio中使用SQLite數(shù)據(jù)庫實現(xiàn)登錄和注冊功能的相關(guān)資料,需要的朋友可以參考下
    2024-06-06
  • Android實現(xiàn)仿魅族日歷首頁功能

    Android實現(xiàn)仿魅族日歷首頁功能

    這篇文章主要介紹了Android實現(xiàn)仿魅族日歷首頁功能的實現(xiàn)過程以及相關(guān)代碼講解分享,對此有興趣的朋友參考下。
    2018-02-02
  • Android獲取通話時間實例分析

    Android獲取通話時間實例分析

    我們知道安卓系統(tǒng)中通話時長應(yīng)該是歸Callog管,所以建議去查查ContactProvider,或者是TelephonyProvider,本文也總結(jié)了一些,需要的朋友可以參考下
    2012-12-12

最新評論

武鸣县| 堆龙德庆县| 诏安县| 曲靖市| 巨野县| 吉水县| 玛沁县| 乐安县| 昭平县| 麻江县| 平阴县| 白银市| 海伦市| 平原县| 彭州市| 石家庄市| 上犹县| 兴国县| 团风县| 株洲市| 云安县| 松原市| 茌平县| 交口县| 柳州市| 贞丰县| 大邑县| 徐州市| 平塘县| 衡水市| 博白县| 姜堰市| 垫江县| 明水县| 厦门市| 长垣县| 鄂托克旗| 乐平市| 苍溪县| 南开区| 漳州市|