Android嵌套滾動(dòng)與協(xié)調(diào)滾動(dòng)的實(shí)現(xiàn)方式匯總
Android的協(xié)調(diào)滾動(dòng)的幾種實(shí)現(xiàn)方式
上一期,我們講了嵌套滾動(dòng)的實(shí)現(xiàn)方式,為什么有了嵌套滾動(dòng)還需要協(xié)調(diào)滾動(dòng)這種方式呢?(不細(xì)講原理,本文只探討實(shí)現(xiàn)的方式與步驟?。?/p>
那在一些細(xì)度化的操作中,如我們需要一些控件隨著滾動(dòng)布局做一些粒度比較小的動(dòng)畫、移動(dòng)等操作,那么我們就需要監(jiān)聽滾動(dòng),然后改變當(dāng)前控件的屬性。
如何實(shí)現(xiàn)這種協(xié)調(diào)滾動(dòng)的布局呢?我們使用 CoordinatorLayout + AppBarLayout 或者 CoordinatorLayout + Behavior 實(shí)現(xiàn),另一種方案是 MotionLayout。我們看看都是怎么實(shí)現(xiàn)的吧。
一、CoordinatorLayout + Behavior
CoordinatorLayout 顧名思義是協(xié)調(diào)布局,其原理很簡(jiǎn)單,在onMeasure()的時(shí)候保存childView,通過(guò) PreDrawListener監(jiān)聽childView的變化,最終通過(guò)雙層for循環(huán)找到對(duì)應(yīng)的Behavior,分發(fā)任務(wù)即可。CoordinatorLayout實(shí)現(xiàn)了NestedScrollingParent2,那么在childView實(shí)現(xiàn)了NestedScrollingChild方法時(shí)候也能解決滑動(dòng)沖突問題。
而Behavior就是一個(gè)應(yīng)用于View的觀察者模式,一個(gè)View跟隨者另一個(gè)View的變化而變化,或者說(shuō)一個(gè)View監(jiān)聽另一個(gè)View。
在Behavior中,被觀察View 也就是事件源被稱為denpendcy,而觀察View,則被稱為child。
一般自定義Behavior來(lái)說(shuō)分兩種情況:
- 監(jiān)聽另一個(gè)view的狀態(tài)變化,例如大小、位置、顯示狀態(tài)等
- 監(jiān)聽CoordinatorLayout里的滑動(dòng)狀態(tài)
這里我們以之前的效果為主來(lái)實(shí)現(xiàn)自定義的Behavior,先設(shè)置NestedScrollView在ImageView下面:
public class MyScrollBehavior extends ViewOffsetBehavior<NestedScrollView> {
private int topImgHeight;
private int topTextHeight;
public MyScrollBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean layoutDependsOn(@NonNull CoordinatorLayout parent, @NonNull NestedScrollView child,
@NonNull View dependency) {
return dependency instanceof ImageView ;
}
@Override
protected void layoutChild(CoordinatorLayout parent, NestedScrollView child, int layoutDirection) {
super.layoutChild(parent, child, layoutDirection);
if (topImgHeight == 0) {
final List<View> dependencies = parent.getDependencies(child);
for (int i = 0, z = dependencies.size(); i < z; i++) {
View view = dependencies.get(i);
if (view instanceof ImageView) {
topImgHeight = view.getMeasuredHeight();
}
}
}
child.setTop(topImgHeight);
child.setBottom(child.getBottom() + topImgHeight);
}
}然后設(shè)置監(jiān)聽CoordinatorLayout里的滑動(dòng)狀態(tài),ImageView做同樣的滾動(dòng)
public class MyImageBehavior extends CoordinatorLayout.Behavior<View> {
private int topBarHeight = 0; //負(fù)圖片高度
private int downEndY = 0; //默認(rèn)為0
public MyImageBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onStartNestedScroll(@NonNull CoordinatorLayout coordinatorLayout,
@NonNull View child, @NonNull View directTargetChild,
@NonNull View target, int axes, int type) {
//監(jiān)聽垂直滾動(dòng)
return (axes & ViewCompat.SCROLL_AXIS_VERTICAL) != 0;
}
@Override
public void onNestedPreScroll(@NonNull CoordinatorLayout coordinatorLayout, @NonNull View child,
@NonNull View target, int dx, int dy, @NonNull int[] consumed, int type) {
if (topBarHeight == 0) {
topBarHeight = -child.getMeasuredHeight();
}
float transY = child.getTranslationY() - dy;
//處理上滑
if (dy > 0) {
if (transY >= topBarHeight) {
translationByConsume(child, transY, consumed, dy);
translationByConsume(target, transY, consumed, dy);
} else {
translationByConsume(child, topBarHeight, consumed, (child.getTranslationY() - topBarHeight));
translationByConsume(target, topBarHeight, consumed, (child.getTranslationY() - topBarHeight));
}
}
if (dy < 0 && !target.canScrollVertically(-1)) {
//處理下滑
if (transY >= topBarHeight && transY <= downEndY) {
translationByConsume(child, transY, consumed, dy);
translationByConsume(target, transY, consumed, dy);
} else {
translationByConsume(child, downEndY, consumed, (downEndY - child.getTranslationY()));
translationByConsume(target, downEndY, consumed, (downEndY - child.getTranslationY()));
}
}
}
@Override
public boolean onNestedFling(@NonNull CoordinatorLayout coordinatorLayout, @NonNull View child, @NonNull View target, float velocityX, float velocityY, boolean consumed) {
return super.onNestedFling(coordinatorLayout, child, target, velocityX,
velocityY, consumed);
}
private void translationByConsume(View view, float translationY, int[] consumed, float consumedDy) {
consumed[1] = (int) consumedDy;
view.setTranslationY(translationY);
}
}分別為ImageView和NestedScrollView設(shè)置對(duì)應(yīng)的 Behavior。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
android:orientation="vertical">
<com.guadou.lib_baselib.view.titlebar.EasyTitleBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:Easy_title="CoordinatorLayout+Behavior" />
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="150dp"
android:layout_height="150dp"
app:layout_behavior="com.google.android.material.appbar.MyImageBehavior"
android:layout_gravity="center_horizontal"
android:contentDescription="我是測(cè)試的圖片"
android:src="@mipmap/ic_launcher" />
<TextView
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#ccc"
android:gravity="center"
android:text="我是測(cè)試的分割線"
android:visibility="gone" />
<androidx.core.widget.NestedScrollView
android:id="@+id/nestedScroll"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="com.google.android.material.appbar.MyScrollBehavior">
<TextView
android:id="@+id/nestedScrollLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/scroll_content" />
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</LinearLayout>我們先把TextView隱藏先不處理TextView。效果如下:

這樣我們就實(shí)現(xiàn)了自定義 Behavior 監(jiān)聽滾動(dòng)的實(shí)現(xiàn)。那么我們加上TextView 的 Behavior 監(jiān)聽I(yíng)mageView的滾動(dòng),做對(duì)應(yīng)的滾動(dòng)。
先修改 MyScrollBehavior 讓他在ImageView和TextView下面
public class MyScrollBehavior extends ViewOffsetBehavior<NestedScrollView> {
private int topImgHeight;
private int topTextHeight;
public MyScrollBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean layoutDependsOn(@NonNull CoordinatorLayout parent, @NonNull NestedScrollView child,
@NonNull View dependency) {
return dependency instanceof ImageView || dependency instanceof TextView ;
}
@Override
protected void layoutChild(CoordinatorLayout parent, NestedScrollView child, int layoutDirection) {
super.layoutChild(parent, child, layoutDirection);
if (topImgHeight == 0) {
final List<View> dependencies = parent.getDependencies(child);
for (int i = 0, z = dependencies.size(); i < z; i++) {
View view = dependencies.get(i);
if (view instanceof ImageView) {
topImgHeight = view.getMeasuredHeight();
} else if (view instanceof TextView) {
topTextHeight = view.getMeasuredHeight();
view.setTop(topImgHeight);
view.setBottom(view.getBottom() + topImgHeight);
}
}
}
child.setTop(topImgHeight + topTextHeight);
child.setBottom(child.getBottom() + topImgHeight + topTextHeight);
}
}然后設(shè)置監(jiān)聽I(yíng)mageView的滾動(dòng):
public class MyTextBehavior extends CoordinatorLayout.Behavior<View> {
private int imgHeight;
public MyTextBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean layoutDependsOn(@NonNull CoordinatorLayout parent, @NonNull View child, @NonNull View dependency) {
return dependency instanceof ImageView;
}
@Override
public boolean onDependentViewChanged(@NonNull CoordinatorLayout parent, @NonNull View child, @NonNull View dependency) {
//跟隨ImageView滾動(dòng),ImageView滾動(dòng)多少我滾動(dòng)多少
float translationY = dependency.getTranslationY();
if (imgHeight == 0) {
imgHeight = dependency.getHeight();
}
float offsetTranslationY = imgHeight + translationY;
child.setTranslationY(offsetTranslationY);
return true;
}
}xml修改如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
android:orientation="vertical">
<com.guadou.lib_baselib.view.titlebar.EasyTitleBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:Easy_title="CoordinatorLayout+Behavior" />
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="150dp"
android:layout_height="150dp"
app:layout_behavior="com.google.android.material.appbar.MyImageBehavior"
android:layout_gravity="center_horizontal"
android:contentDescription="我是測(cè)試的圖片"
android:src="@mipmap/ic_launcher" />
<TextView
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#ccc"
app:layout_behavior="com.google.android.material.appbar.MyTextBehavior"
android:gravity="center"
android:text="我是測(cè)試的分割線"
android:visibility="visible" />
<androidx.core.widget.NestedScrollView
android:id="@+id/nestedScroll"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="com.google.android.material.appbar.MyScrollBehavior">
<TextView
android:id="@+id/nestedScrollLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/scroll_content" />
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</LinearLayout>Ok,修改完成之后我們看看最終的效果:

看到上面的示例,我們把常用的幾種 Behavior 都使用了一遍,系統(tǒng)的ViewOffsetBehavior 和監(jiān)聽滾動(dòng)的 Behavior 監(jiān)聽View的 Behavior。
為了實(shí)現(xiàn)這么一個(gè)簡(jiǎn)單的效果就用了這么多類,這么復(fù)雜。我分分鐘就能實(shí)現(xiàn)!
行行,我知道你厲害,這不是為了演示同樣的效果,使用不同的方式實(shí)現(xiàn)嘛。通過(guò) Behavior 可以實(shí)現(xiàn)一些嵌套滾動(dòng)不能完成的效果,比如鼎鼎大名的支付寶首頁(yè)效果,美團(tuán)詳情效果等。Behavior 更加的靈活,控制的粒度也更加的細(xì)。
但是如果只是簡(jiǎn)單實(shí)現(xiàn)上面的效果,我們可以用 AppBarLayout + 內(nèi)部自帶的 Behavior 也能實(shí)現(xiàn)類似的效果,AppBarLayout內(nèi)部已經(jīng)封裝并使用了 Behavior 。我們看看如何實(shí)現(xiàn)。
二、CoordinatorLayout + AppBarLayout
其實(shí)內(nèi)部也是基于 Behavior 實(shí)現(xiàn)的,內(nèi)部實(shí)現(xiàn)為 HeaderBehavior 和 HeaderScrollingViewBehavior 。
對(duì)一些場(chǎng)景使用進(jìn)行了封裝,滾動(dòng)效果,吸頂效果,折疊效果等。我們看看同樣的效果,使用 AppBarLayout 如何實(shí)現(xiàn)吧:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
android:orientation="vertical">
<com.guadou.lib_baselib.view.titlebar.EasyTitleBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:Easy_title="CoordinatorLayout+AppBarLayout" />
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:elevation="0dp"
android:background="@color/white"
android:orientation="vertical">
<ImageView
android:layout_width="match_parent"
android:layout_height="150dp"
android:contentDescription="我是測(cè)試的圖片"
android:src="@mipmap/ic_launcher"
app:layout_scrollFlags="scroll" />
<TextView
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#ccc"
android:gravity="center"
android:text="我是測(cè)試的分割線"
app:layout_scrollFlags="noScroll" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/scroll_content" />
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</LinearLayout>效果:

So Easy ! 真的是太方便了,類似的效果我們都能使用 AppbarLayout 來(lái)實(shí)現(xiàn),比如一些詳情頁(yè)面頂部圖片,下面列表或ViewPager的都可以使用這種方式,更加的便捷。
三、MotionLayout
不管怎么說(shuō),AppbarLayout 只能實(shí)現(xiàn)一些簡(jiǎn)單的效果,如果想要一些粒度比較細(xì)的效果,我們還得使用自定義 Behavior 來(lái)實(shí)現(xiàn),但是它的實(shí)現(xiàn)確實(shí)是有點(diǎn)復(fù)雜,2019年谷歌推出了 MotionLayout 。
淘寶的出現(xiàn)可以說(shuō)讓世上沒有難做的生意,那么 MotionLayout 的出現(xiàn)可以說(shuō)讓 Android 沒有難實(shí)現(xiàn)的動(dòng)畫了。不管是動(dòng)畫效果,滾動(dòng)效果,MotionLayout 絕殺!能用 Behavior 實(shí)現(xiàn)的 MotionLayout 幾乎是都能做。
使用 MotionLayout 我們只需要定義起始點(diǎn)和結(jié)束點(diǎn)就行了,我們這里不需要根據(jù)百分比Fram進(jìn)行別的操作,所以只定義最簡(jiǎn)單的使用。
我們看看如何用 MotionLayout 實(shí)現(xiàn)同樣的效果:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="@color/white"
android:orientation="vertical">
<com.guadou.lib_baselib.view.titlebar.EasyTitleBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:Easy_title="MotionLayout的動(dòng)作" />
<androidx.constraintlayout.motion.widget.MotionLayout
android:layout_width="match_parent"
android:layout_weight="1"
app:layoutDescription="@xml/scene_scroll_13"
android:layout_height="0dp">
<ImageView
android:id="@+id/iv_img"
android:layout_width="150dp"
android:layout_height="150dp"
android:scaleType="centerCrop"
android:contentDescription="我是測(cè)試的圖片"
android:src="@mipmap/ic_launcher" />
<TextView
android:id="@+id/tv_message"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#ccc"
android:gravity="center"
android:text="我是測(cè)試的分割線"
tools:layout_editor_absoluteY="150dp" />
<androidx.core.widget.NestedScrollView
android:id="@+id/nestedScroll"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/nestedScrollLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/scroll_content" />
</androidx.core.widget.NestedScrollView>
</androidx.constraintlayout.motion.widget.MotionLayout>
</LinearLayout>定義的scene_scroll_13.xml
<?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">
<OnSwipe
motion:dragDirection="dragUp"
motion:touchAnchorId="@id/nestedScroll" />
</Transition>
<ConstraintSet android:id="@+id/start">
<Constraint
android:id="@id/iv_img"
android:layout_width="150dp"
android:layout_height="150dp"
android:translationY="0dp"
motion:layout_constraintLeft_toLeftOf="parent"
motion:layout_constraintRight_toRightOf="parent"
motion:layout_constraintTop_toTopOf="parent" />
<Constraint
android:id="@id/tv_message"
android:layout_width="match_parent"
android:layout_height="50dp"
motion:layout_constraintTop_toBottomOf="@id/iv_img" />
<Constraint
android:id="@id/nestedScroll"
android:layout_width="match_parent"
android:layout_height="0dp"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintTop_toBottomOf="@id/tv_message" />
</ConstraintSet>
<ConstraintSet android:id="@+id/end">
<Constraint
android:id="@id/iv_img"
android:layout_width="150dp"
android:layout_height="150dp"
android:translationY="-150dp"
motion:layout_constraintLeft_toLeftOf="parent"
motion:layout_constraintRight_toRightOf="parent"
motion:layout_constraintTop_toTopOf="parent" />
<Constraint
android:id="@id/tv_message"
android:layout_width="match_parent"
android:layout_height="50dp"
motion:layout_constraintLeft_toLeftOf="parent"
motion:layout_constraintRight_toRightOf="parent"
motion:layout_constraintTop_toTopOf="parent" />
<Constraint
android:id="@id/nestedScroll"
android:layout_width="match_parent"
android:layout_height="0dp"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintTop_toBottomOf="@id/tv_message" />
</ConstraintSet>
</MotionScene>效果:

非常的簡(jiǎn)單,效果很流暢,性能也很好。有時(shí)候都不得不感慨一句,有了 MotionLayout 要你 Behavior 何用。
總結(jié)
Android真的是太卷了,以前學(xué)RxJava Dagger2 NestedScrolling Behavior 等,這些都是很難學(xué)的,更難以應(yīng)用,如果能學(xué)會(huì),那都是高工了。現(xiàn)在谷歌新框架層出不窮,越來(lái)越易用了,越來(lái)越好入門了。以前學(xué)的都已經(jīng)被淘汰,新入Android的同學(xué)已經(jīng)可以無(wú)需門檻,直接學(xué)谷歌的腳手架就能完成效果了。
言歸正傳,這幾種方案大家都理解了嗎?什么時(shí)候需要用協(xié)調(diào)滾動(dòng),什么時(shí)候需要用嵌套滾動(dòng),大家可以做到心中有數(shù)。能用 MotionLayout 的還是推薦使用 MotionLayout 實(shí)現(xiàn),畢竟實(shí)現(xiàn)簡(jiǎn)單,性能優(yōu)秀嘛!
當(dāng)然如果僅限這種效果來(lái)說(shuō),還有很多的方式實(shí)現(xiàn)如RV ListView,純粹的自定義View也能實(shí)現(xiàn)是吧,自定義ViewGroup,ViewDragHelper一樣能實(shí)現(xiàn),就是稍微麻煩點(diǎn),這里也僅從嵌套滾動(dòng)和協(xié)調(diào)滾動(dòng)這點(diǎn)來(lái)實(shí)現(xiàn)的。
好了,如果大家理解了協(xié)調(diào)滾動(dòng)和嵌套滾動(dòng),那萬(wàn)變不離其宗,幾乎應(yīng)用開發(fā)中全部的滾動(dòng)效果都是基于這兩條,內(nèi)部的具體實(shí)現(xiàn)方案幾乎都是基于這6種方案來(lái)實(shí)現(xiàn)。
后面如果大家有興趣,我會(huì)出一期超復(fù)雜的嵌套具體實(shí)現(xiàn)相關(guān)的功能,類似美團(tuán)外賣點(diǎn)餐的頁(yè)面分為上、中、下布局。下布局又分左右列表布局 ,還分上布局抽屜效果和中布局吸頂效果。
到此這篇關(guān)于Android嵌套滾動(dòng)與協(xié)調(diào)滾動(dòng)的幾種實(shí)現(xiàn)方式的文章就介紹到這了,更多相關(guān)Android嵌套滾動(dòng)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android實(shí)現(xiàn)底部導(dǎo)航欄的主界面
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)底部導(dǎo)航欄的主界面 ,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-09-09
Android MonoRepo多倉(cāng)和單倉(cāng)的差別理論
這篇文章主要為大家介紹了Android MonoRepo多倉(cāng)和單倉(cāng)的差別理論,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06
flutter BottomAppBar實(shí)現(xiàn)不規(guī)則底部導(dǎo)航欄
這篇文章主要為大家詳細(xì)介紹了flutter BottomAppBar實(shí)現(xiàn)不規(guī)則底部導(dǎo)航欄,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-07-07
Android簡(jiǎn)單實(shí)現(xiàn) 緩存數(shù)據(jù)
這篇文章主要介紹了Android簡(jiǎn)單實(shí)現(xiàn) 緩存數(shù)據(jù),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-11-11
android 仿微信demo——微信主界面實(shí)現(xiàn)
本系列文章主要介紹了微信小程序-閱讀小程序?qū)嵗╠emo),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧,希望能給你們提供幫助2021-06-06
Android中分析Jetpack?Compose動(dòng)畫內(nèi)部的實(shí)現(xiàn)原理
這篇文章主要介紹了Android中分析Jetpack?Compose動(dòng)畫內(nèi)部的實(shí)現(xiàn)原理,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,感興趣的小伙伴可以參考一下2022-09-09
完美解決Android三星手機(jī)從圖庫(kù)選擇照片旋轉(zhuǎn)問題
這篇文章主要幫助大家完美解決了Android三星手機(jī)從圖庫(kù)選擇照片旋轉(zhuǎn)問題,很實(shí)用的解決小案例,感興趣的小伙伴們可以參考一下2016-04-04

