web-dev-qa-db-ja.com

特定のフラグメントのCollapsingToolbarLayoutで展開を無効にする必要があります

多くのフラグメントの置換を制御するAppCompatActivityがあります。これが私のレイアウトです。

activity_main.xml

<Android.support.v4.widget.DrawerLayout
xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:app="http://schemas.Android.com/apk/res-auto"
Android:id="@+id/drawer_layout"
Android:layout_height="match_parent"
Android:layout_width="match_parent"
Android:fitsSystemWindows="true">

<include layout="@layout/activity_main_frame"/>

<Android.support.design.widget.NavigationView
    Android:id="@+id/navigation_view"
    Android:layout_width="wrap_content"
    Android:layout_height="match_parent"
    Android:layout_gravity="start"
    Android:fitsSystemWindows="true"
    Android:background="@color/white"
    app:headerLayout="@layout/drawer_header"
    app:menu="@menu/drawer"/>

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

activity_main_frame.xml

<Android.support.design.widget.CoordinatorLayout
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:app="http://schemas.Android.com/apk/res-auto"
    Android:id="@+id/main_content"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:fitsSystemWindows="true">

    <Android.support.design.widget.AppBarLayout
        Android:id="@+id/appbar"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        Android:fitsSystemWindows="true">

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

            <ImageView
                Android:id="@+id/backdrop"
                Android:layout_width="match_parent"
                Android:layout_height="256dp"
                Android:scaleType="centerCrop"
                Android:fitsSystemWindows="true"
                app:layout_collapseMode="parallax" />

            <include layout="@layout/activity_main_items"/>

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

            <Android.support.design.widget.TabLayout
                Android:id="@+id/tabs"
                Android:layout_width="match_parent"
                Android:layout_height="wrap_content"
                Android:visibility="gone"
                Android:layout_gravity="bottom"/>

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

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

    <FrameLayout
        Android:id="@+id/content_frame"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" >
    </FrameLayout>

    <Android.support.design.widget.FloatingActionButton
        Android:id="@+id/fab1"
        Android:layout_height="wrap_content"
        Android:layout_width="wrap_content"
        app:layout_anchor="@id/appbar"
        app:layout_anchorGravity="bottom|right|end"
        app:borderWidth="0dp"
        Android:src="@drawable/app_ic_slide_wallpaper_dark"
        Android:layout_margin="@dimen/big_padding"
        Android:clickable="true"/>

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

私のホームフラグメントは最初に設定され、それが折りたたみツールバーを展開したい場所であり、それはうまく機能します。ただし、サイドドロワーからフラグメントを変更するときは、展開ツールバーを無効にします。

引き出し項目が選択されたときに折りたたむ方法を考え出しましたが、ホームフラグメントが表示されない限り展開しないことも確認する必要があります。これは可能ですか?

public void collapseToolbar(){
        CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) appbar.getLayoutParams();
        behavior = (AppBarLayout.Behavior) params.getBehavior();
        if(behavior!=null) {
            behavior.onNestedFling(coordinator, appbar, null, 0, 10000, true);
        }
    }
51
Bignadad

サポートライブラリのv23では、アプリバーの表示を簡単に制御できます。

AppBarLayoutへの参照を取得し、ロードするフラグメントに応じて非表示/表示するだけです。

private AppBarLayout appBarLayout;

@Override
protected void onCreate(Bundle savedInstanceState) {
[...]
appBarLayout = (AppBarLayout) findViewById(R.id.appbar);
[...]
}

public void switchToFragment(Fragment fragment, String tag, boolean expandToolbar){
        FragmentManager fragmentManager = getSupportFragmentManager();

        Fragment currentFragment = fragmentManager.findFragmentByTag(currentFragmentTag);

        if(currentFragment == null || !TextUtils.equals(tag, currentFragmentTag) ){
            currentFragmentTag = tag;
            fragmentManager
                    .beginTransaction()
                    .replace(R.id.flContent, fragment, currentFragmentTag)
                    .commit();

            if(expandToolbar){
                appBarLayout.setExpanded(true,true);
            }else{
                appBarLayout.setExpanded(false,true);
            }
        }
    }

