web-dev-qa-db-ja.com

ツールバーの展開と折りたたみAndroid

ツールバーの折りたたみの助けを借りて、ツールバーの展開と折りたたみを実装していますが、ツールバーが折りたたまれているときに行き詰まり、別のツールバーを表示したいと思います。私はそのようなコードの断片を見てきましたが、私の解決策を見つけることができません。私は素晴らしい開発者の一人の解決策も見ました https://github.com/saulmm/CoordinatorLayoutExample 私の解決策を適切に見つけることができません

enter image description here

これは私が実装した私のコードです

activity_collapsing_toolbar.xml

<?xml version="1.0" encoding="utf-8"?>
<Android.support.design.widget.CoordinatorLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:app="http://schemas.Android.com/apk/res-auto"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent">

    <Android.support.design.widget.AppBarLayout
        Android:id="@+id/app_bar_layout"
        Android:layout_width="match_parent"
        Android:layout_height="176dp"
        Android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <Android.support.design.widget.CollapsingToolbarLayout
            Android:id="@+id/collapsing_toolbar"
            Android:layout_width="match_parent"
            Android:layout_height="match_parent"
            app:contentScrim="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">


            <RelativeLayout
                Android:layout_width="match_parent"
                Android:layout_height="match_parent"
                Android:layout_gravity="center"
                Android:background="@color/base_color_theme_new"
                Android:gravity="center_horizontal"
                app:layout_collapseMode="parallax">

                <RelativeLayout
                    Android:id="@+id/rl_class_image"
                    Android:layout_width="match_parent"
                    Android:layout_height="wrap_content"
                    Android:layout_marginTop="26dp"
                    Android:gravity="center">

                    <LinearLayout
                        Android:id="@+id/ll_class"
                        Android:layout_width="60dp"
                        Android:layout_height="60dp"
                        Android:background="@drawable/rounded_white_circle"
                        Android:gravity="center">

                        <ImageView
                            Android:id="@+id/iv_class_image"
                            Android:layout_width="60dp"
                            Android:layout_height="60dp"
                            Android:layout_gravity="center"
                            Android:padding="8dp"
                            Android:src="@drawable/class_4" />
                    </LinearLayout>
                </RelativeLayout>


                <TextView
                    Android:id="@+id/tv_class_name"
                    Android:layout_width="match_parent"
                    Android:layout_height="wrap_content"
                    Android:layout_below="@id/rl_class_image"
                    Android:layout_marginTop="15dp"
                    Android:gravity="center"
                    Android:text="MATHEMATICS"
                    Android:textSize="17sp" />

                <TextView
                    Android:id="@+id/tv_videos_test"
                    Android:layout_width="match_parent"
                    Android:layout_height="wrap_content"
                    Android:layout_below="@id/tv_class_name"
                    Android:layout_marginTop="10dp"
                    Android:gravity="center"
                    Android:text="20 VIDEOS | 5 TESTS"
                    Android:textSize="10sp" />


            </RelativeLayout>

            <Android.support.v7.widget.Toolbar
                Android:id="@+id/toolbar"
                Android:layout_width="match_parent"
                Android:layout_height="?attr/actionBarSize"
                app:layout_collapseMode="pin" />

        </Android.support.design.widget.CollapsingToolbarLayout>

    </Android.support.design.widget.AppBarLayout>

    <Android.support.v4.widget.NestedScrollView
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:layout_marginLeft="10dp"
        Android:layout_marginRight="10dp"
        Android:background="@drawable/rounded_corners_for_list"
        Android:fillViewport="true"

        app:behavior_overlapTop="10dp"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">


        <!--<include layout="@layout/activity_chapters" />-->
        <com.chalklit.widget.NonScrollListView
            Android:id="@+id/lv_modules_list"
            Android:layout_width="match_parent"
            Android:layout_height="match_parent"
            Android:background="@Android:color/white"
            Android:divider="@null"
            Android:scrollbars="none"></com.chalklit.widget.NonScrollListView>


    </Android.support.v4.widget.NestedScrollView>

</Android.support.design.widget.CoordinatorLayout>

CollapsingToolbarActivity.Java

