如何模仿Google Maps的底页3个阶段的行为? [英] How to mimic Google Maps' bottom-sheet 3 phases behavior?

本文介绍了如何模仿Google Maps的底页3个阶段的行为?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我受命制作一个行为类似于Google Maps显示找到结果的底页的UI.

I'm assigned to make a UI that behaves similar to how Google Maps shows a bottom-sheet for a found result.

它具有三个不同的阶段:

It has three different phases:

  1. 底部内容.上方区域仍可触摸,底部不会滚动任何内容
  2. 全屏内容,而上部区域具有较大的标题.
  3. 全屏内容,而上方区域只有工具栏.

这就是我在Google Maps上谈论的内容:

Here's what I'm talking about on Google Maps:

事实是,底页还不是设计库的一部分(尽管有人要求,但

Thing is, the bottom sheet isn't a part of the design library yet (though it was requested, here).

不仅如此,UI看起来也非常复杂,需要在多个阶段对工具栏进行处理.

Not only that, but the UI seems quite complex and need handling of the toolbar on multiple phases.

我为底页找到了一个很好的库(足够)( 此处 ),并将内容添加到其片段样本中,以具有与材料设计样本中所示的大致相同的视图(例如 此处 ),以拥有一个CollapsingToolbarLayout来处理2 + 3阶段.

I've found a good (enough) library for bottom sheet (here), and added content to its fragment sample, to have about the same views as shown on material design samples (like here), to have a CollapsingToolbarLayout that will take care of phases 2+3.

在我制作的应用中,滚动时我还必须移动一个图标,但是我认为,如果我成功完成了其余的工作,这应该很容易. 这是代码:

In the app I'm making, I also have to move an icon as you scroll, but I think that if I succeed with the rest, this should be easy. Here's the code:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    android:id="@+id/main_content"
    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/appbar"
        android:layout_width="match_parent"
        android:layout_height="@dimen/detail_backdrop_height"

        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:expandedTitleMarginEnd="64dp"
            app:expandedTitleMarginStart="48dp"
            app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">

            <ImageView
                android:id="@+id/backdrop"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                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>
    </android.support.design.widget.AppBarLayout>

    <android.support.v4.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            android:paddingTop="24dp">

            <android.support.v7.widget.CardView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/card_margin">

                <LinearLayout
                    style="@style/Widget.CardContent"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content">

                    <TextView
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:text="Info"
                        android:textAppearance="@style/TextAppearance.AppCompat.Title"/>

                    <TextView
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:text="@string/cheese_ipsum"/>
                </LinearLayout>
            </android.support.v7.widget.CardView>

            <android.support.v7.widget.CardView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginBottom="@dimen/card_margin"
                android:layout_marginLeft="@dimen/card_margin"
                android:layout_marginRight="@dimen/card_margin">

                <LinearLayout
                    style="@style/Widget.CardContent"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content">

                    <TextView
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:text="Friends"
                        android:textAppearance="@style/TextAppearance.AppCompat.Title"/>

                    <TextView
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:text="@string/cheese_ipsum"/>
                </LinearLayout>
            </android.support.v7.widget.CardView>

            <android.support.v7.widget.CardView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginBottom="@dimen/card_margin"
                android:layout_marginLeft="@dimen/card_margin"
                android:layout_marginRight="@dimen/card_margin">

                <LinearLayout
                    style="@style/Widget.CardContent"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content">

                    <TextView
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:text="Related"
                        android:textAppearance="@style/TextAppearance.AppCompat.Title"/>

                    <TextView
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:text="@string/cheese_ipsum"/>
                </LinearLayout>
            </android.support.v7.widget.CardView>
        </LinearLayout>
    </android.support.v4.widget.NestedScrollView>

    <android.support.design.widget.FloatingActionButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/fab_margin"
        android:clickable="true"
        android:src="@android:drawable/ic_menu_send"
        app:layout_anchor="@id/appbar"
        app:layout_anchorGravity="bottom|right|end"/>

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

MyFragment.java

public class MyFragment extends BottomSheetFragment {

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        final View view = inflater.inflate(R.layout.fragment_my, container, false);
        view.setMinimumHeight(getResources().getDisplayMetrics().heightPixels);
        CollapsingToolbarLayout collapsingToolbar = (CollapsingToolbarLayout) view.findViewById(R.id.collapsing_toolbar);
        collapsingToolbar.setTitle("AAA");
        final Toolbar toolbar = (Toolbar) view.findViewById(R.id.toolbar);
        final AppCompatActivity activity = (AppCompatActivity) getActivity();
        activity.setSupportActionBar(toolbar);
        activity.getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        //toolbar.setNavigationIcon(R.drawable.abc_ic_ab_back_mtrl_am_alpha);
        toolbar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                NavUtils.navigateUpFromSameTask(getActivity());
            }
        });
        final ImageView imageView = (ImageView) view.findViewById(R.id.backdrop);

        Glide.with(this).load(R.drawable.cheese_1).centerCrop().into(imageView);
        return view;
    }
}