追伸build.gradleに必要な依存関係を追加することを忘れないでください:

dependencies {  
    compile 'com.Android.support:design:23.2.1'
    compile 'com.Android.support:appcompat-v7:23.2.1'
    compile 'com.Android.support:recyclerview-v7:23.2.1' 
}

EDIT:特定のフラグメントでツールバーをロックしたい場合(折りたたみ以外)、この機能はCollapsingToolbarLayoutによって提供されないため、回避策に頼らなければなりませんこれまで(サポートデザインのv23.2.1)。 ここ 提案された回避策を見つけることができます。

18
Sevle

スクロールフラグメントコンテンツでネストされたスクロールを無効にします。

recyclerView.setNestedScrollingEnabled(false);

サポートライブラリを使用している場合は、これを使用します。

ViewCompat.setNestedScrollingEnabled(recyclerView, false);
60
tachyonflux

このクラスを使用すると、展開動作を無効化/再有効化できます。

public class DisableableAppBarLayoutBehavior extends AppBarLayout.Behavior {
    private boolean mEnabled;

    public DisableableAppBarLayoutBehavior() {
        super();
    }

    public DisableableAppBarLayoutBehavior(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public void setEnabled(boolean enabled) {
        mEnabled = enabled;
    }

    @Override
    public boolean onStartNestedScroll(CoordinatorLayout parent, AppBarLayout child, View directTargetChild, View target, int nestedScrollAxes) {
        return mEnabled && super.onStartNestedScroll(parent, child, directTargetChild, target, nestedScrollAxes);
    }

    public boolean isEnabled() {
        return mEnabled;
    }
}

レイアウトで次のように使用します。

<Android.support.design.widget.AppBarLayout
    ... other attributes ...
    app:layout_behavior="com.yourpackage.DisableableAppBarLayoutBehavior"
    >
    <!-- your app bar contents -->
</Android.support.design.widget.AppBarLayout>

次に、動作を無効にする場合:

AppBarLayout myAppBar = ....;
CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) myAppBar.getLayoutParams();
((DisableableAppBarLayoutBehavior) layoutParams.getBehavior()).setEnabled(false);
33
JasonWyatt

必要なのは、CoordinatorLayoutをConestinLayoutのカスタム実装に置き換えることです。これにより、ネストされたスクロールが処理されたことをごまかすことができます。

MyCoordinatorLayoutの実装:

public class MyCoordinatorLayout extends CoordinatorLayout {

    private boolean allowForScroll = false;

    public MyCoordinatorLayout(Context context) {
        super(context);
    }

    public MyCoordinatorLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) {
        return allowForScroll && super.onStartNestedScroll(child, target, nestedScrollAxes);
    }

    public boolean isAllowForScroll() {
        return allowForScroll;
    }

    public void setAllowForScroll(boolean allowForScroll) {
        this.allowForScroll = allowForScroll;
    }
}

アクティビティビューxml:

<LinearLayout
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:tools="http://schemas.Android.com/tools"
    xmlns:app="http://schemas.Android.com/apk/res-auto"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:orientation="vertical"
    >

    <Android.support.v4.widget.DrawerLayout
        Android:id="@+id/drawerLayout"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        >

        <!--CONTENT-->

        <com.example.views.MyCoordinatorLayout
            Android:id="@+id/coordinator"
            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:fitsSystemWindows="true"
            >

        <com.example.views.ControllableAppBarLayout
            Android:id="@+id/appbar"
            Android:layout_width="match_parent"
            Android:layout_height="192dp"
            Android:fitsSystemWindows="true"
            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"
                Android:fitsSystemWindows="true"
                app:contentScrim="?attr/colorPrimary"
                app:expandedTitleMarginBottom="32dp"
                app:expandedTitleMarginEnd="64dp"
                app:expandedTitleMarginStart="48dp"
                app:layout_scrollFlags="scroll|exitUntilCollapsed">

                <ImageView
                    Android:id="@+id/header"
                    Android:layout_width="match_parent"
                    Android:layout_height="match_parent"
                    Android:background="@color/primary"
                    Android:fitsSystemWindows="true"
                    Android:scaleType="centerCrop"
                    app:layout_collapseMode="parallax" />

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

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

        </com.example.views.ControllableAppBarLayout>

        <FrameLayout
            Android:id="@+id/flContent"
            Android:layout_width="match_parent"
            Android:layout_height="match_parent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior"
            />

        </com.example.views.MyCoordinatorLayout>


        <!-- DRAWER -->

        <fragment
            Android:id="@+id/fDrawer"
            Android:name="com.example.fragment.DrawerFragment"
            Android:layout_width="@dimen/drawer_width"
            Android:layout_height="match_parent"
            Android:layout_gravity="left|start"
            Android:fitsSystemWindows="true"
            Android:clickable="true"
            />

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

