Deslizamento de visualização no android

Na verdade, não importa o tipo de método deslizante, a ideia básica é semelhante: quando o evento click é passado para a View, o sistema registra as coordenadas do ponto de toque e, quando o dedo se move, o sistema registra as coordenadas movidas e calcula o offset, e modifica as coordenadas da View através do offset.

Vamos falar sobre os seguintes métodos deslizantes:

1. método de layout

Como você sabe, ao desenhar uma View, o método onlayout é chamado para definir a posição a ser exibida. Portanto, também podemos controlar as coordenadas da visualização modificando os atributos esquerdo, superior, direito e inferior da visualização. Em seguida, vamos definir uma View e implementar o deslizamento pelo método de layout:

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 {
        //获取手指触摸点的横坐标和纵坐标
        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
                //调用layout方法来重新放置他的位置
                layout(left+offsetX,top+offsetY,right + offsetX, bottom + offsetY)
            }
        }
        return true
    }
}

Em seguida, colocamos em XML para usar:

<?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>

Veja o efeito:

 O efeito desse movimento é alcançado.

2. Em seguida, veremos os métodos offsetLeftAndRight() e offsetTopAndBottom()

Esses dois métodos são semelhantes ao método de layout e podemos modificá-los ligeiramente. Substituímos o bloco de código em ACTION_MOVE:

MotionEvent.ACTION_MOVE -> {
                //计算移动距离
                val offsetX = x -lastX
                val offsetY = y -lastY
                //对left和right进行偏移
                offsetLeftAndRight(offsetX)
                //对top和bottom进行偏移
                offsetTopAndBottom(offsetY)

//                //调用layout方法来重新放置他的位置
//                layout(left+offsetX,top+offsetY,right + offsetX, bottom + offsetY)
            }

ainda pode ser alcançado.

3. O terceiro método: LayoutParams (alterar parâmetros de layout)

LayoutParams salva principalmente os parâmetros de layout de uma View, para que possamos alterar os parâmetros de layout da View através de LayoutParams. Para obter o efeito de alterar a posição do View. Também substituímos o bloco de código em 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进行偏移
//                offsetLeftAndRight(offsetX)
//                //对top和bottom进行偏移
//                offsetTopAndBottom(offsetY)

//                //调用layout方法来重新放置他的位置
//                layout(left+offsetX,top+offsetY,right + offsetX, bottom + offsetY)
            }
        }

No entanto, depois da minha experiência, esta tem um grande desvio, sempre para a direita. que razão?

4. Em seguida, veja como usar o quarto método, usando animação para deslizar.

<?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>

Use o código para ligar:

findViewById<View>(R.id.view_my).animation = AnimationUtils.loadAnimation(this,R.anim.translate)

Deve-se notar que a animação da vista não altera os parâmetros de posição da vista. Assim, quando clicarmos no Button, ele não será acionado, pois seu controle negativo deve primeiro julgar se o evento click está dentro da faixa dos parâmetros de posição da view filho antes de ser distribuído a ele. , ele responderá. Se queremos que ele responda à posição movida, ou seja, mude os parâmetros de posição da vista, então podemos usar a animação de propriedade.

  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. Em seguida, vamos ver o quinto método, scrollTo e ScrollBy

scrollTo(x,y) significa mover para um ponto de coordenada específico e scrollBy(dx,dy) significa que o incremento do movimento é dx, dy. Na verdade, sabemos que scrollBy finalmente calcula as coordenadas finais olhando o código-fonte e finalmente chama scrollTo . Podemos olhar o código fonte:

 public void scrollBy(int x, int y) {
        scrollTo(mScrollX + x, mScrollY + y);
    }

Deve-se observar que scrollTo e ScrollBy são conteúdo móvel. Se definirmos Bacgroud, não encontraremos nenhum efeito. Pode ser alterado para:

 <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()
        }

Use o primeiro plano. Então veja o efeito:

 Começou assim, e então clicamos no botão, e ficou assim:

 Você descobriu algo milagroso? Clique novamente:

 Bom rapaz, quase fora de vista. Qual é a razão? Existem dois fenômenos estranhos aqui, o primeiro é que ele parece se mover na direção oposta, e o segundo é que ele está ficando cada vez menor. Para ser preciso, parece que não está com zoom, mas apenas parte dela pode ser vista.

Isso se deve à diferença nos objetos de referência. Suponha que comparemos a tela do celular com uma lupa. O conteúdo a seguir é tratado como um jornal. Quando chamamos esse método, na verdade fazemos a lupa se mover para baixo em relação à vista, e o lugar que a lupa não consegue ver não existe. É por isso que ele parece ter se movido para cima e para a esquerda. Então, como estamos movendo o conteúdo, a View em si não se move, então sua cor de foreground não pode ser vista.

Se quisermos poder mover com os dedos, podemos modificá-lo assim no método move:

MotionEvent.ACTION_MOVE -> {
                //计算移动距离
                val offsetX = x -lastX
                val offsetY = y -lastY

                val parentView = parent as View
                parentView.scrollBy(-offsetX,-offsetY)
}

Aqui, o valor oposto é tomado, como Gang acabou de dizer, porque o objeto de referência levará à visão oposta. E para obter seu pai, porque essa visão pertence ao conteúdo de seu pai. Portanto, ele pode executar ações relacionadas.

6. Vejamos o sexto método Scroller

Quando usamos o método scrollTo/scrollBy para deslizar, o processo é concluído instantaneamente. Então a experiência não é muito boa. Podemos usar o scroller para obter deslizamento com efeito de transição. No entanto, o próprio scroller não pode realizar o deslizamento da View. Ele precisa cooperar com o método computeScroller da View para obter o efeito de deslizamento elástico. Vejamos a implementação do código:

Primeiro, defina uma variável de membro:

 private val mScroller = Scroller(context)

Em seguida, reescrevemos o método computeScroll, que é chamado no método draw quando o sistema desenha a View.

Vamos primeiro definir um método em CustomView:

 fun smoothScrollTo(destX:Int, destY:Int){
        val scrollX = scrollX
        val delta  = destX - scrollX
        mScroller.startScroll(scrollX,0,delta,2,2000)
        invalidate()
    }

Este método é fornecido para chamadas externas e os parâmetros são X e Y que você deseja compensar.

scrollX é o valor que já foi deslizado até agora, e o valor que já foi deslizado é subtraído daquele a ser compensado pelo alvo, que é o que resta. Chame o método scroller.startScroll(). Defina uma duração. Chamamos invalidate() para começar a redesenhar. Neste momento, o método computeScroller da exibição será chamado. Aqui chamamos o método scrollTo do viewGroup do espaço pai para obter o valor atual do pequeno slide e, em seguida, executamos um pequeno slide. Em seguida, chame o método invalidate() para redesenhar continuamente.

 override fun computeScroll() {
        super.computeScroll()
        if (mScroller.computeScrollOffset()) {
            (parent as View).scrollTo(mScroller.currX,mScroller.currY)
            invalidate()
        }
    }

Por fim, chamamos a atividade:
 

 customView.smoothScrollTo(-400,0)

Panorâmica 400 para a direita.

Acho que você gosta

Origin blog.csdn.net/howlaa/article/details/128452434
Recomendado
Clasificación