private CollapsingToolbarLayout collapsingToolbarLayout = null;
protected void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_NO_TITLE);


    setContentView(R.layout.activity_collapsing_toolbar);

    final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    toolbar.inflateMenu(R.menu.menu_main);

    setSupportActionBar(toolbar);
    ActionBar actionBar = getSupportActionBar();
    actionBar.setDisplayHomeAsUpEnabled(true);

    collapsingToolbarLayout = (CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar);
    collapsingToolbarLayout.setTitle(" ");
    collapsingToolbarLayout.setContentScrimColor(getResources().getColor(R.color.base_color_theme_new));
    collapsingToolbarLayout.setStatusBarScrimColor(getResources().getColor(R.color.base_color_theme_new));
}
8
Shubham Chauhan

カスタムCoordinatorLayoutBehaviorを使用しない別のアプローチを次に示します。

OnOffsetChangedListenerからのAppBarLayoutを使用します。

これがスニペットです:

class OnOffsetChangedListener implements AppBarLayout.OnOffsetChangedListener {

        @Override
        public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {

            final int scrollRange = appBarLayout.getTotalScrollRange();
            float offsetFactor = (float) (-verticalOffset) / (float) scrollRange;
            ...

これは、総スクロール範囲を見つける方法と、総スクロール範囲と現在のスクロール位置の比率を見つける方法を示しています。これは、ツールバーのビューを拡大縮小して配置する方法を理解するために必要なものです。

(私がしたように)カスタムレイアウトの場合、onAttachedToWindowをオーバーライドして、そこにリスナーを追加できます。

        // Add an OnOffsetChangedListener if possible
        final ViewParent parent = getParent();
        if (parent instanceof AppBarLayout) {
            if (mOnOffsetChangedListener == null) {
                mOnOffsetChangedListener = new OnOffsetChangedListener();
            }
            ((AppBarLayout) parent).addOnOffsetChangedListener(mOnOffsetChangedListener);
        }

このアプローチは、カスタム動作を作成するよりも少し単純であることがわかりました。

GitHubでサンプルプロジェクトを作成しました。アプリは次のようになります。

App screenshots

https://github.com/klarson2/Collapsing-Image でプロジェクト全体を見ることができます

8
kris larson

私は、カスタムCoordinatorLayoutBehaviorを使用しないアプローチで2つのamaizingアバターの折りたたみデモサンプルを先読みしました。

サンプルのネイティブコードを表示するには: "Collapsing Avatar Toolbar Sample"

私の "Animation Collapsing Toolbar Android" の投稿をメディアに投稿するには、.


デモ1enter image description hereデモ2enter image description here


カスタムCoordinatorLayoutBehaviorを使用する代わりに、OnOffsetChangedListenerから取得したAppBarLayoutを使用します。

private lateinit var appBarLayout: AppBarLayout

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_demo_1)
        ...
        appBarLayout = findViewById(R.id.app_bar_layout)

        /**/
        appBarLayout.addOnOffsetChangedListener(
                AppBarLayout.OnOffsetChangedListener { appBarLayout, i ->
                   ...
                    /**/
                    updateViews(Math.abs(i / appBarLayout.totalScrollRange.toFloat()))
                })
    }

デモ1

enter image description here


updateViewsメソッドで、アバターはサイズを変更し、最初のデモでアバターのX、Y位置の変換を変更します。

private fun updateViews(offset: Float) {

        ...

        /* Collapse avatar img*/
        ivUserAvatar.apply {
            when {
                offset > avatarAnimateStartPointY -> {
                    val avatarCollapseAnimateOffset = (offset - avatarAnimateStartPointY) * avatarCollapseAnimationChangeWeight
                    val avatarSize = EXPAND_AVATAR_SIZE - (EXPAND_AVATAR_SIZE - COLLAPSE_IMAGE_SIZE) * avatarCollapseAnimateOffset
                    this.layoutParams.also {
                        it.height = Math.round(avatarSize)
                        it.width = Math.round(avatarSize)
                    }
                    invisibleTextViewWorkAround.setTextSize(TypedValue.COMPLEX_UNIT_PX, offset)

                    this.translationX = ((appBarLayout.width - horizontalToolbarAvatarMargin - avatarSize) / 2) * avatarCollapseAnimateOffset
                    this.translationY = ((toolbar.height  - verticalToolbarAvatarMargin - avatarSize ) / 2) * avatarCollapseAnimateOffset
                }
                else -> this.layoutParams.also {
                    if (it.height != EXPAND_AVATAR_SIZE.toInt()) {
                        it.height = EXPAND_AVATAR_SIZE.toInt()
                        it.width = EXPAND_AVATAR_SIZE.toInt()
                        this.layoutParams = it
                    }
                    translationX = 0f
                }
            }
        }
    }