</LinearLayout>

カスタムAppBarLayout実装とヘルパーメソッドを使用して、ツールバーを折りたたみ/展開することをお勧めします。これで Gist が見つかります。

さて、今度はアクティビティでツールバーを設定します。

public class ToolbarAppcompatActivity extends AppCompatActivity
        implements AppBarLayout.OnOffsetChangedListener {

    protected Toolbar toolbar;
    protected MyCoordinatorLayout coordinator;
    protected ControllableAppBarLayout appbar;

    @Override protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        configureToolbar();
    switchFragment(new FooFragment(), "FOO", true);
    }

    protected void configureToolbar() {
        toolbar = (Toolbar) findViewById(R.id.toolbar);
        coordinator = (MyCoordinatorLayout) findViewById(R.id.coordinator);
        appbar = (ControllableAppBarLayout) findViewById(R.id.appbar);
        appbar.addOnOffsetChangedListener(this);
        getDelegate().setSupportActionBar(toolbar);
    }

    public void switchToFragment(Fragment fragment, String tag, boolean expandToolbar){
        FragmentManager fragmentManager = getSupportFragmentManager();

        Fragment currentFragment = fragmentManager.findFragmentByTag(currentFragmentTag);

        if(currentFragment == null || !TextUtils.equals(tag, currentFragmentTag) ){
            currentFragmentTag = tag;
            fragmentManager
                    .beginTransaction()
                    .replace(R.id.flContent, fragment, currentFragmentTag)
                    .commit();

            if(expandToolbar){
                expandToolbar();
            }else{
                collapseToolbar();
            }
        }
    }

    protected void addFragment(Fragment fragment, String tag, boolean expandToolbar) {
        FragmentManager fragmentManager = getSupportFragmentManager();
        currentFragmentTag = tag;
        fragmentManager
                .beginTransaction()
                .add(R.id.flContent, fragment, currentFragmentTag)
                .addToBackStack(tag)
                .commit();

        if(expandToolbar){
            expandToolbar();
        }else{
            collapseToolbar();
        }
    }

   protected void collapseToolbar(){
        appbar.collapseToolbar();
        coordinator.setAllowForScroll(false);
    }

    public void expandToolbar(){
        appbar.expandToolbar();
        coordinator.setAllowForScroll(true);
    }

}

フラグメントを切り替えてツールバーを折りたたむ/展開するたびに、適切なブール値パラメーターを使用してメソッドswitchFragment/addFragmentを呼び出すだけです。

最後のメモです。必ず最新のサポートライブラリを使用してください。

dependencies {

    // Android support
    compile 'com.Android.support:appcompat-v7:22.2.1'
    compile 'com.Android.support:recyclerview-v7:22.2.1'
    compile 'com.Android.support:design:22.2.1'

}

AppBarLayoutでincludeタグを使用しないでください。それは動作しません

11
Lucy Fair

Android Design Library v23.1.1では、@ LucyFairで記述されているメソッドは機能しません。app:layout_scrollFlagsからenterAlwaysCollapsedのみで、アプリバーは「ロック」されたままです。

お役に立てれば。 :)

5
StrangeCode

CollapsingToolbarLayoutで折りたたみを有効/無効にする簡単なソリューションを見つけました。

    private void setExpandEnabled(boolean enabled) {
        mAppBarLayout.setExpanded(enabled, false);
        mAppBarLayout.setActivated(enabled);
        final AppBarLayout.LayoutParams params = (AppBarLayout.LayoutParams) collapsingToolbarLayout.getLayoutParams();
        if (enabled)
            params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_EXIT_UNTIL_COLLAPSED);
        else
            params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS | AppBarLayout.LayoutParams.SCROLL_FLAG_EXIT_UNTIL_COLLAPSED);
        collapsingToolbarLayout.setLayoutParams(params);
    }
