国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 系統(tǒng) > Android > 正文

Android自定義雙向進(jìn)度條的實(shí)現(xiàn)代碼

2019-10-22 18:27:59
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

想整個(gè)雙向的進(jìn)度條,就是可以選取播放范圍的。

像這樣:

Android,雙向進(jìn)度條,自定義進(jìn)度條

然而官方控件里只有單向的。不要慌,我們自己畫(huà)一個(gè)。

繪制一個(gè)進(jìn)度條主要是三方面。1.樣式,2.尺寸,3.操作監(jiān)聽(tīng)。

完整代碼來(lái)一遍:

注釋基本上就把原理說(shuō)明了一下。

package util;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.drawable.Drawable;import android.support.v4.content.ContextCompat;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.view.View;import com.example.qzd.utildemo.R;import java.math.BigDecimal;/** * 雙向滑塊的進(jìn)度條(區(qū)域選擇) */public class SeekRangeBar extends View {  private Context _context;  private static final int CLICK_ON_LOW = 1;    //手指在前滑塊上滑動(dòng)  private static final int CLICK_ON_HIGH = 2;    //手指在后滑塊上滑動(dòng)  private static final int CLICK_IN_LOW_AREA = 3;  //手指點(diǎn)擊離前滑塊近  private static final int CLICK_IN_HIGH_AREA = 4; //手指點(diǎn)擊離后滑塊近  private static final int CLICK_OUT_AREA = 5;   //手指點(diǎn)擊在view外  private static final int CLICK_INVAILD = 0;  private static final int[] STATE_NORMAL = {};  private static final int[] STATE_PRESSED = {android.R.attr.state_pressed,android.R.attr.state_window_focused,};  private static int mThumbMarginTop = 0;  //滑動(dòng)塊頂部離view頂部的距離  private static int mTextViewMarginTop = 0;  //當(dāng)前滑塊文字距離view頂部距離  private Drawable hasScrollBarBg;    //滑動(dòng)條滑動(dòng)后背景圖  private Drawable notScrollBarBg;    //滑動(dòng)條未滑動(dòng)背景圖  private Drawable mThumbLow;     //前滑塊  private Drawable mThumbHigh;    //后滑塊  private int mScollBarWidth;   //控件寬度 = 滑動(dòng)條寬度 + 滑動(dòng)塊寬度  private int mScollBarHeight;  //控件高度  private int mThumbWidth;    //滑動(dòng)塊直徑  private double mOffsetLow = 0;   //前滑塊中心坐標(biāo)  private double mOffsetHigh = 0;  //后滑塊中心坐標(biāo)  private int mDistance=0;   //總刻度是固定距離 兩邊各去掉半個(gè)滑塊距離  private int mFlag = CLICK_INVAILD;  //手指按下的類型  private double defaultScreenLow = 0;  //默認(rèn)前滑塊位置百分比  private double defaultScreenHigh = 100; //默認(rèn)后滑塊位置百分比  private OnSeekBarChangeListener mBarChangeListener;  private boolean editable=false;//是否處于可編輯狀態(tài)  private int miniGap=5;//AB的最小間隔  private double progressLow;//起點(diǎn)(百分比)  private double progressHigh;//終點(diǎn)  public SeekRangeBar(Context context) {    this(context, null);  }  public SeekRangeBar(Context context, AttributeSet attrs) {    this(context, attrs, 0);  }  public SeekRangeBar(Context context, AttributeSet attrs, int defStyle) {    super(context, attrs, defStyle);    _context=context;    //這里設(shè)置背景圖及滑塊圖,自定義過(guò)進(jìn)度條的同學(xué)應(yīng)該很熟悉了    notScrollBarBg = ContextCompat.getDrawable(_context,R.mipmap.hp_wbf);    hasScrollBarBg = ContextCompat.getDrawable(_context, R.mipmap.hp_ybf);    mThumbLow = ContextCompat.getDrawable(_context,R.mipmap.hp_a);    mThumbHigh = ContextCompat.getDrawable(_context,R.mipmap.hp_b);    mThumbLow.setState(STATE_NORMAL);    mThumbHigh.setState(STATE_NORMAL);    //設(shè)置滑動(dòng)條高度    mScollBarHeight = notScrollBarBg.getIntrinsicHeight();    //設(shè)置滑動(dòng)塊直徑    mThumbWidth = mThumbLow.getIntrinsicWidth();  }  /**   * 測(cè)量view尺寸(在onDraw()之前)   * @param widthMeasureSpec   * @param heightMeasureSpec   */  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {    int width = MeasureSpec.getSize(widthMeasureSpec);    mScollBarWidth = width;    if(mDistance==0) {//這里滑塊中心坐標(biāo)初始化的時(shí)候測(cè)量一下(根據(jù)mDistance是否賦值判斷),并不需要不停地去測(cè)量。后面會(huì)根據(jù)進(jìn)度計(jì)算滑塊位置。      mOffsetLow = mThumbWidth / 2;      mOffsetHigh = width - mThumbWidth / 2;    }    mDistance = width - mThumbWidth;    if(defaultScreenLow != 0) {      mOffsetLow = formatInt(defaultScreenLow / 100 * (mDistance)) + mThumbWidth / 2;    }    if(defaultScreenHigh != 100) {      mOffsetHigh = formatInt(defaultScreenHigh / 100 * (mDistance)) + mThumbWidth / 2;    }    setMeasuredDimension(width, mThumbWidth + mThumbMarginTop + 2);  }  protected void onLayout(boolean changed, int l, int t, int r, int b) {    super.onLayout(changed, l, t, r, b);  }  /**   * 繪制進(jìn)度條   */  protected void onDraw(Canvas canvas) {    super.onDraw(canvas);    //設(shè)置繪制樣式    Paint text_Paint = new Paint();    text_Paint.setTextAlign(Paint.Align.CENTER);    text_Paint.setColor(Color.RED);    text_Paint.setTextSize(20);    int top = mThumbMarginTop + mThumbWidth / 2 - mScollBarHeight / 2;    int bottom = top + mScollBarHeight;    //繪制是否可操作狀態(tài)的下的不同樣式,僅可編輯狀態(tài)下顯示進(jìn)度條    if(editable) {      //白色滑動(dòng)條,兩個(gè)滑塊各兩邊部分      notScrollBarBg.setBounds(mThumbWidth / 2, top, mScollBarWidth - mThumbWidth / 2, bottom);      notScrollBarBg.draw(canvas);      //紅色滑動(dòng)條,兩個(gè)滑塊中間部分      hasScrollBarBg.setBounds((int) mOffsetLow, top, (int) mOffsetHigh, bottom);      hasScrollBarBg.draw(canvas);    }    //前滑塊    mThumbLow.setBounds((int) (mOffsetLow - mThumbWidth / 2), mThumbMarginTop, (int) (mOffsetLow + mThumbWidth / 2), mThumbWidth + mThumbMarginTop);    mThumbLow.draw(canvas);    //后滑塊    mThumbHigh.setBounds((int) (mOffsetHigh - mThumbWidth / 2), mThumbMarginTop, (int) (mOffsetHigh + mThumbWidth / 2), mThumbWidth + mThumbMarginTop);    mThumbHigh.draw(canvas);    //當(dāng)前滑塊刻度    progressLow = formatInt((mOffsetLow - mThumbWidth / 2) * 100 / mDistance);    progressHigh = formatInt((mOffsetHigh - mThumbWidth / 2) * 100 / mDistance);    canvas.drawText((int) progressLow + "", (int) mOffsetLow - 2 - 2, mTextViewMarginTop, text_Paint);    canvas.drawText((int) progressHigh + "", (int) mOffsetHigh - 2, mTextViewMarginTop, text_Paint);    if (mBarChangeListener != null) {      mBarChangeListener.onProgressChanged(this, progressLow, progressHigh);    }  }  //手勢(shì)監(jiān)聽(tīng)  @Override  public boolean onTouchEvent(MotionEvent e) {    if(!editable) {      return false;    }    if (e.getAction() == MotionEvent.ACTION_DOWN) {      mFlag = getAreaFlag(e);      if (mFlag == CLICK_ON_LOW) {        mThumbLow.setState(STATE_PRESSED);      } else if (mFlag == CLICK_ON_HIGH) {        mThumbHigh.setState(STATE_PRESSED);      } else if (mFlag == CLICK_IN_LOW_AREA) {        mThumbLow.setState(STATE_PRESSED);        mThumbHigh.setState(STATE_NORMAL);        //如果點(diǎn)擊0-mThumbWidth/2坐標(biāo)        if (e.getX() < 0 || e.getX() <= mThumbWidth / 2) {          mOffsetLow = mThumbWidth / 2;        } else if (e.getX() > mScollBarWidth - mThumbWidth / 2) {          mOffsetLow = mThumbWidth / 2 + mDistance;        } else {          mOffsetLow = formatInt(e.getX());        }      } else if (mFlag == CLICK_IN_HIGH_AREA) {        mThumbHigh.setState(STATE_PRESSED);        mThumbLow.setState(STATE_NORMAL);        if (e.getX() >= mScollBarWidth - mThumbWidth / 2) {          mOffsetHigh = mDistance + mThumbWidth / 2;        } else {          mOffsetHigh = formatInt(e.getX());        }      }      //更新滑塊      invalidate();    } else if (e.getAction() == MotionEvent.ACTION_MOVE) {      if (mFlag == CLICK_ON_LOW) {        if (e.getX() < 0 || e.getX() <= mThumbWidth / 2) {          mOffsetLow = mThumbWidth / 2;        } else if (e.getX() >= mScollBarWidth - mThumbWidth / 2) {          mOffsetLow = mThumbWidth / 2 + mDistance;          mOffsetHigh = mOffsetLow;        } else {          mOffsetLow = formatInt(e.getX());          if (mOffsetHigh - mOffsetLow <= 0) {            mOffsetHigh = (mOffsetLow <= mDistance + mThumbWidth / 2) ? (mOffsetLow) : (mDistance + mThumbWidth / 2);          }        }      } else if (mFlag == CLICK_ON_HIGH) {        if (e.getX() < mThumbWidth / 2) {          mOffsetHigh = mThumbWidth / 2;          mOffsetLow = mThumbWidth / 2;        } else if (e.getX() > mScollBarWidth - mThumbWidth / 2) {          mOffsetHigh = mThumbWidth / 2 + mDistance;        } else {          mOffsetHigh = formatInt(e.getX());          if (mOffsetHigh - mOffsetLow <= 0) {            mOffsetLow = (mOffsetHigh >= mThumbWidth / 2) ? (mOffsetHigh) : mThumbWidth / 2;          }        }      }      //更新滑塊,每次滑塊有動(dòng)作都要執(zhí)行此函數(shù)觸發(fā)onDraw方法繪制新圖片      invalidate();    } else if (e.getAction() == MotionEvent.ACTION_UP) {      Log.d("LOGCAT","ACTION UP:"+progressHigh+"-"+progressLow);      mThumbLow.setState(STATE_NORMAL);      mThumbHigh.setState(STATE_NORMAL);      if(miniGap>0 && progressHigh<progressLow+miniGap){        progressHigh=progressLow+miniGap;        this.defaultScreenHigh = progressHigh;        mOffsetHigh = formatInt(progressHigh / 100 * (mDistance)) + mThumbWidth / 2;        invalidate();      }    }    return true;  }  /**   * 設(shè)置是否可編輯狀態(tài),非可編輯狀態(tài)將不能對(duì)AB點(diǎn)進(jìn)行操作   * @param _b   */  public void setEditable(boolean _b){    editable=_b;    invalidate();  }  /**   * 獲取當(dāng)前手指位置   */  public int getAreaFlag(MotionEvent e) {    int top = mThumbMarginTop;    int bottom = mThumbWidth + mThumbMarginTop;    if (e.getY() >= top && e.getY() <= bottom && e.getX() >= (mOffsetLow - mThumbWidth / 2) && e.getX() <= mOffsetLow + mThumbWidth / 2) {      return CLICK_ON_LOW;    } else if (e.getY() >= top && e.getY() <= bottom && e.getX() >= (mOffsetHigh - mThumbWidth / 2) && e.getX() <= (mOffsetHigh + mThumbWidth / 2)) {      return CLICK_ON_HIGH;    } else if (e.getY() >= top      && e.getY() <= bottom      && ((e.getX() >= 0 && e.getX() < (mOffsetLow - mThumbWidth / 2)) || ((e.getX() > (mOffsetLow + mThumbWidth / 2))      && e.getX() <= ((double) mOffsetHigh + mOffsetLow) / 2))) {      return CLICK_IN_LOW_AREA;    } else if (e.getY() >= top && e.getY() <= bottom && (((e.getX() > ((double) mOffsetHigh + mOffsetLow) / 2) && e.getX() < (mOffsetHigh - mThumbWidth / 2)) || (e.getX() > (mOffsetHigh + mThumbWidth / 2) && e.getX() <= mScollBarWidth))) {      return CLICK_IN_HIGH_AREA;    } else if (!(e.getX() >= 0 && e.getX() <= mScollBarWidth && e.getY() >= top && e.getY() <= bottom)) {      return CLICK_OUT_AREA;    } else {      return CLICK_INVAILD;    }  }  /**   * 設(shè)置前滑塊位置   * @param progressLow   */  public void setProgressLow(double progressLow) {    this.defaultScreenLow = progressLow;    mOffsetLow = formatInt(progressLow / 100 * (mDistance)) + mThumbWidth / 2;    invalidate();  }  /**   * 設(shè)置后滑塊位置   * @param progressHigh   */  public void setProgressHigh(double progressHigh) {    this.defaultScreenHigh = progressHigh;    mOffsetHigh = formatInt(progressHigh / 100 * (mDistance)) + mThumbWidth / 2;    invalidate();  }  /**   * 設(shè)置滑動(dòng)監(jiān)聽(tīng)   * @param mListener   */  public void setOnSeekBarChangeListener(OnSeekBarChangeListener mListener) {    this.mBarChangeListener = mListener;  }  /**   * 滑動(dòng)監(jiān)聽(tīng),改變輸入框的值   */  public interface OnSeekBarChangeListener {    //滑動(dòng)時(shí)    public void onProgressChanged(SeekRangeBar seekBar, double progressLow, double progressHigh);  }  /**   * 設(shè)置滑動(dòng)結(jié)果為整數(shù)   */  private int formatInt(double value) {    BigDecimal bd = new BigDecimal(value);    BigDecimal bd1 = bd.setScale(0, BigDecimal.ROUND_HALF_UP);    return bd1.intValue();  }}

然后就可以在程序中使用了。

布局中

<util.SeekRangeBar  android:id="@+id/doubleSeekbar"  android:layout_width="match_parent"  android:layout_height="wrap_content"  android:layout_centerVertical="true"/>

調(diào)用

private SeekRangeBar doubleSeekbar;//雙向進(jìn)度條doubleSeekbar = (SeekRangeBar) findViewById(R.id.doubleSeekbar);//監(jiān)聽(tīng)進(jìn)度范圍變化doubleSeekbar.setOnSeekBarChangeListener(new SeekRangeBar.OnSeekBarChangeListener() {  @Override  public void onProgressChanged(SeekRangeBar seekBar, double progressLow, double progressHigh) {    Log.d("LOGCAT","低:" + progressLow + "高:" + progressHigh);  }});

相關(guān)GitHub項(xiàng)目地址:https://github.com/codeqian/android-class-lib

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持VEVB武林網(wǎng)。


注:相關(guān)教程知識(shí)閱讀請(qǐng)移步到Android開(kāi)發(fā)頻道。
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 牟定县| 贺兰县| 静宁县| 思南县| 红安县| 含山县| 西乌珠穆沁旗| 莫力| 奉新县| 玛沁县| 马公市| 宜都市| 阿勒泰市| 武夷山市| 婺源县| 大同县| 小金县| 福海县| 宜川县| 平顶山市| 边坝县| 沭阳县| 聂拉木县| 肥东县| 洪雅县| 寿阳县| 会理县| 福建省| 凤台县| 大名县| 桦川县| 临海市| 正定县| 德令哈市| 永胜县| 奉新县| 龙岩市| 临泽县| 时尚| 定西市| 贵德县|