麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 開發 > 綜合 > 正文

Kotlin自定義View系列教程之標尺控件(選擇身高、體重等)的實現

2024-07-21 23:03:48
字體:
來源:轉載
供稿:網友

前言

本篇文章講的是Kotlin 自定義view之實現標尺控件Ruler,以選擇身高、體重等。開發中,當我們需要獲取用戶的身高和體重等信息時,如果直接讓他們輸入,顯然體驗不夠好。像類似于唯品會、好輕等APP都是使用了類似于刻度尺的控件讓用戶滑動選擇身高體重,覺得很棒。網上已有人使用Java語言實現這樣的功能,但不影響我對其的學習。和往常一樣,主要還是想總結一下自定義view之實現標尺控件的開發過程以及一些需要注意的地方。

按照慣例,我們先來看看效果圖 

Kotlin,View,標尺控件

一、先總結下自定義View的步驟: 

1、自定義View的屬性 

2、在View的構造方法中獲得我們自定義的屬性 

3、重寫onMesure 

4、重寫onDraw 

其中onMesure方法不一定要重寫,但大部分情況下還是需要重寫的

二、View 的幾個構造函數 

1、constructor(mContext: Context)

—>java代碼直接new一個RulerView實例的時候,會調用這個只有一個參數的構造函數; 

2、constructor(mContext: Context, attrs: AttributeSet)

—>在默認的XML布局文件中創建的時候調用這個有兩個參數的構造函數。AttributeSet類型的參數負責把XML布局文件中所自定義的屬性通過AttributeSet帶入到View內; 

3、constructor(mContext: Context, attrs: AttributeSet,defStyleAttr:Int)

—>構造函數中第三個參數是默認的Style,這里的默認的Style是指它在當前Application或者Activity所用的Theme中的默認Style,且只有在明確調用的時候才會調用 

4、constructor(mContext: Context, attrs: AttributeSet,defStyleAttr:Int,defStyleRes:Int)

—>該構造函數是在API21的時候才添加上的

三、下面我們就開始來看看代碼啦 

1、自定義View的屬性,首先在res/values/ 下建立一個attrs.xml , 在里面定義我們的需要用到的屬性以及聲明相對應屬性的取值類型

<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView  android:id="@+id/tv_weight_tip"  android:layout_width="wrap_content"  android:layout_height="wrap_content"  android:text="體重"  android:textColor="@android:color/black"  android:textSize="14dp"  app:layout_constraintBottom_toBottomOf="parent"  app:layout_constraintLeft_toLeftOf="parent"  app:layout_constraintRight_toRightOf="parent"  app:layout_constraintTop_toTopOf="parent"  app:layout_constraintVertical_bias="0.132" /> <RelativeLayout  android:id="@+id/rl_weight_ruler"  android:layout_width="match_parent"  android:layout_height="wrap_content"  app:layout_constraintTop_toBottomOf="@+id/tv_weight_tip"  app:layout_constraintLeft_toLeftOf="parent"  app:layout_constraintRight_toRightOf="parent">  <per.lijuan.rulerdome.RulerView   android:id="@+id/ruler_weight"   android:layout_width="match_parent"   android:layout_height="58dp"   android:layout_marginTop="24dp"   app:alphaEnable="true"   app:lineColor="@android:color/darker_gray"   app:lineMaxHeight="40dp"   app:lineMidHeight="30dp"   app:lineMinHeight="20dp"   app:lineSpaceWidth="10dp"   app:lineWidth="2.5dp"   app:textColor="@android:color/black"   app:minValue="20"   app:maxValue="200"   app:perValue="0.1"   app:selectorValue="55"/>  <ImageView   android:layout_width="14dp"   android:layout_height="46dp"   android:layout_centerHorizontal="true"   android:layout_marginTop="6dp"   android:scaleType="fitXY"   android:src="@mipmap/ic_arrow"/> </RelativeLayout> <TextView  android:id="@+id/tv_weight"  android:layout_width="wrap_content"  android:layout_height="wrap_content"  android:layout_marginTop="11dp"  android:maxHeight="30sp"  android:textColor="@color/colorPrimary"  android:textSize="24sp"  app:layout_constraintTop_toBottomOf="@+id/rl_weight_ruler"  app:layout_constraintEnd_toEndOf="parent"  app:layout_constraintStart_toStartOf="parent"/></android.support.constraint.ConstraintLayout>

