gpt4 book ai didi

android - 如何在类似于 Youtube 的 MotionLayout 中处理 和 onClickListener

转载 作者:行者123 更新时间:2023-12-02 04:23:07 24 4
gpt4 key购买 nike

我一直在尝试了解 MotionLayout 的工作原理,经过一番尝试后,我对 OnClick 如何为 View 工作有疑问。

我有一些我尝试过的东西 official examples .我尝试了类似于 youtube 刷卡的方法。
scene_24.xml

<Transition
motion:constraintSetEnd="@+id/end"
motion:constraintSetStart="@+id/start"
motion:duration="1000"
motion:motionInterpolator="linear">

<OnSwipe
motion:dragDirection="dragUp"
motion:touchAnchorSide="bottom"
motion:touchRegionId="@+id/top_image_container" />

<ConstraintSet android:id="@id/start">

<Constraint
android:id="@id/top_image_container"
android:layout_width="0dp"
android:layout_height="320dp"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintTop_toTopOf="parent" />

<Constraint
android:id="@id/top_image"
android:layout_width="0dp"
android:layout_height="0dp"
motion:layout_constraintBottom_toBottomOf="@id/top_image_container"
motion:layout_constraintEnd_toEndOf="@id/top_image_container"
motion:layout_constraintStart_toStartOf="@id/top_image_container"
motion:layout_constraintTop_toTopOf="@id/top_image_container" />

<Constraint
android:id="@id/recyclerview_container"
android:layout_width="0dp"
android:layout_height="0dp"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintTop_toBottomOf="@id/top_image_container" />

<Constraint
android:id="@id/recyclerview_front"
android:layout_width="0dp"
android:layout_height="0dp"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintTop_toBottomOf="@id/top_image_container" />

<Constraint android:id="@+id/image_play">
<PropertySet motion:alpha="0" />
</Constraint>

<Constraint android:id="@+id/image_clear">
<PropertySet motion:alpha="0" />
</Constraint>

<Constraint
android:id="@id/bottom_nav"
android:layout_width="0dp"
android:layout_height="wrap_content"
motion:layout_constraintLeft_toLeftOf="parent"
motion:layout_constraintRight_toRightOf="parent"
motion:layout_constraintTop_toBottomOf="parent" />
</ConstraintSet>

<ConstraintSet android:id="@id/end">

<Constraint
android:id="@id/top_image_container"
android:layout_width="0dp"
android:layout_height="52dp"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
motion:layout_constraintBottom_toTopOf="@id/bottom_nav"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintStart_toStartOf="parent" />

<Constraint
android:id="@id/top_image"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="2dp"
android:layout_marginBottom="2dp"
motion:layout_constraintBottom_toBottomOf="@id/top_image_container"
motion:layout_constraintDimensionRatio="H,1:2.5"
motion:layout_constraintStart_toStartOf="@id/top_image_container"
motion:layout_constraintTop_toTopOf="@id/top_image_container" />

<Constraint
android:id="@id/recyclerview_container"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
motion:layout_constraintBottom_toTopOf="@id/bottom_nav"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintTop_toBottomOf="@id/top_image_container" />

<Constraint
android:id="@id/recyclerview_front"
android:layout_width="0dp"
android:layout_height="0dp"
android:alpha="0"
motion:layout_constraintBottom_toBottomOf="@id/top_image_container"
motion:layout_constraintEnd_toEndOf="@id/top_image_container"
motion:layout_constraintStart_toStartOf="@id/top_image_container"
motion:layout_constraintTop_toBottomOf="@id/top_image_container" />

<Constraint android:id="@+id/image_play">
<PropertySet motion:alpha="1" />
</Constraint>

<Constraint android:id="@id/image_clear">
<PropertySet motion:alpha="1" />
</Constraint>


<Constraint
android:id="@id/bottom_nav"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="?android:attr/windowBackground"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintLeft_toLeftOf="parent"
motion:layout_constraintRight_toRightOf="parent" />
</ConstraintSet>

<KeyFrameSet>

