android學(xué)習(xí)筆記之View的滑動
前言
其實不管是哪種滑動方式,基本思想都是類似的:當(dāng)點擊事件傳遞到View時,系統(tǒng)記下觸摸點的坐標(biāo),手指移動的時候,系統(tǒng)記下移動后的坐標(biāo),并計算出偏移量,并通過偏移量來修改View的坐標(biāo)。
下面我們來講下幾種滑動方法:
1.layout方法
大家知道,繪制View的時候會調(diào)用onlayout方法來設(shè)置要顯示的位置。因此我們也可以通過修改view的left,top,right,bottom這4個屬性來控制view的坐標(biāo)。接下來我們來自定義一個View,通過layout方法來實現(xiàn)滑動:
package com.example.myapplication.views
import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
class CustomView @JvmOverloads constructor(
context: Context,
attrs:AttributeSet? = null,
defStyleAttr:Int= 0
) :View(
context,attrs,defStyleAttr){
private var lastX:Int = 0
private var lastY:Int = 0
override fun onTouchEvent(event: MotionEvent): Boolean {
//獲取手指觸摸點的橫坐標(biāo)和縱坐標(biāo)
val x = event.x.toInt()
val y = event.y.toInt()
when(event.action) {
MotionEvent.ACTION_DOWN -> {
lastX = x
lastY = y
}
MotionEvent.ACTION_MOVE -> {
//計算移動距離
val offsetX = x -lastX
val offsetY = y -lastY
//調(diào)用layout方法來重新放置他的位置
layout(left+offsetX,top+offsetY,right + offsetX, bottom + offsetY)
}
}
return true
}
}然后我們把他放到XML里去使用:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.example.myapplication.views.CustomView
android:id="@+id/view_my"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_gravity="center_horizontal"
android:background="@mipmap/cai"/>
</LinearLayout>看下效果:

這個移動的效果實現(xiàn)。
2.接下來,我們看看offsetLeftAndRight()與offsetTopAndBottom()方法
這兩種方法和layout方法差不多,我們稍加修改就可以。我們替換下ACTION_MOVE中的代碼塊:
MotionEvent.ACTION_MOVE -> {
//計算移動距離
val offsetX = x -lastX
val offsetY = y -lastY
//對left和right進(jìn)行偏移
offsetLeftAndRight(offsetX)
//對top和bottom進(jìn)行偏移
offsetTopAndBottom(offsetY)
// //調(diào)用layout方法來重新放置他的位置
// layout(left+offsetX,top+offsetY,right + offsetX, bottom + offsetY)
}仍然能夠?qū)崿F(xiàn)。
3.第三個方法:LayoutParams(改變布局參數(shù))
LayoutParams主要保存了一個View的布局參數(shù),因此我們可以通過LayoutParams來改變View的布局參數(shù)。從而達(dá)到改變View位置的效果。我們同樣替換下ACTION_MOVE中的代碼塊:
MotionEvent.ACTION_MOVE -> {
//計算移動距離
val offsetX = x -lastX
val offsetY = y -lastY
val layoutParams = layoutParams as LinearLayout.LayoutParams
layoutParams.leftMargin = left + offsetX
layoutParams.topMargin = top + offsetY
setLayoutParams(layoutParams)
// //對left和right進(jìn)行偏移
// offsetLeftAndRight(offsetX)
// //對top和bottom進(jìn)行偏移
// offsetTopAndBottom(offsetY)
// //調(diào)用layout方法來重新放置他的位置
// layout(left+offsetX,top+offsetY,right + offsetX, bottom + offsetY)
}
}不過經(jīng)過我實驗,這個有挺大的偏差,總是靠右邊。什么原因?
4.接下來,看看使用第四種方法,使用動畫來滑動。
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true">
<translate android:fromXDelta="0"
android:toXDelta="300"
/>
</set>使用代碼調(diào)用:
findViewById<View>(R.id.view_my).animation = AnimationUtils.loadAnimation(this,R.anim.translate)
需要注意的是,view動畫,并不能改變view的位置參數(shù)。所以我們點擊Button并不會觸發(fā),因為他的負(fù)控件要先判斷點擊事件是否在子view的位置參數(shù)范圍內(nèi)才會分發(fā)給他,當(dāng)我們點擊原來的位置的時候,才會響應(yīng)。如果我們想讓他在移動后的位置響應(yīng),也就是說更改view的位置參數(shù),那么可以使用屬性動畫。
val customView = findViewById<View>(R.id.view_my)
findViewById<Button>(R.id.btn_move).setOnClickListener {
ObjectAnimator.ofFloat(customView,"translationX",0f,300f).setDuration(1000).start()
}5.接下來我們看看第五種方法,scrollTo與ScrollBy
scrollTo(x,y)表示移動到一個具體的坐標(biāo)點,而scrollBy(dx,dy)表示移動的增量為dx,dy,其實我們看源碼就知道scorllBy最終也是計算出最終坐標(biāo),最終調(diào)用scrollTo的。我們可以看下源碼:
public void scrollBy(int x, int y) {
scrollTo(mScrollX + x, mScrollY + y);
}需要注意的是,scrollTo和ScrollBy是移動的內(nèi)容。我們?nèi)绻O(shè)置了Bacgroud會發(fā)現(xiàn)看不出效果。可以改下:
<com.example.myapplication.views.CustomView
android:id="@+id/view_my"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_gravity="center_horizontal"
android:foreground="@mipmap/cai"/> findViewById<Button>(R.id.btn_move).setOnClickListener {
customView.scrollBy(50,100)
// ObjectAnimator.ofFloat(customView,"translationX",0f,300f).setDuration(1000).start()
}使用foreground。接著看下效果:

