我的应用程序有一个项目列表,点击其中一个会带来一个片段,其中包含该项目的详细信息。细节包含一些有点复杂的RecyclerView(许多带FlexBoxLayoutManager的小视图),测量/布局传递可以超过50ms。
该延迟导致应用程序在片段转换开始时丢弃几帧,导致相当明显的跳#34;
我看到了一些可能的方法来避免这种情况:
不幸的是,退出动画必须在主线程上运行,测量/布局也是如此;测量/布局没有AsyncLayoutInflater
,对吗?
这个应用程序只需在onMeasure()
方法中添加一个睡眠,只要"慢速测量"选中复选框。
此处&#39; sa screen recording - 请注意复选框切换时的区别,跳转方式(左侧最明显的文字和旧/新片段之间的右边缘)。< / p>
var beSlow = false
class SlowWidget @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : TextView(context, attrs, defStyleAttr) {
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
if (beSlow) {
SystemClock.sleep(100)
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
}
}
class SlowFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater, parent: ViewGroup?, state: Bundle?): View {
return inflater.inflate(R.layout.fragment, parent, false)
}
}
class MainActivity : AppCompatActivity() {
var i = 0
val colors = arrayOf(Color.RED, Color.GREEN, Color.BLUE, Color.YELLOW, Color.CYAN)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.main)
}
fun viewClicked(v: View): Unit {
beSlow = slowbox.isChecked
supportFragmentManager.beginTransaction()
.setCustomAnimations(R.anim.slide_in, R.anim.slide_out)
.replace(R.id.container, SlowFragment().apply {
arguments = Bundle().apply {
putInt("color", colors[i++ % colors.size])
}
})
.commit()
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:text="Switch"
android:onClick="viewClicked"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<CheckBox
android:id="@+id/slowbox"
android:text="slow measure"
android:checked="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<se.dolkow.debug.animdemo.SlowWidget
xmlns:android="http://schemas.android.com/apk/res/android"
android:text="Hello World!"
android:textColor="#000"
android:gravity="center_vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/rainbow"
/>
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"
>
<gradient
android:startColor="#ffff0000"
android:centerColor="#ff00ff00"
android:endColor="#ff8000ff"
/>
</shape>
<?xml version="1.0" encoding="utf-8"?>
<set
xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:shareInterpolator="false"
>
<translate android:fromXDelta="100%p" android:toXDelta="0"
android:interpolator="@android:anim/linear_interpolator" />
</set>
<?xml version="1.0" encoding="utf-8"?>
<set
xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:shareInterpolator="false">
<translate android:fromXDelta="0" android:toXDelta="-100%p"
android:interpolator="@android:anim/linear_interpolator" />
</set>