多くのフラグメントの置換を制御する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);
}
}
サポートライブラリの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)。 ここ 提案された回避策を見つけることができます。
スクロールフラグメントコンテンツでネストされたスクロールを無効にします。
recyclerView.setNestedScrollingEnabled(false);
サポートライブラリを使用している場合は、これを使用します。
ViewCompat.setNestedScrollingEnabled(recyclerView, false);
このクラスを使用すると、展開動作を無効化/再有効化できます。
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);
必要なのは、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タグを使用しないでください。それは動作しません
Android Design Library v23.1.1では、@ LucyFairで記述されているメソッドは機能しません。app:layout_scrollFlags
からenterAlwaysCollapsed
のみで、アプリバーは「ロック」されたままです。
お役に立てれば。 :)
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);
}
@ JasonWyattのソリューションを使用し、DragCallback
を動作クラスに追加して、タッチとドラッグを防止してCollapsingToolbarLayout
を展開しました
private void setDragCallback() {
setDragCallback(new DragCallback() {
@Override
public boolean canDrag(@NonNull AppBarLayout appBarLayout) {
return mEnabled;
}
});
}
アクティビティとさまざまなフラグメントで動作する回避策を見つけました。 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はツールバーを標準サイズに縮小し、再び拡大しないようにします
それがあなたを助けることを願っています!
私はコメントできないので、 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
これを除いて、提供されたソリューションはどれもうまくいきませんでした。このソリューションを使用すると、折りたたみツールバーの状態を簡単に管理できます。これにより、折りたたみツールバーの拡大を防ぎ、タイトルを設定します。
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);
}
}
このようにAppBarLayout idを見つけます。
appBarLayout = (AppBarLayout) findViewById(R.id.appbar);
特定のフラグメントのCollapsingToolbarLayoutの展開を無効にします
appBarLayout.setExpanded(true,true);
特定のフラグメントのCollapsingToolbarLayoutで展開を有効にします
appBarLayout.setExpanded(false,true);
それがあなたを助けることを願っています!!
折りたたみツールバーの高さをツールバーの高さにリセットすることにより、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 */);
}
次のコードは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
}
})