4
Dmitry Velychko

@ JasonWyattのソリューションを使用し、DragCallbackを動作クラスに追加して、タッチとドラッグを防止してCollapsingToolbarLayoutを展開しました

private void setDragCallback() {
    setDragCallback(new DragCallback() {
        @Override
        public boolean canDrag(@NonNull AppBarLayout appBarLayout) {
            return mEnabled;
        }
    });
}
3
Duev S.

アクティビティとさまざまなフラグメントで動作する回避策を見つけました。 CollapsingToolbarLayoutをAppBarなどでアクティビティに実装すると、新しいフラグメントを呼び出すたびに、これら2つの関数を呼び出すことができます。

  • アプリバーを折りたたんでおく場合:

    public void lockAppBarClosed() {
        mAppBarLayout.setExpanded(false, false);
        mAppBarLayout.setActivated(false);
        CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams)mAppBarLayout.getLayoutParams();
        lp.height = (int) getResources().getDimension(R.dimen.toolbar_height);
    }
    
  • アプリバーを再度展開してスクロール可能にする場合

    public void unlockAppBarOpen() {
        mAppBarLayout.setExpanded(true, false);
        mAppBarLayout.setActivated(true);
        CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams)mAppBarLayout.getLayoutParams();
        lp.height = (int) getResources().getDimension(R.dimen.toolbar_expand_height);
    }
    

インターフェイスを実装することで、フラグメントからそれらの関数を呼び出すことができます。あなたの場合の簡単な例です(ツールバーはhomeFragmentでのみ展開します)

public interface CustomListener() {
    void unlockAppBarOpen();
    void lockAppBarClosed()
}

public class MainActivity extends BaseActivity implements CustomListener {

    @Override
    public void unlockAppBarOpen() {
        mAppBarLayout.setExpanded(true, false);
        mAppBarLayout.setActivated(true);
        CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams)mAppBarLayout.getLayoutParams();
        lp.height = (int) getResources().getDimension(R.dimen.toolbar_expand_height);
    }

    @Override
    public void lockAppBarClosed() {
        mAppBarLayout.setExpanded(false, false);
        mAppBarLayout.setActivated(false);
        CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams)mAppBarLayout.getLayoutParams();
        lp.height = (int) getResources().getDimension(R.dimen.toolbar_height);
    }
}

public class MainFragment extends BaseFragment {

    @Override
    public void onResume() {
        super.onPause();
        ((MainActivity) getContext()).unlockAppBarOpen();
    }
}

public class SecondFragment extends BaseFragment {

    @Override
    public void onResume() {
        super.onPause();
        ((MainActivity) getContext()).lockAppBarClosed();
    }
}

この例では:

  • mainFragmentが表示されるたびに->ツールバーを拡張し、折りたたみ可能および展開可能にします

  • secondFragmentが表示されるたびに-> ilはツールバーを標準サイズに縮小し、再び拡大しないようにします

それがあなたを助けることを願っています!

3
Anne-Claire

私はコメントできないので、 JasonWyatt's DisableableAppBarLayoutBehaviorソリューションへの追加を独立した回答として投稿します。

public class DisableableAppBarLayoutBehavior extends AppBarLayout.Behavior {
    private boolean mEnabled = true; // enabled by default

    public DisableableAppBarLayoutBehavior() {
        super();
    }

    public DisableableAppBarLayoutBehavior(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public void setEnabled(boolean enabled) {
        mEnabled = enabled;
    }

    @Override
    public boolean onStartNestedScroll(CoordinatorLayout parent, AppBarLayout child, View directTargetChild, View target, int nestedScrollAxes, int type) {
        return mEnabled && super.onStartNestedScroll(parent, child, directTargetChild, target, nestedScrollAxes, type);
    }

    @Override
    public void onNestedScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int type) {
        if (!isEnabled()) return;
        super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, type);
    }

    @Override
    public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, int dx, int dy, int[] consumed, int type) {
        if (!isEnabled()) return;
        super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed, type);
    }

    public boolean isEnabled() {
        return mEnabled;
    }
}