avatarAnimateStartPointYavatarCollapseAnimationChangeWeightを見つけるには(一般的なオフセットをアバターアニメーションオフセットに変換するため):

private var avatarAnimateStartPointY: Float = 0F
 private var avatarCollapseAnimationChangeWeight: Float = 0F
 private var isCalculated = false
 private var verticalToolbarAvatarMargin =0F
...
if (isCalculated.not()) {
    avatarAnimateStartPointY = 
                 Math.abs((appBarLayout.height - (EXPAND_AVATAR_SIZE + horizontalToolbarAvatarMargin)) / appBarLayout.totalScrollRange)

    avatarCollapseAnimationChangeWeight = 1 / (1 - avatarAnimateStartPointY)

    verticalToolbarAvatarMargin = (toolbar.height - COLLAPSE_IMAGE_SIZE) * 2
    isCalculated = true
 }

デモ2

enter image description here


アバターは彼のサイズを変更し、アニメーション化すると同時に、上部のツールバーのテキストが表示されるようになり、左に移動するようになりました。

状態を追跡する必要があります:TO_EXPANDED_STATE変更中、TO_COLLAPSED_STATE変更中、WAIT_FOR_SWITCH

 /*Collapsed/expended sizes for views*/
            val result: Pair<Int, Int> = when {
                percentOffset < ABROAD -> {
                    Pair(TO_EXPANDED_STATE, cashCollapseState?.second ?: WAIT_FOR_SWITCH)
                }
                else -> {
                    Pair(TO_COLLAPSED_STATE, cashCollapseState?.second ?: WAIT_FOR_SWITCH)
                }
            }

状態切り替え時のアバターのアニメーションを作成します。

   result.apply {
        var translationY = 0f
        var headContainerHeight = 0f
        val translationX: Float
        var currentImageSize = 0
        when {
            cashCollapseState != null && cashCollapseState != this -> {
                when (first) {
                    TO_EXPANDED_STATE -> {
                        translationY = toolbar.height.toFloat()
                        headContainerHeight = appBarLayout.totalScrollRange.toFloat()
                        currentImageSize = EXPAND_AVATAR_SIZE.toInt()
                        /**/
                        titleToolbarText.visibility = View.VISIBLE
                        titleToolbarTextSingle.visibility = View.INVISIBLE
                        background.setBackgroundColor(ContextCompat.getColor(this@Demo2Activity, R.color.color_transparent))
                        /**/
                        ivAvatar.translationX = 0f
                    }

                    TO_COLLAPSED_STATE -> {
                        background.setBackgroundColor(ContextCompat.getColor(this@Demo2Activity, R.color.colorPrimary))
                        currentImageSize = COLLAPSE_IMAGE_SIZE.toInt()
                        translationY = appBarLayout.totalScrollRange.toFloat() - (toolbar.height - COLLAPSE_IMAGE_SIZE) / 2
                        headContainerHeight = toolbar.height.toFloat()
                        translationX = appBarLayout.width / 2f - COLLAPSE_IMAGE_SIZE / 2 - margin * 2
                        /**/
                        ValueAnimator.ofFloat(ivAvatar.translationX, translationX).apply {
                            addUpdateListener {
                                if (cashCollapseState!!.first == TO_COLLAPSED_STATE) {
                                    ivAvatar.translationX = it.animatedValue as Float
                                }
                            }
                            interpolator = AnticipateOvershootInterpolator()
                            startDelay = 69
                            duration = 350
                            start()
                        }
                       ...
                    }
                }

                ivAvatar.apply {
                    layoutParams.height = currentImageSize
                    layoutParams.width = currentImageSize
                }
                collapsingAvatarContainer.apply {
                    layoutParams.height = headContainerHeight.toInt()
                    this.translationY = translationY
                    requestLayout()
                }
                /**/
                cashCollapseState = Pair(first, SWITCHED)
            }

サンプルのネイティブコードを表示するには: "Collapsing Avatar Toolbar Sample"

4
Serg Burlaka

これを実現するには、CoordinatorLayout.Behaviorを使用してカスタム動作を作成する必要があります

子と依存関係の2つのコア要素を考慮します。

子は、子要素と対話するトリガーとして機能する動作、依存関係を強化するビューです。あなたの要件では、子はImageViewであり、依存関係はツールバーです。そのようにして、ツールバーが移動すると、ImageViewも移動します。

カスタム動作ツールバーのデモについては、以下のリンクをいくつか確認してください

2
Patrick R