BottomSheetFragmentActivity.java

public final class BottomSheetFragmentActivity extends AppCompatActivity {

    protected BottomSheetLayout bottomSheetLayout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_bottom_sheet_fragment);
        bottomSheetLayout = (BottomSheetLayout) findViewById(R.id.bottomsheet);
        findViewById(R.id.bottomsheet_fragment_button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new MyFragment().show(getSupportFragmentManager(), R.id.bottomsheet);
            }
        });
        bottomSheetLayout.setShouldDimContentView(false);
        bottomSheetLayout.setPeekOnDismiss(true);
        bottomSheetLayout.setPeekSheetTranslation(200);
        bottomSheetLayout.setInterceptContentTouch(false);
        bottomSheetLayout.setDefaultViewTransformer(new BaseViewTransformer() {
            @Override
            public void transformView(final float translation, final float maxTranslation, final float peekedTranslation, final BottomSheetLayout parent, final View view) {
                Log.d("AppLog", "translation:" + translation + " maxTranslation:" + maxTranslation + " peekedTranslation:" + peekedTranslation);
            }
        });
    }
}

几乎可以正常工作.唯一的问题是从#3过渡到#2:

It almost works well. The only problem is the transition from #3 back to #2:

代码有什么问题?我该怎么做才能达到要求的行为?

What is wrong with the code? What can I do in order to achieve the required behavior?

推荐答案

注意:阅读底部的编辑内容

Note: Read the edits at the bottom

好的,我找到了一种方法,但是我不得不更改多个类的代码,以便底页知道appBarLayout的状态(是否扩展),并忽略向上滚动如果它没有展开:

OK, I've found a way to do it, but I had to change the code of multiple classes, so that the bottom sheet would know of the state of the appBarLayout (expanded or not), and ignore scroll-up in case it's not expanded:

添加的字段:

private AppBarLayout mAppBarLayout;
private OnOffsetChangedListener mOnOffsetChangedListener;
private int mAppBarLayoutOffset;

init()-添加了此内容

init() - added this:

    mOnOffsetChangedListener = new OnOffsetChangedListener() {
        @Override
        public void onOffsetChanged(final AppBarLayout appBarLayout, final int verticalOffset) {
            mAppBarLayoutOffset = verticalOffset;
        }
    };

添加了用于设置appBarLayout的函数:

Added function to set the appBarLayout:

public void setAppBarLayout(final AppBarLayout appBarLayout) {
    if (mAppBarLayout == appBarLayout)
        return;
    if (mAppBarLayout != null)
        mAppBarLayout.removeOnOffsetChangedListener(mOnOffsetChangedListener);
    mAppBarLayout = appBarLayout;
    mAppBarLayout.addOnOffsetChangedListener(mOnOffsetChangedListener);
}

