Android 在视图上设置y值时滚动视图不滚动

Android 在视图上设置y值时滚动视图不滚动,android,kotlin,Android,Kotlin,我是android开发的新手,两个多星期来我一直在这个问题上碰壁。我通过学习Kotlin开始了我的android开发 我有一个ScrollView作为应用程序布局的一部分,在ScrollView中有一个布局。我以编程方式定位XML中基于TextSwitcher的按钮,主要是调整按钮的大小并将其移出屏幕。这些按钮是用来在屏幕上滑动的弹簧动画。问题是,当我设置按钮的y位置时,ScrollView不会滚动 我在ScrollView中使用了各种布局(LinearLayout、RelativeLayout

我是android开发的新手,两个多星期来我一直在这个问题上碰壁。我通过学习Kotlin开始了我的android开发

我有一个ScrollView作为应用程序布局的一部分,在ScrollView中有一个布局。我以编程方式定位XML中基于TextSwitcher的按钮,主要是调整按钮的大小并将其移出屏幕。这些按钮是用来在屏幕上滑动的弹簧动画。问题是,当我设置按钮的y位置时,ScrollView不会滚动

我在ScrollView中使用了各种布局(LinearLayout、RelativeLayout、FrameLayout),它们的行为方式都是一样的。如果我没有使用y值以编程方式定位按钮,这意味着让按钮完全通过XML定位(对于我当时在ScrollView中使用的任何布局),以便它们在屏幕上启动,ScrollView可以正常滚动。即使我这样使用Spring动画,它仍然可以很好地滚动,所以我认为使用动画不是问题。只有当我通过代码设置每个按钮视图的初始y值时,它才不会滚动

我有一个精简的测试应用程序,没有应用程序的所有其他功能,显示问题。我让ScrollView滚动的方法就是在ScrollView中添加布局可能需要的任何属性,并注释掉setButton方法中的“button.y=-y”行。例如,如果我只是将ScrollView中的FrameLayout更改为LinearLayout,并在代码中设置y值,则按钮将在屏幕上一个接一个地排列,并滚动OK。单击“Get Started”(开始)按钮可使它们使用Spring动画进行动画制作,并且在动画之后仍会滚动。只需将设置y行添加回,即可使ScrollView不滚动

以下是XML:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/mainLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:focusableInTouchMode="true"
    android:orientation="horizontal"
    tools:context="com.example.scrolltest.MainActivity">

    <View
        android:id="@+id/centerShim"
        android:layout_height="match_parent"
        android:layout_width="0dp"
        android:visibility="invisible"
        android:layout_centerHorizontal="true"/>

    <ScrollView
        android:id="@+id/buttonScrollView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:elevation="2dp"
        android:fillViewport="true"
        android:orientation="vertical"
        android:layout_alignParentTop="true"
        android:layout_alignParentStart="true"
        android:layout_toLeftOf="@id/centerShim"
        android:scrollbars="none">

        <FrameLayout
            android:id="@+id/buttonLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <com.example.scrolltest.MyButton
                android:id="@+id/button1View"
                android:background="@color/black"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:gravity="center"
                    android:textColor="@color/white"
                    android:textSize="30sp"
                    android:layout_alignParentTop="true"
                    android:layout_alignParentStart="true"/>

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:gravity="center"
                    android:textColor="@color/white"
                    android:textSize="30sp"
                    android:layout_alignParentTop="true"
                    android:layout_alignParentStart="true"/>
            </com.example.scrolltest.MyButton>

            <com.example.scrolltest.MyButton
                android:id="@+id/button2View"
                android:background="@color/black"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:gravity="center"
                    android:textColor="@color/white"
                    android:textSize="30sp"
                    android:layout_alignParentTop="true"
                    android:layout_alignParentStart="true"/>

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:gravity="center"
                    android:textColor="@color/white"
                    android:textSize="30sp"
                    android:layout_alignParentTop="true"
                    android:layout_alignParentStart="true"/>
            </com.example.scrolltest.MyButton>

            <com.example.scrolltest.MyButton
                android:id="@+id/button3View"
                android:background="@color/black"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:gravity="center"
                    android:textColor="@color/white"
                    android:textSize="30sp"
                    android:layout_alignParentTop="true"
                    android:layout_alignParentStart="true"/>

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:gravity="center"
                    android:textColor="@color/white"
                    android:textSize="30sp"
                    android:layout_alignParentTop="true"
                    android:layout_alignParentStart="true"/>
            </com.example.scrolltest.MyButton>

            <com.example.scrolltest.MyButton
                android:id="@+id/button4View"
                android:background="@color/black"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:gravity="center"
                    android:textColor="@color/white"
                    android:textSize="30sp"
                    android:layout_alignParentTop="true"
                    android:layout_alignParentStart="true"/>

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:gravity="center"
                    android:textColor="@color/white"
                    android:textSize="30sp"
                    android:layout_alignParentTop="true"
                    android:layout_alignParentStart="true"/>
            </com.example.scrolltest.MyButton>

            <com.example.scrolltest.MyButton
                android:id="@+id/button5View"
                android:background="@color/black"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:gravity="center"
                    android:textColor="@color/white"
                    android:textSize="30sp"
                    android:layout_alignParentTop="true"
                    android:layout_alignParentStart="true"/>

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:gravity="center"
                    android:textColor="@color/white"
                    android:textSize="30sp"
                    android:layout_alignParentTop="true"
                    android:layout_alignParentStart="true"/>
            </com.example.scrolltest.MyButton>

            <com.example.scrolltest.MyButton
                android:id="@+id/button6View"
                android:background="@color/black"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:gravity="center"
                    android:textColor="@color/white"
                    android:textSize="30sp"
                    android:layout_alignParentTop="true"
                    android:layout_alignParentStart="true"/>

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:gravity="center"
                    android:textColor="@color/white"
                    android:textSize="30sp"
                    android:layout_alignParentTop="true"
                    android:layout_alignParentStart="true"/>
            </com.example.scrolltest.MyButton>

            <com.example.scrolltest.MyButton
                android:id="@+id/button7View"
                android:background="@color/black"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:gravity="center"
                    android:textColor="@color/white"
                    android:textSize="30sp"
                    android:layout_alignParentTop="true"
                    android:layout_alignParentStart="true"/>

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:gravity="center"
                    android:textColor="@color/white"
                    android:textSize="30sp"
                    android:layout_alignParentTop="true"
                    android:layout_alignParentStart="true"/>
            </com.example.scrolltest.MyButton>

            <com.example.scrolltest.MyButton
                android:id="@+id/button8View"
                android:background="@color/black"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:gravity="center"
                    android:textColor="@color/white"
                    android:textSize="30sp"
                    android:layout_alignParentTop="true"
                    android:layout_alignParentStart="true"/>

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:gravity="center"
                    android:textColor="@color/white"
                    android:textSize="30sp"
                    android:layout_alignParentTop="true"
                    android:layout_alignParentStart="true"/>
            </com.example.scrolltest.MyButton>
        </FrameLayout>
    </ScrollView>

    <TextView
        android:id="@+id/getStartedView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentEnd="true"
        android:layout_alignParentBottom="true"
        android:layout_marginEnd="5dp"
        android:layout_marginBottom="5dp"
        android:background="@color/black"
        android:gravity="center"
        android:text="Get Started"
        android:textColor="@color/white"
        android:textSize="30sp"/>
</RelativeLayout>
我不明白为什么每个按钮视图上的SETY调用会导致滚动问题。感谢您的帮助。谢谢

package com.example.scrolltest

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.util.TypedValue
import android.view.animation.AnimationUtils
import android.widget.*
import androidx.dynamicanimation.animation.DynamicAnimation
import androidx.dynamicanimation.animation.SpringAnimation
import androidx.dynamicanimation.animation.SpringForce

class MainActivity : AppCompatActivity() {
    private var buttonAnimationOffset: Float = 0f
    // STIFFNESS_MEDIUM = 1500, higher is stiffer.
    private val stiffnessValue = 300f
    // DAMPING_RATIO_MEDIUM_BOUNCY = 0.5, higher dampens quicker.
    private val dampeningValue = 0.7f
    private val initialVelocity = 0.5f
    private val fadeDuration = 500L
    private var lastButtonAnim: SpringAnimation? = null
    private var buttonWidth = 0f
    private var buttonHeight = 0f

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val screenWidth = resources.displayMetrics.widthPixels
        val screenHeight = resources.displayMetrics.heightPixels

        var h = 0
        buttonWidth = screenWidth * 0.33f
        buttonHeight = screenHeight * 0.16f

        buttonAnimationOffset = -buttonHeight

        setButton(R.id.button1View, buttonHeight * 8, "Button 1")
        setButton(R.id.button2View, buttonHeight * 7, "Button 2")
        setButton(R.id.button3View, buttonHeight * 6, "Button 3")
        setButton(R.id.button4View, buttonHeight * 5, "Button 4")
        setButton(R.id.button5View, buttonHeight * 4, "Button 5")
        setButton(R.id.button6View, buttonHeight * 3, "Button 6")
        setButton(R.id.button7View, buttonHeight * 2, "Button 7")
        setButton(R.id.button8View, buttonHeight, "Button 8")

        val startButton = findViewById<TextView>(R.id.getStartedView)

        startButton.setOnClickListener {
            lastButtonAnim?.start()
        }

        /*
        val buttonScrollView = findViewById<ScrollView>(R.id.buttonScrollView)

        buttonScrollView.getViewTreeObserver()
            .addOnScrollChangedListener(object : ViewTreeObserver.OnScrollChangedListener {
                var lastScroll = 0
                override fun onScrollChanged() {
                    Log.i("ScrollView", "[" + buttonScrollView.scrollX.toString() + "] [" + buttonScrollView.scrollX.toString() + "]")
                    val scrollY: Int =
                        buttonScrollView.getScrollY() // For ScrollView herzontial use getScrollX()
                    if (scrollY > lastScroll) {
                        Log.e("scroll", "down scroll$scrollY")
                    } else if (scrollY < lastScroll) {
                        Log.e("scroll", "up scroll$scrollY")
                    }
                    lastScroll = scrollY
                }
            })
        */

        setButtonAnimationsAndListeners(buttonHeight)
    }

    private fun setButton( id: Int, y: Float, text: String ) {
        val button = findViewById<MyButton>(id)
        val mainLayout = findViewById<RelativeLayout>(R.id.mainLayout)

        if ( button.layoutParams == null ) {
            val buttonLayout = findViewById<FrameLayout>(R.id.buttonLayout)
            button.layoutParams = FrameLayout.LayoutParams(buttonLayout.layoutParams)
        }
        button.layoutParams.height = buttonHeight.toInt()
        button.layoutParams.width = buttonWidth.toInt()
        button.y = -y

        button.setOnClickListener {
            val tv = button.currentView as TextView

            if (tv.text.contains(" clicked"))
            {
                button.setText(tv.text.dropLast(8))
            }
            else
            {
                button.setText(tv.text.toString() + " clicked")
            }
        }

        button.setCurrentText(text)
    }

    private fun setButtonAnimationsAndListeners(height: Float) {
        val anim1 = setButtonAnimationAndListener(
            R.id.button1View,
            null,
            0f
        )

        val anim2 = setButtonAnimationAndListener(
            R.id.button2View,
            anim1,
            0f
        )

        val anim3 = setButtonAnimationAndListener(
            R.id.button3View,
            anim2,
            0f
        )

        val anim4 = setButtonAnimationAndListener(
            R.id.button4View,
            anim3,
            0f
        )

        val anim5 = setButtonAnimationAndListener(
            R.id.button5View,
            anim4,
            0f
        )

        val anim6 = setButtonAnimationAndListener(
            R.id.button6View,
            anim5,
            0f
        )

        val anim7 = setButtonAnimationAndListener(
            R.id.button7View,
            anim6,
            0f
        )

        // Last button
        lastButtonAnim = setButtonAnimationAndListener(
            R.id.button8View,
            anim7,
           height
        )
    }

    private fun setButtonAnimationAndListener(
        buttonId: Int,
        prevAnim: SpringAnimation?,
        height: Float
    ): SpringAnimation {

        val view = findViewById<MyButton>(buttonId)
        val buttonLayout = findViewById<FrameLayout>(R.id.buttonLayout)

        lateinit var anim: SpringAnimation

        if (height > 0) {
            Log.i("setAnim", "finalPosition = " + (height * ( buttonLayout.childCount - 1 )) )
            anim = SpringAnimation(
                view,
                DynamicAnimation.TRANSLATION_Y
            ).apply {
                spring = SpringForce().apply {
                    stiffness = stiffnessValue
                    dampingRatio = dampeningValue
                    finalPosition = height * ( buttonLayout.childCount - 1 )
                }
            }
        } else {
            anim = SpringAnimation(
                view,
                DynamicAnimation.TRANSLATION_Y
            ).apply {
                spring = SpringForce().apply {
                    stiffness = stiffnessValue
                    dampingRatio = dampeningValue
                }
            }
        }

        anim.setStartVelocity(
            TypedValue.applyDimension(
                TypedValue.COMPLEX_UNIT_DIP,
                initialVelocity,
                resources.displayMetrics
            )
        )

        anim.addUpdateListener { _, value, _ ->
            Log.i("anim", "[" + getResources().getResourceEntryName(view.id) + "] value = " + value.toString() + " buttonAnimationOffset = " + buttonAnimationOffset.toString() + ", value + buttonAnimationOffset = " + (value + buttonAnimationOffset).toString())
            prevAnim?.animateToFinalPosition(value + buttonAnimationOffset)
        }

        // Set fade in and out animations for changing the text.
        val textAnimationIn = AnimationUtils.loadAnimation(this, android.R.anim.fade_in)
        textAnimationIn.duration = fadeDuration

        val textAnimationOut = AnimationUtils.loadAnimation(this, android.R.anim.fade_out)
        textAnimationOut.duration = fadeDuration

        view.setInAnimation(textAnimationIn)
        view.setOutAnimation(textAnimationOut)

        return anim
    }
}
package com.example.scrolltest

import android.content.Context
import android.graphics.Canvas
import android.graphics.drawable.Drawable
import android.util.AttributeSet
import android.util.Log
import android.widget.ScrollView
import android.widget.TextSwitcher

class MyButton: TextSwitcher {
    constructor( context: Context) : super( context ) {
    }
    constructor(context: Context, attrs: AttributeSet? ): super( context, attrs ) {
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)

        val x = this.x
        val y = this.y
        val h = this.height
        val w = this.width
        val t = this.top
        val ty = this.translationY
        Log.i("onMeasure", "[" + getResources().getResourceEntryName(id) + "] y = " + y.toString() + ", top = " + t.toString() + ", translateY = " + ty.toString())
    }

    override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
        super.onLayout(changed, left, top, right, bottom)

        val x = this.x
        val y = this.y
        val h = this.height
        val w = this.width
        val t = this.top
        val ty = this.translationY
        Log.i("onLayout", "[" + getResources().getResourceEntryName(id) + "] y = " + y.toString() + ", top = " + t.toString() + ", translateY = " + ty.toString())
    }
}