最開始是這樣的,然后我們點擊下按鈕,變成了這樣:

是不是發(fā)現(xiàn)了神奇的現(xiàn)象。再點擊一次:

好家伙,快看不到了。什么原因呢?這里有兩個奇怪的現(xiàn)象,第一個是他似乎移動的方向是相反的,第二個是是越來越小。準(zhǔn)確說,是好像并不是縮小,而是只能看到局部。
這是因為參照物的不同導(dǎo)致的。假設(shè),我們把手機屏幕比喻為放大鏡。下面的內(nèi)容當(dāng)作報紙。我們調(diào)用這個方法,實際是使放大鏡相對于這個view,往下移動了,放大鏡看不到的地方不并是不存在了。所以他才看起來像是往左上移動了。然后,因為我們是內(nèi)容在移動,所以View本身并沒有移動,所以他的前景色就看不到了。
我們?nèi)绻M茏龅诫S手指移動,可以在move方法里這樣修改:
MotionEvent.ACTION_MOVE -> {
//計算移動距離
val offsetX = x -lastX
val offsetY = y -lastY
val parentView = parent as View
parentView.scrollBy(-offsetX,-offsetY)
}這里,取相反的值,崗剛說了,是因為參考物,會導(dǎo)致視覺相反。而要取他的parent,是因為這個view就屬于他的parent的內(nèi)容。所以,他就可以進(jìn)行相關(guān)的動作。
6.來看第六種方法Scroller
我們在使用scrollTo/scrollBy方法進(jìn)行滑動的時候,這個過程是瞬間就完成的。所以體驗就不是太好。我們可以使用scroller來實現(xiàn)有過度效果的滑動。但是scroller本身是不能實現(xiàn)View的滑動,它需要與View的computeScroller 方法配合才能實現(xiàn)彈性滑動效果。來看代碼實現(xiàn):
首先,定義個成員變量:
private val mScroller = Scroller(context)
接下來,我們重寫computeScroll方法,系統(tǒng)會繪制View的時候,在draw方法里調(diào)用該方法。
我們先在CustomView里定義個方法:
fun smoothScrollTo(destX:Int, destY:Int){
val scrollX = scrollX
val delta = destX - scrollX
mScroller.startScroll(scrollX,0,delta,2,2000)
invalidate()
}這個方法是提供給外部調(diào)用的,參數(shù)是想偏移的X和Y。
scrollX是目前已經(jīng)滑動值,拿目的要偏移的減去已經(jīng)滑動的,就是還剩下的。調(diào)用scroller.startScroll()方法。設(shè)置一個duration。我們調(diào)用invalidate()就開始重繪。這個時候就會調(diào)用view的computeScroller方法。這里面我們調(diào)用父空間viewGroup的scroollTo方法,來獲取當(dāng)前的一小段滑動值,然后行成小的滑動。接著調(diào)用invalidate()方法不斷的重繪。
override fun computeScroll() {
super.computeScroll()
if (mScroller.computeScrollOffset()) {
(parent as View).scrollTo(mScroller.currX,mScroller.currY)
invalidate()
}
}最后,我們在activity里調(diào)用:
customView.smoothScrollTo(-400,0)
向右邊平移400。
總結(jié)
到此這篇關(guān)于android學(xué)習(xí)筆記之View的滑動的文章就介紹到這了,更多相關(guān)android View的滑動內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android開發(fā)實現(xiàn)圖片大小與質(zhì)量壓縮及保存
這篇文章主要為大家介紹了Android開發(fā)實現(xiàn)圖片大小與質(zhì)量壓縮及保存的方法,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-04-04
詳解Android短信的發(fā)送和廣播接收實現(xiàn)短信的監(jiān)聽
本篇文章主要介紹了Android短信的發(fā)送和廣播接收實現(xiàn)短信的監(jiān)聽,可以實現(xiàn)短信收發(fā),有興趣的可以了解一下。2016-11-11
教你3分鐘了解Android 簡易時間軸的實現(xiàn)方法
本篇文章主要介紹了教你3分鐘了解Android 簡易時間軸的實現(xiàn)方法,具有一定的參考價值,有興趣的可以了解一下2017-07-07
Android ListView position詳解及實例代碼
這篇文章主要介紹了Android ListView position的相關(guān)資料,在開發(fā)Android 應(yīng)用的時候你真的用對了嗎?這里給大家徹底解釋下,需要的朋友可以參考下2016-10-10
Android利用ScaleTransition實現(xiàn)吹氣球動畫
這篇文章主要為大家介紹了如何將利用ScaleTransition實現(xiàn)一個吹氣球的動畫,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起了解一下2022-04-04