<KeyPosition
motion:curveFit="linear"
motion:framePosition="90"
motion:motionTarget="@id/top_image"
motion:percentWidth="0"
motion:percentX="0" />

<KeyPosition
motion:curveFit="linear"
motion:framePosition="90"
motion:motionTarget="@id/top_image_container"
motion:percentWidth="0" />

<KeyPosition
motion:curveFit="linear"
motion:framePosition="90"
motion:motionTarget="@id/recyclerview_container"
motion:percentWidth="0" />

<KeyAttribute
android:alpha="0"
motion:framePosition="75"
motion:motionTarget="@id/recyclerview_front" />

<KeyAttribute
android:alpha="0.10"
motion:framePosition="90"
motion:motionTarget="@id/image_clear" />

<KeyAttribute
android:alpha="0.10"
motion:framePosition="90"
motion:motionTarget="@id/image_play" />
</KeyFrameSet>
</Transition>
motion_layout_anim :
<androidx.constraintlayout.motion.widget.MotionLayout 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/motionLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#444"
app:layoutDescription="@xml/scene_24"
tools:ignore="contentDescription"
>

<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/top_image_container"
android:layout_width="match_parent"
android:layout_height="320dp"
android:background="?android:attr/windowBackground"
app:layout_constrainedWidth="true"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />

<com.google.android.youtube.player.YouTubePlayerView
android:id="@+id/top_image"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintTop_toTopOf="@id/top_image_container"
app:layout_constraintBottom_toBottomOf="@id/top_image_container"
app:layout_constraintStart_toStartOf="@id/top_image_container"
app:layout_constraintEnd_toEndOf="@id/top_image_container" />
<!-- <ImageView
android:id="@+id/image_play"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
app:srcCompat="@drawable/ic_play_arrow_gray_32dp"
android:alpha="0"
app:layout_constraintEnd_toStartOf="@id/image_clear"
app:layout_constraintTop_toTopOf="@id/top_image_container"
app:layout_constraintBottom_toBottomOf="@id/top_image_container"
/>

<ImageView
android:id="@+id/image_clear"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
app:srcCompat="@drawable/ic_clear_gray_32dp"
android:alpha="0"
app:layout_constraintEnd_toEndOf="@id/top_image_container"
app:layout_constraintBottom_toBottomOf="@id/top_image_container"
app:layout_constraintTop_toTopOf="@id/top_image_container"
/>-->

<FrameLayout
android:id="@+id/recyclerview_container"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="?android:attr/windowBackground"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/top_image_container"
/>

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerview_front"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/top_image_container" />

<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_nav"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="?android:attr/windowBackground"
app:layout_constraintTop_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:menu="@menu/bottom_nav_menu"
/>
</androidx.constraintlayout.motion.widget.MotionLayout>