OnStartNestedScrollに加えて、onNestedPreScrollおよびonNestedScroll自体もロックして、予期しない動作を回避します。たとえば、私の場合-アプリバーでsetExpanded(false、true)を呼び出すと、予想される動作が妨げられ、ラグで拡大していました。今では動作します:

LayoutParams layoutParams = (LayoutParams) context.appBarLayout.getLayoutParams();
((DisableableAppBarLayoutBehavior)layoutParams.getBehavior()).setEnabled(false);
context.appBarLayout.setLayoutParams(layoutParams);
context.appBarLayout.setExpanded(false, true); // collapse app bar
1
ekar

これを除いて、提供されたソリューションはどれもうまくいきませんでした。このソリューションを使用すると、折りたたみツールバーの状態を簡単に管理できます。これにより、折りたたみツールバーの拡大を防ぎ、タイトルを設定します。

public void lockAppBar(boolean locked,String title) {
    if(locked){
        appBarLayout.setExpanded(false, true);
        int px = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 80, getResources().getDisplayMetrics());
        CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams)appBarLayout.getLayoutParams();
        lp.height = px;
        appBarLayout.setLayoutParams(lp);
        collapsingToolbarLayout.setTitleEnabled(false);
        toolbar.setTitle(title);
    }else{
        appBarLayout.setExpanded(true, false);
        appBarLayout.setActivated(true);
        CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams();
        lp.height = (int) getResources().getDimension(R.dimen.toolbarExpandHeight);
        collapsingToolbarLayout.setTitleEnabled(true);
        collapsingToolbarLayout.setTitle(title);
    }
}
0
Kemal

このようにAppBarLayout idを見つけます。

appBarLayout = (AppBarLayout) findViewById(R.id.appbar);

特定のフラグメントのCollapsingToolbarLayoutの展開を無効にします

appBarLayout.setExpanded(true,true);

特定のフラグメントのCollapsingToolbarLayoutで展開を有効にします

appBarLayout.setExpanded(false,true);

それがあなたを助けることを願っています!!

0

折りたたみツールバーの高さをツールバーの高さにリセットすることにより、appbarlayoutの展開をロックできます

toolbarHeight = toolbar.getLayoutParams().height;

if (expand) {
    collapsingToolbar.getLayoutParams().height = getResources().getDimensionPixelOffset(R.dimen.collapsingToolbarDefaultHeight);
    appBarLayout.setExpanded(true, true);
} else {
    //collapse
    //** it is important you do this before resetting **
    appBarLayout.setExpanded(false, true);
    appBarLayout.postDelayed(new Runnable() {
        @Override
        public void run() {
            collapsingToolbar.getLayoutParams().height = toolbarHeight;
        }
     }, 700/* 600 is default animation time to collapse */);
}
0
Pushan

次のコードは3つの目的を達成します。

ユーザーによるCollapsingToolbarLayoutの展開または折りたたみを無効にしますが、AppBarLayout.setExpanded

RecyclerViewまたはNestedScrollViewのスクロールがCollapsingToolbarLayoutを拡大または縮小しないようにします。

// scrollView can be RecyclerView or NestedScrollView
ViewCompat.setNestedScrollingEnabled(scrollView, false)

AppBarをフリックして、ユーザーがCollapsingToolbarLayoutを展開または折りたたみできないようにします。

val params = appBar.layoutParams as CoordinatorLayout.LayoutParams
if (params.behavior == null)
    params.behavior = AppBarLayout.Behavior()
val behaviour = params.behavior as AppBarLayout.Behavior
behaviour.setDragCallback(object : AppBarLayout.Behavior.DragCallback() {
    override fun canDrag(appBarLayout: AppBarLayout): Boolean {
        return false
    }
})

https://code.luasoftware.com/tutorials/Android/how-to-disable-or-lock-collapsingtoolbarlayout-collapse-or-expand/

0
Desmond Lua