我一直试图了解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>
现在,我有三个问题:
W / YouTubeAndroidPlayerAPI:由于播放器顶部的未授权覆盖,导致YouTube视频播放停止。 android.widget.ImageView {3ae28d60 V.ED .... ........ 704,320-704,320#7f09009f app:id / image_play}遮住了YouTubePlayerView。遮挡视图位于播放器视图的内部区域内。遮挡视图的每个边缘与相应的内部区域边缘之间的距离(px)为:左:704,上:320,右:64,下:320。
OnSwipe
时,视频停止播放,播放器变小。我试图了解this,但我只是想知道他们如何在YouTube官方应用中播放它。W / YouTubeAndroidPlayerAPI:由于播放器的视图过小,导致YouTube视频播放停止。 YouTubePlayerView的宽度为384dp(最小为200dp),高度为87dp(最小为110dp)。
motion:touchRegionId="@+id/top_image_container"
时,如何使Youtube播放器暂停/播放并使用其他控件,或者播放器变得无法点击/无法对焦甚至使用touchRegionId
后,只能从下面的空白处向玩家刷卡(为什么)。PS:尽管没有用,但我已经测试过并尝试过。
答案 0 :(得分:0)
Youtube官方应用uses ExoPlayer inside it,据我了解,他们不使用自己的Youtube SDK :)因此,ExoPlayer没有限制:宽度/高度/覆盖。
我遇到了与您相同的问题,并且我使用了这个库-android-youtube-player来播放youtube视频。
关于屏幕触摸,当您触摸VideoView(youtube)时,它会拦截TouchEvent,因此,我们需要在VideoView捕获它之前先拦截TouchEvent。我们需要了解这是什么类型的事件。如果是Swipe->,我们将在父视图中拦截事件。如果点击->,我们不会拦截此事件。
我从this article获得的自定义MotionLayout示例。它仅捕获所选视图中的触摸。代码示例:
<?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>