onDetachedFromWindow()-添加了此内容:

onDetachedFromWindow() - added this:

    if (mAppBarLayout != null)
        mAppBarLayout.removeOnOffsetChangedListener(mOnOffsetChangedListener);

onTouchEvent()-添加了此内容:

onTouchEvent() - added this:

      ...
      if (bottomSheetOwnsTouch) {
        if (state == State.EXPANDED && scrollingDown && mAppBarLayout != null && mAppBarLayoutOffset != 0) {
            event.offsetLocation(0, sheetTranslation - getHeight());
            getSheetView().dispatchTouchEvent(event);
            return true;
        }
      ...

这些是主要更改.现在是什么设置它们:

Those were the main changes. Now for what sets them:

MyFragment.java

onCreateView()-添加了此内容

onCreateView() - added this:

    mBottomSheetLayout.setAppBarLayout((AppBarLayout) view.findViewById(R.id.appbar));

我还添加了此功能:

 public void setBottomSheetLayout(final BottomSheetLayout bottomSheetLayout) {
    mBottomSheetLayout = bottomSheetLayout;
}

现在这是活动如何告诉片段有关appBarLayout的方式:

Now this is how the activity tells the fragment about the appBarLayout:

            final MyFragment myFragment = new MyFragment();
            myFragment.setBottomSheetLayout(bottomSheetLayout);
            myFragment.show(getSupportFragmentManager(), R.id.bottomsheet);

项目现已在GitHub上可用:

Project is now available on GitHub:

https://github.com/AndroidDeveloperLB/ThreePhasesBottomSheet

我希望它没有任何错误.

I hope it doesn't have any bugs.

可悲的是,该解决方案存在错误,因此我不会将此答案标记为正确的答案:

The solution has bugs, sadly, so I won't mark this answer as the correct one:

  1. 它仅适用于Android 6及更高版本.其他人则具有奇怪的行为,即每次显示底片时都将其展开一小部分.
  2. 方向更改根本不会保存滚动状态,因此我将其禁用.
  3. 在底部工作表的内容仍处于折叠状态时(底部)可以滚动到内部的罕见问题
  4. 如果以前显示过键盘,则在尝试窥视时,底页可能会变成全屏显示.

如果有人可以提供帮助,请这样做.

If anyone can help with it, please do.

对于问题1,我尝试通过在底表尚未显示时将可见性设置为INVISIBLE来添加修复程序,但这并不总是有效,尤其是在显示键盘的情况下.

For issue #1, I've tried adding a fix by setting the visibility to INVISIBLE when the bottom sheet isn't peeked yet, but it doesn't always work, especially if a keyboard is shown.

对于问题1,我已经找到了解决方法,只需将CoordinatorLayout包装(在"fragment_my.xml"中)并使用您希望使用的任何视图(我使用了FrameLayout),然后将完整的大小的视图(我只是放了视图"),例如:

For issue #1, I've found how to fix it, by just wrapping (in "fragment_my.xml") the CoordinatorLayout with any view that you wish to use (I used FrameLayout), and also put a full-sized view in it (I just put "View") , as such:

<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <!--This full sized view, together with the FrameLayout above, are used to handle some weird UI issues on pre-Android-6 -->
    <View
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <...CollapsingToolbarLayout 
    ...

当我将CoordinatorLayout作为其视图时,它可能会使bottomSheet感到困惑. 我已经更新了该项目,但仍然可以通过任何方式获得更好的解决方案.

It probably confused the bottomSheet when I had the CoordinatorLayout being its view. I've updated the project, but still, if there is any way to have a nicer solution, I'd like to know about it.

最近几个月,谷歌发布了自己的bottomSheet类,但是由于我发现它存在很多问题,所以我什至无法尝试.

In recent months, Google has published its own bottomSheet class, but as I've found it has a lot of issues, so I can't even try it out.

这篇关于如何模仿Google Maps的底页3个阶段的行为?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