一定要引入xmlns:app=”http://schemas.android.com/apk/res-auto” ,Android Studio中我們可以使用res-atuo命名空間,就不用在添加自定義View全類名。

3、在View的構造方法中,獲得我們的自定義的樣式

private var mMinVelocity:Int = 0 private var mScroller: Scroller? = null//Scroller是一個專門用于處理滾動效果的工具類 用mScroller記錄/計算View滾動的位置,再重寫View的computeScroll(),完成實際的滾動 private var mVelocityTracker: VelocityTracker?=null//主要用跟蹤觸摸屏事件(flinging事件和其他gestures手勢事件)的速率。 private var mWidth:Int = 0 private var mHeight:Int = 0 private var mSelectorValue=50f  // 未選擇時 默認的值 滑動后表示當前中間指針正在指著的值 private var mMaxValue=200f   // 最大數值 private var mMinValue=100f   //最小的數值 private var mPerValue=1f   //最小單位(如 1:表示每2條刻度差為1;0.1:表示每2條刻度差為0.1 private var mLineSpaceWidth = 5f // 尺子刻度2條線之間的距離 private var mLineWidth = 4f   // 尺子刻度的寬度 private var mLineMaxHeight = 420f // 尺子刻度分為3中不同的高度。 mLineMaxHeight表示最長的那根(也就是 10的倍數時的高度) private var mLineMidHeight = 30f // mLineMidHeight 表示中間的高度(也就是 5 15 25 等時的高度) private var mLineMinHeight = 17f // mLineMinHeight 表示最短的那個高度(也就是 1 2 3 4 等時的高度) private var mTextMarginTop = 10f private var mTextSize = 30f   //尺子刻度下方數字的大小 private var mAlphaEnable=false  // 尺子 最左邊 最后邊是否需要透明 `(透明效果更好點) private var mTextHeight = 0.toFloat()//尺子刻度下方數字的高度 private var mTextPaint: Paint?=null // 尺子刻度下方數字(也就是每隔10個出現的數值)畫筆 private var mLinePaint: Paint?=null // 尺子刻度線的畫筆 private var mTotalLine:Int = 0  //共有多少條 刻度 private var mMaxOffset:Int = 0  //所有刻度 共有多長 private var mOffset:Float = 0.toFloat()// 默認狀態下,mSelectorValue所在的位置 位于尺子總刻度的位置 private var mLastX:Int = 0 private var mMove: Int = 0 private lateinit var mListener: OnValueChangeListener// 滑動后數值回調 private var mLineColor:Int= Color.GRAY //刻度的顏色 private var mTextColor:Int= Color.BLACK//文字的顏色 constructor(mContext: Context) : super(mContext,null) constructor(mContext: Context, attrs: AttributeSet) : super(mContext, attrs,0) constructor(mContext: Context, attrs: AttributeSet,defStyleAttr:Int) : super(mContext, attrs,defStyleAttr) {  init(mContext, attrs) } fun init(context: Context, attrs: AttributeSet){  Log.d(TAG, "init")  mScroller= Scroller(context)  this.mLineSpaceWidth=myfloat(25.0f)  this.mLineWidth=myfloat(2.0f)  this.mLineMaxHeight=myfloat(100.0f)  this.mLineMidHeight=myfloat(60.0f)  this.mLineMinHeight=myfloat(40.0f)  this.mTextHeight=myfloat(40.0f)  val typedArray: TypedArray =context.obtainStyledAttributes(attrs,    R.styleable.RulerView)  mAlphaEnable= typedArray.getBoolean(R.styleable.RulerView_alphaEnable, mAlphaEnable)  mLineSpaceWidth = typedArray.getDimension(R.styleable.RulerView_lineSpaceWidth, mLineSpaceWidth)  mLineWidth = typedArray.getDimension(R.styleable.RulerView_lineWidth, mLineWidth)  mLineMaxHeight = typedArray.getDimension(R.styleable.RulerView_lineMaxHeight, mLineMaxHeight)  mLineMidHeight = typedArray.getDimension(R.styleable.RulerView_lineMidHeight, mLineMidHeight)  mLineMinHeight = typedArray.getDimension(R.styleable.RulerView_lineMinHeight, mLineMinHeight)  mLineColor = typedArray.getColor(R.styleable.RulerView_lineColor, mLineColor)  mTextSize = typedArray.getDimension(R.styleable.RulerView_textSize, mTextSize)  mTextColor = typedArray.getColor(R.styleable.RulerView_textColor, mTextColor)  mTextMarginTop = typedArray.getDimension(R.styleable.RulerView_textMarginTop, mTextMarginTop)  mSelectorValue = typedArray.getFloat(R.styleable.RulerView_selectorValue, 0.0f)  mMinValue = typedArray.getFloat(R.styleable.RulerView_minValue, 0.0f)  mMaxValue = typedArray.getFloat(R.styleable.RulerView_maxValue, 100.0f)  mPerValue = typedArray.getFloat(R.styleable.RulerView_perValue, 0.1f)  mMinVelocity= ViewConfiguration.get(getContext()).scaledMinimumFlingVelocity  mTextPaint = Paint(Paint.ANTI_ALIAS_FLAG)  mTextPaint!!.textSize = mTextSize  mTextPaint!!.color = mTextColor  mTextHeight = getFontHeight(mTextPaint!!)  mLinePaint = Paint(Paint.ANTI_ALIAS_FLAG)  mLinePaint!!.strokeWidth = mLineWidth  mLinePaint!!.color = mLineColor }

