? ? ? ? 1逛绵、通過手勢和相對(duì)坐標(biāo)來完成可隨手指滑動(dòng)的自定義View
????????了解了Android 中的坐標(biāo)系,我們通過獲取View的相對(duì)坐標(biāo)來完成一個(gè)可隨手指進(jìn)行滑動(dòng)的自定義View的創(chuàng)建听系。
? ? ? ? 先創(chuàng)建一個(gè)自定義DrawCanvasView繼承View,實(shí)現(xiàn)構(gòu)造方法 ? ? ? ? ?
class DrawCanvasView : View {
????????constructor(context: Context?) :super(context) {
????????}
? ? ? ? constructor(context: Context?, attrs: AttributeSet?) :super(context, attrs) {
????????}
}
聲明兩個(gè)變量箱亿,lastX跛锌,lastY
var lastX =0F//記錄上次的X坐標(biāo)
var lastY =0F//記錄上一次的Y坐標(biāo)
重寫onTouchEvent方法,定義x届惋,y參數(shù)
override fun onTouchEvent(event: MotionEvent?): Boolean {
????????var x = event!!.x
? ? ? ? var y = event!!.y
? ? ? ?????return true
? ? }
監(jiān)聽MotionEvent手勢動(dòng)作髓帽,當(dāng)觸發(fā)MotionEvent.ACTION_DOWN時(shí),記錄上次的相對(duì)坐標(biāo)的位置脑豹,當(dāng)觸發(fā)MotionEvent.ACTION_MOVE時(shí)郑藏,計(jì)算出x,y軸的偏移量瘩欺,重新設(shè)置View的顯示位置必盖。代碼如下
when (event!!.action) {
????MotionEvent.ACTION_DOWN -> {
????????lastX = x//每次更新上次的x坐標(biāo)
????????lastY = y//每次更新上次的y坐標(biāo)
????}
????MotionEvent.ACTION_MOVE -> {
????????var offsetX = (x -lastX).toInt()//計(jì)算x軸偏移量
????????var offsetY = (y -lastY).toInt()//計(jì)算y軸偏移量
????????layout(left + offsetX, top + offsetY, right + offsetX, bottom + offsetY)//通過layout方法重新設(shè)置View的位置
????}
}
整個(gè)DrawCanvasView的代碼如下
class DrawCanvasView : View {
? ? var lastX =0F//記錄上次的X坐標(biāo)
? ? var lastY =0F//記錄上一次的Y坐標(biāo)
? ? constructor(context: Context?) :super(context) {
????}
????constructor(context: Context?, attrs: AttributeSet?) :super(context, attrs) {
????}
????override fun onTouchEvent(event: MotionEvent?): Boolean {
????????var x = event!!.x
? ? ? ? var y = event!!.y
? ? ? ? when (event!!.action) {
????????????MotionEvent.ACTION_DOWN -> {
????????????????lastX = x
????????????????lastY = y
????????????}
????????????MotionEvent.ACTION_MOVE -> {
????????????????var offsetX = (x -lastX).toInt()
????????????????var offsetY = (y -lastY).toInt()
????????????????layout(left + offsetX, top + offsetY, right + offsetX, bottom + offsetY)
? ? ? ? ? ? }
????????}
????????return true
????}
}
在布局文件中引用該DrawCanvasView
運(yùn)行程序后,可以對(duì)View進(jìn)行拖拽滑動(dòng)的效果俱饿。
? ? ? ? 也可以把MotionEvent.ACTION_MOVE代碼中的layout(left + offsetX, top + offsetY, right + offsetX, bottom + offsetY)換成以下代碼
offsetLeftAndRight(offsetX)
offsetTopAndBottom(offsetY)
也可以達(dá)到手指滑動(dòng)View的效果歌粥。
? ? ? ? 2、通過動(dòng)畫來實(shí)現(xiàn)View的平移拍埠、縮放失驶、旋轉(zhuǎn)或動(dòng)作組合
? ? ? ? 一、anim xml文件實(shí)現(xiàn)動(dòng)畫:
????平移:在res/anim文件夾下創(chuàng)建一個(gè)命名為translate的xml文件枣购,代碼如下
? ? ? ? 給在上面引用的DrawCanvasView設(shè)置一個(gè)id為custom_view
? ? ? ? 在activity中設(shè)置view.setAnimation為AnimationUtils.loadAnimation(this, R.anim.translate)
mDataBinding.customView.animation = AnimationUtils.loadAnimation(this, R.anim.translate)
效果如下
? ? 以同樣的步驟可以實(shí)現(xiàn)View的縮放和旋轉(zhuǎn)等嬉探,這里就不多做贅述和效果圖展示,只把設(shè)置的xml文件截圖一下
旋轉(zhuǎn):
縮放:
再做一次動(dòng)畫組合:
二:屬性動(dòng)畫
ObjectAnimator棉圈、使用屬性動(dòng)畫一樣可以實(shí)現(xiàn)View的平移涩堤、旋轉(zhuǎn)和縮放,平移的代碼
var animator= ObjectAnimator.ofFloat(mDataBinding.customView,"translationX",300f)
animator.duration=1000
animator.start()
實(shí)現(xiàn)旋轉(zhuǎn)和縮放分瘾,把ObjectAnimator.ofFloat方法中的propertyName參數(shù)分別替換為rotation胎围、rotationX、rotationY或者scaleX德召、scaleY等相對(duì)應(yīng)的方法痊远。
ValueAnimator、使用ValueAnimator如下
var valueAnimator=ValueAnimator.ofFloat(0f,100f)
valueAnimator.setTarget(mDataBinding.customView)
valueAnimator.setDuration(2000).start()
valueAnimator.addUpdateListener{
? ? mDataBinding.customView.scaleX=it.animatedValue as Float
}
ValueAnimator并不支持實(shí)現(xiàn)動(dòng)圖氏捞,只能通過監(jiān)聽來獲取到設(shè)置的取值變化碧聪,通過獲取到的這個(gè)取值變化來更新View的狀態(tài),從而實(shí)現(xiàn)動(dòng)畫的效果液茎。
剛才在上面的步驟中逞姿,通過anim.xml來實(shí)現(xiàn)了一次view的多種動(dòng)畫的組合效果,那么通過這個(gè)Java代碼的Animator怎么來實(shí)現(xiàn)呢捆等,用到了這么一個(gè)類AnimatorSet滞造,以下為代碼:
var animator= ObjectAnimator.ofFloat(mDataBinding.customView,"translationX",1.5f)?
var animator2= ObjectAnimator.ofFloat(mDataBinding.customView,"scaleX",1.5f)
var animator3= ObjectAnimator.ofFloat(mDataBinding.customView,"rotation",1.5f)
var set=AnimatorSet()
set.duration=3000
set.play(animator).with(animator2).after(animator3)
set.start()
其中,play()這個(gè)方法很好理解栋烤,就是啟動(dòng)動(dòng)畫谒养,with則是指的同時(shí)執(zhí)行的動(dòng)畫,after則是在這個(gè)動(dòng)畫之后執(zhí)行明郭,相反before則是在這個(gè)動(dòng)畫之前執(zhí)行买窟。
還有一個(gè)類PropertyValuesHolder可以實(shí)現(xiàn)組合動(dòng)畫丰泊,代碼:
var valuesHolder = PropertyValuesHolder.ofFloat("translationX", 1.0f, 1.5f, 1.0f)
var valuesHolder1 = PropertyValuesHolder.ofFloat("scaleX", 1.0f, 1.5f, 1.0f)
var valuesHolder2 = PropertyValuesHolder.ofFloat("rotationX", 0f, 90f, 0f)
var objectAnimator = ObjectAnimator.ofPropertyValuesHolder(
mDataBinding.customView,
? ? valuesHolder,
? ? valuesHolder1,
? ? valuesHolder2
)
objectAnimator.duration =3000
objectAnimator.start()
來看一下效果圖
????????至此,這篇文章就結(jié)束了始绍。主要講了一下比較簡單瞳购、容易理解的View的一些簡單動(dòng)作或者說是簡單動(dòng)畫實(shí)現(xiàn)。有說的不對(duì)或者說的有歧義的地方亏推,還望看到文章的大神們可以指導(dǎo)学赛、指正,謝謝吞杭。