现在进入正题,我有 问题:
  • 如果我使用 youtube播放器,如果我放置这些播放图标并关闭,我的播放器将无法正常工作。那么 Youtube 是如何工作的(假设我从官方文档中获取了这个例子)?

  • W/YouTubeAndroidPlayerAPI: YouTube video playback stopped due to unauthorized overlay on top of player. The YouTubePlayerView is obscured by android.widget.ImageView{3ae28d60 V.ED.... ........ 704,320-704,320 #7f09009f app:id/image_play}. The obscuring view is inside the player view's interior zone. The distance (px) between each edge of the obscuring view and each corresponding interior zone edge is: left: 704, top: 320, right: 64, bottom: 320. .


  • 当我最小化时,我的视频会停止,即使用 OnSwipe并且播放器变小了。我试图理解 this但我只是想知道他们是如何在官方 Youtube 应用中播放的。

  • W/YouTubeAndroidPlayerAPI: YouTube video playback stopped due to the player's view being too small. The YouTubePlayerView is 384dp wide (minimum is 200dp) and 87dp high (minimum is 110dp).


  • 最后但并非最不重要也是最重要的一点,当我使用 motion:touchRegionId="@+id/top_image_container" 时,我究竟如何让 Youtube 播放器暂停/播放和使用任何其他控件当我使用它时,播放器变得不可点击/不可聚焦,甚至在使用 touchRegionId 之后玩家只能从下面的空白处向下滑动(为什么)。

  • PS:我已经测试和尝试过的东西,虽然不起作用。
  • MotionLayout: MotionScene OnClick overrides setOnClickListener
  • Can we use OnSwipe and OnClick in the same <Transition> for Android MotionLayout?
  • 最佳答案

    Youtube官方申请uses ExoPlayer inside it ,据我了解,他们不使用他们的 Youtube SDK :) 所以,ExoPlayer 没有限制:宽度/高度/覆盖。

    我遇到了和你一样的问题,我使用了这个库 - android-youtube-player用于播放 youtube 视频。

    关于屏幕触摸,当您触摸 VideoView(youtube) 时,它会拦截 TouchEvent,因此,我们需要在 VideoView 捕获它之前拦截 TouchEvent。我们需要了解它是什么类型的事件。如果是 Swipe -> 我们在父 View 中拦截事件。如果它 Click -> 我们不拦截此事件。

    我从 this article 获得的自定义 MotionLayout 示例.它仅从选定的 View 中捕获触摸。代码示例:

    <?xml version="1.0" encoding="utf-8"?>
    <MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:motion="http://schemas.android.com/apk/res-auto">

    <Transition
    motion:constraintSetEnd="@+id/end"
    motion:constraintSetStart="@+id/start"
    motion:duration="1000"
    motion:motionInterpolator="linear">

    <OnSwipe
    motion:touchAnchorId="@+id/top_image_container"
    motion:touchAnchorSide="bottom"
    motion:dragDirection="dragUp" />

    <ConstraintSet android:id="@id/start">

    <Constraint
    android:id="@id/top_image_container"
    android:layout_width="0dp"
    android:layout_height="233dp"
    motion:layout_constraintTop_toTopOf="parent"
    motion:layout_constraintStart_toStartOf="parent"
    motion:layout_constraintEnd_toEndOf="parent" />

    <Constraint
    android:id="@id/top_image"
    android:layout_width="0dp"
    android:layout_height="0dp"
    motion:layout_constraintTop_toTopOf="@id/top_image_container"
    motion:layout_constraintBottom_toBottomOf="@id/top_image_container"
    motion:layout_constraintStart_toStartOf="@id/top_image_container"
    motion:layout_constraintEnd_toEndOf="@id/top_image_container"
    />

    <Constraint
    android:id="@id/recyclerview_container"
    android:layout_width="0dp"
    android:layout_height="0dp"
    motion:layout_constraintTop_toBottomOf="@id/top_image_container"
    motion:layout_constraintBottom_toBottomOf="parent"
    motion:layout_constraintEnd_toEndOf="parent"
    motion:layout_constraintStart_toStartOf="parent" />

    <Constraint
    android:id="@id/recyclerview_front"
    android:layout_width="0dp"
    android:layout_height="0dp"
    motion:layout_constraintTop_toBottomOf="@id/top_image_container"
    motion:layout_constraintBottom_toBottomOf="parent"
    motion:layout_constraintEnd_toEndOf="parent"
    motion:layout_constraintStart_toStartOf="parent"/>

    <Constraint android:id="@id/image_play" >
    <PropertySet motion:alpha="0" />
    </Constraint>

    <Constraint android:id="@id/image_clear" >
    <PropertySet motion:alpha="0" />
    </Constraint>

    </ConstraintSet>

    <ConstraintSet android:id="@id/end">

    <Constraint
    android:id="@id/top_image_container"
    android:layout_width="0dp"
    android:layout_height="80dp"
    android:layout_marginBottom="56dp"
    android:layout_marginStart="0dp"
    android:layout_marginEnd="0dp"
    motion:layout_constraintEnd_toEndOf="parent"
    motion:layout_constraintStart_toStartOf="parent"
    motion:layout_constraintBottom_toBottomOf="parent" />

    <Constraint
    android:id="@+id/close"
    android:layout_width="28dp"
    android:layout_height="28dp"
    android:layout_marginRight="16dp"
    motion:layout_constraintTop_toTopOf="@+id/playerContainer"
    motion:layout_constraintRight_toRightOf="@+id/playerContainer"
    motion:layout_constraintBottom_toBottomOf="@+id/playerContainer"/>

    <Constraint
    android:id="@id/top_image"
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:layout_marginTop="0dp"
    android:layout_marginBottom="0dp"
    motion:layout_constraintTop_toTopOf="@id/top_image_container"
    motion:layout_constraintBottom_toBottomOf="@id/top_image_container"
    motion:layout_constraintStart_toStartOf="@id/top_image_container"
    motion:layout_constraintDimensionRatio="H,1:1.8"
    />

    <Constraint
    android:id="@id/recyclerview_container"
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:layout_marginBottom="56dp"
    android:layout_marginStart="0dp"
    android:layout_marginEnd="0dp"
    motion:layout_constraintTop_toBottomOf="@id/top_image_container"
    motion:layout_constraintBottom_toBottomOf="parent"
    motion:layout_constraintEnd_toEndOf="parent"
    motion:layout_constraintStart_toStartOf="parent" />

    <Constraint
    android:id="@id/recyclerview_front"
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:alpha="0"
    motion:layout_constraintTop_toBottomOf="@id/top_image_container"
    motion:layout_constraintBottom_toBottomOf="@id/top_image_container"
    motion:layout_constraintEnd_toEndOf="@id/top_image_container"
    motion:layout_constraintStart_toStartOf="@id/top_image_container"
    />

    <Constraint android:id="@id/image_play" >
    <PropertySet motion:alpha="1" />
    </Constraint>

    <Constraint android:id="@id/image_clear" >
    <PropertySet motion:alpha="1" />
    </Constraint>
    </ConstraintSet>

    <KeyFrameSet>

    <KeyPosition
    motion:motionTarget="@id/top_image"
    motion:framePosition="90"
    motion:percentWidth="0"
    motion:percentX="0"
    motion:curveFit="linear"
    />

    <KeyPosition
    motion:motionTarget="@id/top_image_container"
    motion:framePosition="90"
    motion:percentWidth="0"
    motion:curveFit="linear"
    />

    <KeyPosition
    motion:motionTarget="@id/recyclerview_container"
    motion:framePosition="90"
    motion:percentWidth="0"
    motion:curveFit="linear"
    />

    <KeyAttribute
    android:alpha="0"
    motion:framePosition="75"
    motion:motionTarget="@id/recyclerview_front" />

    <KeyAttribute
    android:alpha="0.10"
    motion:framePosition="90"
    motion:motionTarget="@id/image_clear" />

    <KeyAttribute
    android:alpha="0.10"
    motion:framePosition="90"
    motion:motionTarget="@id/image_play" />

    <KeyAttribute
    android:alpha="0"
    motion:framePosition="95"
    motion:motionTarget="@id/close" />
    </KeyFrameSet>
    </Transition>

    </MotionScene>

    SingleViewTouchableMotionLayout.kt
    import android.content.Context
    import android.graphics.Rect
    import android.util.AttributeSet
    import android.view.GestureDetector
    import android.view.MotionEvent
    import android.view.View
    import androidx.constraintlayout.motion.widget.MotionLayout
    import com.example.android.R

    class SingleViewTouchableMotionLayout(context: Context, attributeSet: AttributeSet? = null) : MotionLayout(context, attributeSet) {

    private val viewRect = Rect()
    private var touchStarted = false

    private val viewToDetectTouch by lazy {
    findViewById<View>(R.id.top_image_container)
    }

    private val gestureListener by lazy {
    object : GestureDetector.SimpleOnGestureListener() {
    override fun onScroll(e1: MotionEvent, e2: MotionEvent, distanceX: Float, distanceY: Float): Boolean {
    viewToDetectTouch.getHitRect(viewRect)
    return viewRect.contains(e1.x.toInt(), e1.y.toInt())
    }
    }
    }

    private val gestureDetector by lazy {
    GestureDetector(context, gestureListener)
    }

    init {
    setTransitionListener(object : MotionLayout.TransitionListener {
    override fun onTransitionStarted(p0: MotionLayout?, p1: Int, p2: Int) {

    }

    override fun onTransitionTrigger(p0: MotionLayout?, p1: Int, p2: Boolean, p3: Float) {

    }

    override fun onTransitionChange(p0: MotionLayout?, p1: Int, p2: Int, p3: Float) {
    }

    override fun onTransitionCompleted(p0: MotionLayout?, p1: Int) {
    touchStarted = false
    }
    })

    }


    override fun onInterceptTouchEvent(event: MotionEvent?): Boolean {
    return gestureDetector.onTouchEvent(event)
    }

    override fun onTouchEvent(event: MotionEvent): Boolean {
    when (event.actionMasked) {
    MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
    touchStarted = false
    return super.onTouchEvent(event)
    }
    }
    if (!touchStarted) {
    viewToDetectTouch.getHitRect(viewRect)
    touchStarted = viewRect.contains(event.x.toInt(), event.y.toInt())
    }
    return touchStarted && super.onTouchEvent(event)
    }
    }

    fragment_video_new.kt
    <?xml version="1.0" encoding="utf-8"?>
    <com.example.android.android.features.music.SingleViewTouchableMotionLayout 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/motionLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layoutDescription="@xml/scene_24"
    tools:ignore="contentDescription">

    <FrameLayout
    app:layout_constraintTop_toTopOf="@+id/top_image_container"
    app:layout_constraintBottom_toBottomOf="@+id/recyclerview_container"
    android:id="@+id/playerContainer"
    android:layout_width="match_parent"
    android:layout_height="0dp"/>

    <androidx.constraintlayout.widget.ConstraintLayout
    android:id="@+id/top_image_container"
    android:layout_width="match_parent"
    android:layout_height="320dp"
    android:background="?android:attr/windowBackground"
    app:layout_constrainedWidth="true"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintEnd_toEndOf="parent" />

    <com.pierfrancescosoffritti.androidyoutubeplayer.core.player.views.YouTubePlayerView
    android:id="@+id/top_image"
    android:layout_width="0dp"
    android:layout_height="0dp"
    app:layout_constraintTop_toTopOf="@id/top_image_container"
    app:layout_constraintBottom_toBottomOf="@id/top_image_container"
    app:layout_constraintStart_toStartOf="@id/top_image_container"
    app:layout_constraintEnd_toEndOf="@id/top_image_container" />

    <ImageView
    android:id="@+id/image_play"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginEnd="16dp"
    android:alpha="0"
    app:layout_constraintEnd_toStartOf="@id/image_clear"
    app:layout_constraintTop_toTopOf="@id/top_image_container"
    app:layout_constraintBottom_toBottomOf="@id/top_image_container"
    />

    <ImageView
    android:id="@+id/image_clear"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginEnd="16dp"
    android:alpha="0"
    app:layout_constraintEnd_toEndOf="@id/top_image_container"
    app:layout_constraintBottom_toBottomOf="@id/top_image_container"
    app:layout_constraintTop_toTopOf="@id/top_image_container" />

    <FrameLayout
    android:id="@+id/recyclerview_container"
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:background="?android:attr/windowBackground"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@id/top_image_container" />


    <ImageView
    android:id="@+id/close"
    android:layout_width="28dp"
    android:layout_height="28dp"
    android:alpha="0"
    app:layout_constraintTop_toTopOf="@+id/playerContainer"
    app:layout_constraintRight_toRightOf="@+id/playerContainer"
    app:layout_constraintBottom_toBottomOf="@+id/playerContainer"
    app:srcCompat="@drawable/ic_close" />

    <com.revolut.rxdiffadapter.AsyncDiffRecyclerView
    android:id="@+id/recyclerview_front"
    android:layout_width="0dp"
    android:layout_height="0dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@id/top_image_container" />
    </com.example.android.android.features.music.SingleViewTouchableMotionLayout>

    gif
    enter image description here

    关于android - 如何在类似于 Youtube 的 MotionLayout 中处理 <OnClick> 和 onClickListener,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57819969/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com