我們重寫了3個構造方法,在上面的構造方法中說過默認的布局文件調用的是兩個參數的構造方法,所以記得讓所有的構造方法調用三個參數的構造方法,然后在三個參數的構造方法中獲得自定義屬性。 
一開始一個參數的構造方法和兩個參數的構造方法是這樣的:

constructor(mContext: Context) : super (mContext) constructor(mContext: Context, attrs: AttributeSet?) : super(mContext, attrs)

有一點要注意的是super應該改成this,然后讓一個參數的構造方法引用兩個參數的構造方法,兩個參數的構造方法引用三個參數的構造方法,代碼如下:

constructor(mContext: Context) : this(mContext,null) constructor(mContext: Context, attrs: AttributeSet?) : this(mContext, attrs!!,0) constructor(mContext: Context, attrs: AttributeSet,defStyleAttr:Int) : super(mContext, attrs,defStyleAttr) {  init(mContext, attrs) }

4、重寫onDraw方法

override fun onDraw(canvas: Canvas) {  super.onDraw(canvas)  var left: Float  var height: Float  var value: String  var alpha = 0  var scale: Float  val srcPointX = mWidth / 2  for (i in 0 until mTotalLine) {   left = srcPointX.toFloat() + mOffset + i * mLineSpaceWidth   if (left < 0 || left > mWidth) {    continue //先畫默認值在正中間,左右各一半的view。多余部分暫時不畫(也就是從默認值在中間,畫旁邊左右的刻度線)   }   if (i % 10 == 0) {    height = mLineMaxHeight   } else if (i % 5 == 0) {    height = mLineMidHeight   } else {    height = mLineMinHeight   }   if (mAlphaEnable) {    scale = 1 - Math.abs(left - srcPointX) / srcPointX    alpha = (255f * scale * scale).toInt()    mLinePaint!!.setAlpha(alpha)   }   canvas.drawLine(left, 0f, left, height, mLinePaint)   if (i % 10 == 0) {    value = (mMinValue + i * mPerValue / 10).toInt().toString()    if (mAlphaEnable) {     mTextPaint!!.alpha = alpha    }    canvas.drawText(value, left - mTextPaint!!.measureText(value) / 2,      height + mTextMarginTop + mTextHeight, mTextPaint) // 在為整數時,畫 數值   }  } }

View的繪制流程是從ViewRoot的performTravarsals方法開始的,經過measure、layout和draw三個過程才能最終將一個View繪制出來,其中:

測量——onMeasure():用來測量View的寬和高來決定View的大小 
布局——onLayout():用來確定View在父容器ViewGroup中的放置位置 
繪制——onDraw():負責將View繪制在屏幕上

5、重寫onTouchEvent方法 

onTouchEvent()是View自帶的接口,Android系統提供了默認的實現,用于處理觸摸事件。當我們對標尺控件向左向右滑動時,此方法就會被調用。

override fun onTouchEvent(event: MotionEvent): Boolean {    Log.d(TAG, "onTouchEvent")    val action = event.action    val xPosition = event.x.toInt()    if (mVelocityTracker == null) {      mVelocityTracker = VelocityTracker.obtain()    }    mVelocityTracker!!.addMovement(event)    when (action) {      MotionEvent.ACTION_DOWN -> {        mScroller!!.forceFinished(true)        mLastX = xPosition        mMove = 0      }      MotionEvent.ACTION_MOVE -> {        mMove = mLastX - xPosition        changeMoveAndValue()      }      MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {        countMoveEnd()        countVelocityTracker()        return false      }      else -> {      }    }    mLastX = xPosition    return true  }

現在我把完整的代碼貼出來

package per.lijuan.rulerdomeimport android.content.Contextimport android.content.res.TypedArrayimport android.graphics.Canvasimport android.graphics.Colorimport android.graphics.Paintimport android.util.AttributeSetimport android.util.Logimport android.view.MotionEventimport android.view.VelocityTrackerimport android.view.Viewimport android.view.ViewConfigurationimport android.widget.Scroller/** * Created by juan on 2018/5/11. */class RulerView: View {  private val TAG : String = "RulerView"  private var mMinVelocity:Int = 0  private var mScroller: Scroller? = null//Scroller是一個專門用于處理滾動效果的工具類  用mScroller記錄/計算View滾動的位置,再重寫View的computeScroll(),完成實際的滾動  private var mVelocityTracker: VelocityTracker?=null//主要用跟蹤觸摸屏事件(flinging事件和其他gestures手勢事件)的速率。  private var mWidth:Int = 0  private var mHeight:Int = 0  private var mSelectorValue=50f   // 未選擇時 默認的值 滑動后表示當前中間指針正在指著的值  private var mMaxValue=200f     // 最大數值  private var mMinValue=100f     //最小的數值  private var mPerValue=1f      //最小單位(如 1:表示每2條刻度差為1;0.1:表示每2條刻度差為0.1  private var mLineSpaceWidth = 5f  // 尺子刻度2條線之間的距離  private var mLineWidth = 4f     // 尺子刻度的寬度  private var mLineMaxHeight = 420f  // 尺子刻度分為3中不同的高度。 mLineMaxHeight表示最長的那根(也就是 10的倍數時的高度)  private var mLineMidHeight = 30f  // mLineMidHeight 表示中間的高度(也就是 5 15 25 等時的高度)  private var mLineMinHeight = 17f  // mLineMinHeight 表示最短的那個高度(也就是 1 2 3 4 等時的高度)  private var mTextMarginTop = 10f  private var mTextSize = 30f     //尺子刻度下方數字的大小  private var mAlphaEnable=false    // 尺子 最左邊 最后邊是否需要透明 `(透明效果更好點)  private var mTextHeight = 0.toFloat()//尺子刻度下方數字的高度  private var mTextPaint: Paint?=null  // 尺子刻度下方數字(也就是每隔10個出現的數值)畫筆  private var mLinePaint: Paint?=null  // 尺子刻度線的畫筆  private var mTotalLine:Int = 0    //共有多少條 刻度  private var mMaxOffset:Int = 0    //所有刻度 共有多長  private var mOffset:Float = 0.toFloat()// 默認狀態下,mSelectorValue所在的位置 位于尺子總刻度的位置  private var mLastX:Int = 0  private var mMove: Int = 0  private lateinit var mListener: OnValueChangeListener// 滑動后數值回調  private var mLineColor:Int= Color.GRAY //刻度的顏色  private var mTextColor:Int= Color.BLACK//文字的顏色  constructor(mContext: Context) : this(mContext,null)  constructor(mContext: Context, attrs: AttributeSet?) : this(mContext, attrs!!,0)  constructor(mContext: Context, attrs: AttributeSet,defStyleAttr:Int) : super(mContext, attrs,defStyleAttr) {    init(mContext, attrs)  }  fun init(context: Context, attrs: AttributeSet){    Log.d(TAG, "init")    mScroller= Scroller(context)    this.mLineSpaceWidth=myfloat(25.0f)    this.mLineWidth=myfloat(2.0f)    this.mLineMaxHeight=myfloat(100.0f)    this.mLineMidHeight=myfloat(60.0f)    this.mLineMinHeight=myfloat(40.0f)    this.mTextHeight=myfloat(40.0f)    val typedArray: TypedArray =context.obtainStyledAttributes(attrs,        R.styleable.RulerView)    mAlphaEnable= typedArray.getBoolean(R.styleable.RulerView_alphaEnable, mAlphaEnable)    mLineSpaceWidth = typedArray.getDimension(R.styleable.RulerView_lineSpaceWidth, mLineSpaceWidth)    mLineWidth = typedArray.getDimension(R.styleable.RulerView_lineWidth, mLineWidth)    mLineMaxHeight = typedArray.getDimension(R.styleable.RulerView_lineMaxHeight, mLineMaxHeight)    mLineMidHeight = typedArray.getDimension(R.styleable.RulerView_lineMidHeight, mLineMidHeight)    mLineMinHeight = typedArray.getDimension(R.styleable.RulerView_lineMinHeight, mLineMinHeight)    mLineColor = typedArray.getColor(R.styleable.RulerView_lineColor, mLineColor)    mTextSize = typedArray.getDimension(R.styleable.RulerView_textSize, mTextSize)    mTextColor = typedArray.getColor(R.styleable.RulerView_textColor, mTextColor)    mTextMarginTop = typedArray.getDimension(R.styleable.RulerView_textMarginTop, mTextMarginTop)    mSelectorValue = typedArray.getFloat(R.styleable.RulerView_selectorValue, 0.0f)    mMinValue = typedArray.getFloat(R.styleable.RulerView_minValue, 0.0f)    mMaxValue = typedArray.getFloat(R.styleable.RulerView_maxValue, 100.0f)    mPerValue = typedArray.getFloat(R.styleable.RulerView_perValue, 0.1f)    mMinVelocity= ViewConfiguration.get(getContext()).scaledMinimumFlingVelocity    mTextPaint = Paint(Paint.ANTI_ALIAS_FLAG)    mTextPaint!!.textSize = mTextSize    mTextPaint!!.color = mTextColor    mTextHeight = getFontHeight(mTextPaint!!)    mLinePaint = Paint(Paint.ANTI_ALIAS_FLAG)    mLinePaint!!.strokeWidth = mLineWidth    mLinePaint!!.color = mLineColor  }  private fun myfloat(paramFloat:Float):Float{    return 0.5f+paramFloat*1.0f  }  private fun getFontHeight(paint: Paint):Float{    val fm = paint.fontMetrics    return fm.descent - fm.ascent  }  /**   * 設置默認的參數   * @param selectorValue 未選擇時 默認的值 滑動后表示當前中間指針正在指著的值   * @param minValue  最大數值   * @param maxValue  最小的數值   * @param per  最小單位(如1:表示每2條刻度差為1;0.1:表示每2條刻度差為0.1;其中身高mPerValue為1,體重mPerValue 為0.1)   */  fun setValue(selectorValue: Float, minValue: Float, maxValue: Float, per: Float) {    this.mSelectorValue = selectorValue    this.mMaxValue = maxValue    this.mMinValue = minValue    this.mPerValue = per * 10.0f    this.mTotalLine = ((mMaxValue * 10 - mMinValue * 10) / mPerValue).toInt() + 1    mMaxOffset = (-(mTotalLine - 1) * mLineSpaceWidth).toInt()    mOffset = (mMinValue - mSelectorValue) / mPerValue * mLineSpaceWidth * 10f    Log.d(TAG, "mOffset:" + mOffset + ",mMaxOffset:" + mMaxOffset        + ",mTotalLine:" + mTotalLine)    invalidate()    visibility = View.VISIBLE  }  fun setOnValueChangeListener(listener: OnValueChangeListener) {    mListener = listener  }  override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {    super.onSizeChanged(w, h, oldw, oldh)    if (w > 0 && h > 0) {      mWidth = w      mHeight = h    }  }  override fun onDraw(canvas: Canvas) {    super.onDraw(canvas)    var left: Float    var height: Float    var value: String    var alpha = 0    var scale: Float    val srcPointX = mWidth / 2    for (i in 0 until mTotalLine) {      left = srcPointX.toFloat() + mOffset + i * mLineSpaceWidth      if (left < 0 || left > mWidth) {        continue //先畫默認值在正中間,左右各一半的view。多余部分暫時不畫(也就是從默認值在中間,畫旁邊左右的刻度線)      }      if (i % 10 == 0) {        height = mLineMaxHeight      } else if (i % 5 == 0) {        height = mLineMidHeight      } else {        height = mLineMinHeight      }      if (mAlphaEnable) {        scale = 1 - Math.abs(left - srcPointX) / srcPointX        alpha = (255f * scale * scale).toInt()        mLinePaint!!.setAlpha(alpha)      }      canvas.drawLine(left, 0f, left, height, mLinePaint)      if (i % 10 == 0) {        value = (mMinValue + i * mPerValue / 10).toInt().toString()        if (mAlphaEnable) {          mTextPaint!!.alpha = alpha        }        canvas.drawText(value, left - mTextPaint!!.measureText(value) / 2,            height + mTextMarginTop + mTextHeight, mTextPaint)  // 在為整數時,畫 數值      }    }  }  override fun onTouchEvent(event: MotionEvent): Boolean {    Log.d(TAG, "onTouchEvent")    val action = event.action    val xPosition = event.x.toInt()    if (mVelocityTracker == null) {      mVelocityTracker = VelocityTracker.obtain()    }    mVelocityTracker!!.addMovement(event)    when (action) {      MotionEvent.ACTION_DOWN -> {        mScroller!!.forceFinished(true)        mLastX = xPosition        mMove = 0      }      MotionEvent.ACTION_MOVE -> {        mMove = mLastX - xPosition        changeMoveAndValue()      }      MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {        countMoveEnd()        countVelocityTracker()        return false      }      else -> {      }    }    mLastX = xPosition    return true  }  private fun countVelocityTracker() {    Log.d(TAG, "countVelocityTracker")    mVelocityTracker!!.computeCurrentVelocity(1000) //初始化速率的單位    val xVelocity = mVelocityTracker!!.xVelocity //當前的速度    if (Math.abs(xVelocity) > mMinVelocity) {      mScroller!!.fling(0, 0, xVelocity.toInt(), 0, Integer.MIN_VALUE, Integer.MAX_VALUE, 0, 0)    }  }  /**   * 滑動結束后,若是指針在2條刻度之間時,改變mOffset 讓指針正好在刻度上。   */  private fun countMoveEnd() {    mOffset -= mMove.toFloat()    if (mOffset <= mMaxOffset) {      mOffset = mMaxOffset.toFloat()    } else if (mOffset >= 0) {      mOffset = 0f    }    mLastX = 0    mMove = 0    mSelectorValue = mMinValue + Math.round(Math.abs(mOffset) * 1.0f / mLineSpaceWidth) * mPerValue / 10.0f    mOffset = (mMinValue - mSelectorValue) * 10.0f / mPerValue * mLineSpaceWidth    notifyValueChange()    postInvalidate()  }  /**   * 滑動后的操作   */  private fun changeMoveAndValue() {    mOffset -= mMove.toFloat()    if (mOffset <= mMaxOffset) {      mOffset = mMaxOffset.toFloat()      mMove = 0      mScroller!!.forceFinished(true)    } else if (mOffset >= 0) {      mMove = 0      mScroller!!.forceFinished(true)    }    mSelectorValue = mMinValue + Math.round(Math.abs(mOffset) * 1.0f / mLineSpaceWidth) * mPerValue / 10.0f    notifyValueChange()    postInvalidate()  }  private fun notifyValueChange() {    if (null != mListener) {      mListener.onValueChange(mSelectorValue)    }  }  /**   * 滑動后的回調   */  interface OnValueChangeListener{    fun onValueChange(value: Float)  }  override fun computeScroll() {    Log.d(TAG, "computeScroll")    super.computeScroll()    if (mScroller!!.computeScrollOffset()) {//mScroller.computeScrollOffset()返回true表示滑動還沒有結束      if (mScroller!!.currX == mScroller!!.finalX) {        countMoveEnd()      } else {        val xPosition = mScroller!!.currX        mMove = mLastX - xPosition        changeMoveAndValue()        mLastX = xPosition      }    }  }}

在頁面中,我們要給自定義的標尺設置默認的參數:未選擇時默認的值、最大數值、最小的數值以及最小單位

//體重的view    mWeightRuler!!.setOnValueChangeListener(object : RulerView.OnValueChangeListener {      override fun onValueChange(value: Float) {        weight = value        mTvWeight!!.text = weight.toString() + "kg"      }    })    mWeightRuler!!.setValue(55f, 20f, 200f, 0.1f)

參考資料: 

https://github.com/panacena/RuleView

源碼下載

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對VeVb武林網的支持。


注:相關教程知識閱讀請移步到kotlin教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 成年性羞羞视频免费观看 | 成人国产精品一区 | 午夜精品久久久久久中宇 | 免费国产人成网站 | 欧美日韩在线看片 | 黄色毛片免费视频 | 美女黄污视频 | 国产精品中文在线 | 精品中文字幕在线观看 | 免费a级片在线观看 | 午夜视频在线 | 欧美成人福利 | 香蕉视频1024 | 精品一区二区三区毛片 | 99国产精成人午夜视频一区二区 | 国内免费视频成人精品 | 日韩av成人| 色婷婷一区二区三区 | 久久久久国产成人精品亚洲午夜 | 欧美zoofilia杂交videos | 久久久一区二区三区精品 | qyl在线视频精品免费观看 | 国产午夜精品一区二区三区不卡 | 亚洲综合一区在线观看 | 国av在线 | 亚洲九九色 | 欧美日本一区二区 | 亚洲99 | 成人午夜一区二区 | 欧美亚洲国产一区二区三区 | 在线天堂中文在线资源网 | 激情毛片 | 少妇的肉体的满足毛片 | 免费a视频 | 国产精品久久久久久久久久尿 | 一级免费观看 | 激情午夜天 | 19禁国产精品福利视频 | 欧美激情视频一区二区免费 | 欧美一区黄色 | 日韩毛片网站 |