Làm thế nào để bắt chước hành vi 3 giai đoạn cuối trang tính của Google Maps?


110

Lý lịch

Tôi được chỉ định tạo một giao diện người dùng hoạt động tương tự như cách Google Maps hiển thị trang dưới cùng cho một kết quả tìm thấy.

Nó có ba giai đoạn khác nhau:

  1. Nội dung dưới cùng. Khu vực phía trên vẫn có thể chạm vào và sẽ không cuộn bất kỳ thứ gì ở phía dưới
  2. Nội dung toàn màn hình, trong khi khu vực phía trên có tiêu đề lớn.
  3. Nội dung toàn màn hình, trong khi khu vực phía trên chỉ có thanh công cụ.

Đây là những gì tôi đang nói về Google Maps:

Nhập mô tả hình ảnh tại đây

Vấn đề

Điều đó là, trang dưới cùng chưa phải là một phần của thư viện thiết kế (mặc dù nó đã được yêu cầu, tại đây ).

Không chỉ vậy, giao diện người dùng có vẻ khá phức tạp và cần xử lý thanh công cụ trên nhiều giai đoạn.

Những gì tôi đã thử

Tôi đã tìm thấy một thư viện tốt (đủ) cho trang tính dưới cùng ( tại đây ) và thêm nội dung vào mẫu phân đoạn của nó, để có cùng chế độ xem như được hiển thị trên các mẫu thiết kế material design (như ở đây ), để có một CollapsingToolbarLayout sẽ xử lý của giai đoạn 2 + 3.

Trong ứng dụng tôi đang tạo, tôi cũng phải di chuyển một biểu tượng khi bạn cuộn, nhưng tôi nghĩ rằng nếu tôi thành công với phần còn lại, điều này sẽ dễ dàng. Đây là mã:

gment_my.xml

<?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);
            }
        });
    }
}

Nó gần như hoạt động tốt. Vấn đề duy nhất là quá trình chuyển đổi từ # 3 trở lại # 2:

nhập mô tả hình ảnh ở đây

Câu hỏi

Có gì sai với mã? Tôi có thể làm gì để đạt được hành vi cần thiết?


Đối với tôi, giống như Chuyển đổi hoạt động. Bạn đã thử tạo 2 Hoạt động và áp dụng chuyển đổi vật chất giữa chúng chưa? Và được sử dụng CoordinatorLayouttrên màn hình thứ 2?
SD

@SD Tôi rất chắc chắn đó không phải là 2 hoạt động, vì bạn có thể tiếp tục chạm vào màn hình để cuộn và chuyển đổi giữa các giai đoạn. Nó không ngăn bạn chuyển sang hoạt động tiếp theo / trước đó. Khi mở một hoạt động mới, tôi không nghĩ rằng có thể duy trì các sự kiện chạm tương tự cho cơ chế cuộn. Tôi thậm chí không chắc liệu có thể sử dụng các mảnh vỡ hay không, nhưng điều này có lẽ còn khả thi hơn các hoạt động.
nhà phát triển Android

Sau đó, tôi nghĩ rằng tất cả các chế độ xem đều ở trong cùng một bố cục, với mỗi chế độ có một Hành vi cụ thể được đặt trên đó. Và tất cả các hành vi đang được kích hoạt từ tính năng chặn cuộn dọc trên bố cục gốc điều phối mọi thứ.
SD

@SD Bạn có biết cách làm cho nó hoạt động tốt không? Nó có tốt hơn những gì tôi đã tìm thấy không?
nhà phát triển Android

1
Tôi nghĩ bạn nên xem thư viện này .
Savelii Zagurskii

Câu trả lời:


18

Lưu ý : Đọc các chỉnh sửa ở dưới cùng


OK, tôi đã tìm ra cách để làm điều đó, nhưng tôi phải thay đổi mã của nhiều lớp, để trang dưới cùng biết trạng thái của appBarLayout (được mở rộng hay không) và bỏ qua cuộn lên trong trường hợp không được mở rộng:

BottomSheetLayout.java

Các trường đã thêm:

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

init () - đã thêm cái này:

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

Đã thêm chức năng để đặt appBarLayout:

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

onDetachedFromWindow () - đã thêm cái này:

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

onTouchEvent () - đã thêm cái này:

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

Đó là những thay đổi chính. Bây giờ cho những gì đặt chúng:

MyFragment.java

onCreateView () - đã thêm cái này:

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

Tôi cũng đã thêm chức năng này:

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

Bây giờ đây là cách hoạt động nói với phân đoạn về appBarLayout:

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

Dự án hiện đã có trên GitHub:

https://github.com/AndroidDeveloperLB/ThreePhasesBottomSheet

Tôi hy vọng nó không có bất kỳ lỗi nào.


Giải pháp có lỗi, thật đáng buồn, vì vậy tôi sẽ không đánh dấu câu trả lời này là câu trả lời đúng:

  1. Nó chỉ hoạt động tốt trên Android 6 trở lên. Những người khác có một hành vi kỳ lạ là hiển thị trang dưới cùng được mở rộng trong một phần nhỏ của thời gian, mỗi khi hiển thị nó.
  2. Thay đổi hướng không lưu trạng thái cuộn, vì vậy tôi đã tắt nó.
  3. Sự cố hiếm khi có thể cuộn bên trong nội dung của trang dưới cùng trong khi nó vẫn được thu gọn (ở dưới cùng)
  4. Nếu bàn phím được hiển thị trước đó, trang dưới cùng có thể ở chế độ toàn màn hình khi cố gắng xem trộm.

Nếu bất cứ ai có thể giúp với nó, xin vui lòng làm.


Đối với sự cố số 1, tôi đã thử thêm một bản sửa lỗi bằng cách đặt khả năng hiển thị thành KHÔNG CÓ THỂ khi trang dưới cùng chưa được xem qua, nhưng nó không phải lúc nào cũng hoạt động, đặc biệt là nếu bàn phím được hiển thị.


Đối với vấn đề số 1, tôi đã tìm ra cách khắc phục nó, bằng cách chỉ gói (trong "mảnh_tình.xml") CoordinatorLayout với bất kỳ chế độ xem nào mà bạn muốn sử dụng (tôi đã sử dụng FrameLayout) và cũng đưa một chế độ xem có kích thước đầy đủ vào nó (tôi chỉ đặt "View"), chẳng hạn như:

<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 
    ...

Nó có thể nhầm lẫn bottomSheet khi tôi có CoordinatorLayout là chế độ xem của nó. Tôi đã cập nhật dự án, nhưng vẫn còn, nếu có bất kỳ cách nào để có một giải pháp tốt hơn, tôi muốn biết về nó.


Trong những tháng gần đây, Google đã xuất bản lớp bottomSheet của riêng mình, nhưng tôi thấy nó có rất nhiều vấn đề nên tôi thậm chí không thể dùng thử.


nhưng những gì về hình ảnh này? cloud.githubusercontent.com/assets/5357526/11641271/… tôi muốn triển khai loại trang trình bày hình ảnh này cùng với phần dưới cùng đi lên
Hardy

@HBdroid Tôi nghĩ nó có thể. có thể đối với chức năng "onOffsetChanged", cũng thay đổi bản dịch của mBottomSheetBackgroundImageView? Yêu cầu đối với trường hợp của tôi là đầu tiên phải xử lý 3 giai đoạn. Bây giờ là một câu hỏi về việc chuyển đổi những gì và như thế nào, và điều này rất tùy chỉnh và phụ thuộc vào nhu cầu của bạn. Nó cũng đòi hỏi rất nhiều phép toán khó chịu. Tôi khuyên bạn nên sử dụng tính năng chạy tức thì để thử nhanh.
nhà phát triển android

tôi không thể tìm ra giải pháp giúp đỡ xin vui lòng cho tôi
Hardy

@HBdroid Xin lỗi tôi không biết. Có thể thử xóa ứng dụng này: layout_collapseMode = "parallax". cũng cố gắng thực hiện việc dịch trong TransformView.
nhà phát triển android

2
@Hardy, bạn đã kết thúc việc tạo ra giải pháp bạn muốn chưa? nếu có nó là mã nguồn mở và nó có thể được chia sẻ không?
N Jay

15

CẬP NHẬT LỚN

Bởi vì có khoảng 4 hoặc 5 câu hỏi về cùng một chủ đề, NHƯNG với các yêu cầu KHÁC NHAU và tôi đã cố gắng trả lời tất cả chúng, nhưng một quản trị viên không lịch sự đã xóa / đóng chúng, khiến tôi phải tạo một phiếu cho từng chủ đề và thay đổi chúng thành tránh "sao chép dán" Tôi sẽ cung cấp cho bạn một liên kết đến câu trả lời đầy đủ trong đó bạn có thể tìm thấy tất cả lời giải thích về cách có được hành vi đầy đủ như Google Maps.


Trả lời câu hỏi của bạn

Làm thế nào để bắt chước hành vi 3 giai đoạn cuối trang tính của Google Maps?

Với thư viện hỗ trợ 23.x.x +, bạn có thể thực hiện việc sửa đổi mặc định BottomSheetBehavior, thêm một chỉ số nữa bằng các bước sau:

  1. Tạo một lớp Java và mở rộng nó từ CoordinatorLayout.Behavior<V>
  2. Sao chép mã dán từ BottomSheetBehaviortệp mặc định sang tệp mới của bạn.
  3. Sửa đổi phương pháp clampViewPositionVerticalvới mã sau:

    @Override
    public int clampViewPositionVertical(View child, int top, int dy) {
        return constrain(top, mMinOffset, mHideable ? mParentHeight : mMaxOffset);
    }
    int constrain(int amount, int low, int high) {
        return amount < low ? low : (amount > high ? high : amount);
    }
  4. Thêm trạng thái mới:

    public static final int STATE_ANCHOR_POINT = X;
  5. Sửa đổi các phương pháp tiếp theo: onLayoutChild, onStopNestedScroll, BottomSheetBehavior<V> from(V view)setState(không bắt buộc)

Tôi sẽ thêm các phương thức đã sửa đổi đó và một liên kết đến dự án mẫu .

Và đây là cách nó trông như thế nào:
CustomBottomSheetBehavior


Tôi đã thử nghiệm repo github và nó có vẻ tốt. Nhưng khu vực màu xanh lam phía trên đôi khi trông một phần. Ngoài ra, tôi không thể tìm ra nơi để xử lý các dạng xem cần di chuyển khi bạn kéo trang tính dưới cùng. Trong repo mà tôi đã tạo (tại đây: github.com/AndroidDeveloperLB/ThreePhasesBottomSheet ), hình ảnh mờ dần và hình ảnh nhỏ di chuyển từ nơi này sang nơi khác, bao gồm cả việc thay đổi kích thước của nó. Tôi muốn biết nơi để thêm việc xử lý chúng.
nhà phát triển android

Xin chào, tôi có một phiên bản cục bộ với hình ảnh thị sai nhưng nó chưa hoạt động tốt (tôi có thể đẩy nó nếu bạn muốn xem nó). Bạn có thể thêm bất kỳ chế độ xem nào bên CoordinatorLayouttrong activity_main.xml. Tôi đoán bạn có kinh nghiệm tốt với bố cục bộ điều phối, nếu không, hãy xem liên kết
MiguelHincapieC

Tôi sẽ xem bạn đã có hành vi thanh công cụ như thế nào và sẽ sử dụng nó trên của tôi: D. Nhân tiện, có một hành vi nhỏ mà tôi chỉ có thể bắt chước nếu tôi sử dụng thư viện hỗ trợ 23.2: trong bản đồ google nếu bạn kéo hình ảnh bên dưới thanh công cụ, nó sẽ di chuyển trang tính dưới cùng, nhưng nếu bạn nâng cấp lên 23.4 hoặc minSdkVersion 14+ thì bạn sẽ mất hành vi này o_O '
MiguelHincapieC

@androiddeveloper Tôi hiểu rồi! bây giờ nó đang hoạt động với hiệu ứng thị sai hình ảnh và hoạt ảnh thanh công cụ ... Tôi chỉ thiếu màu sắc chiếm thanh công cụ khi bạn tiếp tục trượt lên: D
MiguelHincapieC

@MiguelHincapieC Xin chào, tôi muốn chỉ hiển thị thanh công cụ chính và tôi đã xóa bố cục thanh ứng dụng đã hợp nhất nhưng thanh trạng thái thời gian mở rộng ở trang dưới cùng không hiển thị và hình ảnh parallex kết thúc ở vị trí thanh trạng thái và tôi muốn hình ảnh parallex dính bên dưới thanh công cụ chính. bạn có thể giải thích làm thế nào tôi có thể làm điều đó
Vijay Rajput

0

Bạn đã thử cái này chưa? http://android-developers.blogspot.in/2016/02/android-support-library-232.html?m=1 Ở đây nó cho biết chúng ta chỉ có thể chỉ định hành vi bố cục trang tính dưới cùng.

CẬP NHẬT:

Về cơ bản, liên kết trạng thái-

Bằng cách gắn BottomSheetBehavior vào Chế độ xem của một CoordinatorLayout con (tức là thêm ứng dụng: layout_behavior = "android.support.design.widget.BottomSheetBehavior"), bạn sẽ tự động nhận được phát hiện chạm thích hợp để chuyển đổi giữa năm trạng thái:

STATE_COLLAPSED: this collapsed state is the default and shows just a portion of the layout along the bottom. The height can be controlled with the app:behavior_peekHeight attribute (defaults to 0)
STATE_DRAGGING: the intermediate state while the user is directly dragging the bottom sheet up or down
STATE_SETTLING: that brief time between when the View is released and settling into its final position
STATE_EXPANDED: the fully expanded state of the bottom sheet, where either the whole bottom sheet is visible (if its height is less than the containing CoordinatorLayout) or the entire CoordinatorLayout is filled
STATE_HIDDEN: disabled by default (and enabled with the app:behavior_hideable attribute), enabling this allows users to swipe down on the bottom sheet to completely hide the bottom sheet
Keep in mind that scrolling containers in your bottom sheet must support nested scrolling (for example, NestedScrollView, RecyclerView, or ListView/ScrollView on API 21+).

Nếu bạn muốn nhận các cuộc gọi lại về các thay đổi trạng thái, bạn có thể thêm BottomSheetCallback:

// The View with the BottomSheetBehavior  
 View bottomSheet = coordinatorLayout.findViewById(R.id.bottom_sheet);  
 BottomSheetBehavior behavior = BottomSheetBehavior.from(bottomSheet);  
 behavior.setBottomSheetCallback(new BottomSheetCallback() {  
    @Override  
    public void onStateChanged(@NonNull View bottomSheet, int newState) {  
      // React to state change  
    }  
      @Override  
      public void onSlide(@NonNull View bottomSheet, float slideOffset) {  
       // React to dragging events  
   }  
 });  

Trong khi BottomSheetBehavior ghi lại trường hợp trang tính dưới cùng liên tục, bản phát hành này cũng cung cấp BottomSheetDialog và BottomSheetDialogFragment để điền vào trường hợp sử dụng trang tính dưới cùng theo phương thức. Chỉ cần thay thế AppCompatDialog hoặc AppCompatDialogFragment bằng các ứng dụng tương đương trang dưới cùng của chúng để hộp thoại của bạn được tạo kiểu như trang dưới cùng.


Câu hỏi được đưa ra trước khi Google hiển thị lớp thư viện hỗ trợ của họ. Nếu bạn có một giải pháp hoạt động bằng cách sử dụng nó, vui lòng hiển thị nó ở đây.
nhà phát triển android

@androiddeveloper Tôi đã không đọc ngày câu hỏi và do đó tôi đề xuất câu trả lời này. Nhưng nếu bạn muốn sử dụng thư viện này, bạn có thể sử dụng nó. Đối với giải pháp làm việc cho mã này, tôi không có nó. Lấy làm tiếc.
Vaibhav Sharma

0

Tôi cũng phải triển khai một chế độ xem tương tự như cách Google Maps hiển thị trang dưới cùng để có kết quả tìm thấy.

Đây là diện mạo của tôi:

Nhìn lén

Mở rộng chế độ xem được cuộn lên đầu

Mở rộng chế độ xem được cuộn xuống dưới cùng

Lúc đầu, tôi đã xác định trang tính dưới cùng với tiêu đề và nội dung có thể cuộn nhưng layout_height dường như không bao bọc nội dung của tiêu đề cũng như nội dung có thể cuộn mặc dù đã chỉ định wrap_content.

Vấn đề đó đã biến mất khi tôi sử dụng LinearLayoutthay vì ConstraintLayoutcho CoordinatorLayoutbố cục con của '(và cho các con của nó).

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/buttonPeek"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Peek"
        app:layout_constraintEnd_toStartOf="@+id/buttonExpand"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/buttonExpand"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Expand"
        app:layout_constraintEnd_toStartOf="@+id/buttonClose"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toEndOf="@+id/buttonPeek"
        app:layout_constraintTop_toTopOf="@+id/buttonPeek" />

    <Button
        android:id="@+id/buttonClose"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Close"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toEndOf="@+id/buttonExpand"
        app:layout_constraintTop_toTopOf="@+id/buttonExpand" />

    <androidx.coordinatorlayout.widget.CoordinatorLayout 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:id="@+id/layout_coordinator"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <LinearLayout
            android:id="@+id/layout_coordinator_child"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            app:behavior_hideable="true"
            app:layout_behavior="@string/bottom_sheet_behavior">

            <LinearLayout
                android:id="@+id/layout_bottom_sheet_header"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="#FFFF0000"
                android:orientation="vertical" >

                <TextView
                    android:id="@+id/headerTextView_a"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="a" />

                <TextView
                android:id="@+id/headerTextView_b"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="b" />

                <TextView
                android:id="@+id/headerTextView_c"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="c" />

                <TextView
                android:id="@+id/headerTextView_d"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="d" />

                <TextView
                android:id="@+id/headerTextView_e"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="e" />

                <TextView
                android:id="@+id/headerTextView_f"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="f" />

                <TextView
                android:id="@+id/headerTextView_g"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="g" />

                <TextView
                android:id="@+id/headerTextView_h"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="h" />

                <TextView
                android:id="@+id/headerTextView_i"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="i" />

                <TextView
                android:id="@+id/headerTextView_j"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="j" />

                <TextView
                android:id="@+id/headerTextView_k"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="k" />

            </LinearLayout>

            <androidx.core.widget.NestedScrollView
                android:id="@+id/layout_bottom_sheet_scrollable_view"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="#FF00FF00"
                android:fillViewport="true" >

                <LinearLayout
                    android:id="@+id/layout_bottom_sheet_scrollable_content"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:orientation="vertical">

                    <TextView
                        android:id="@+id/textView0"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="0" />

                    <TextView
                        android:id="@+id/textView1"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="1" />

                    <TextView
                        android:id="@+id/textView2"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="2" />

                    <TextView
                        android:id="@+id/textView3"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="3" />

                    <TextView
                        android:id="@+id/textView4"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="4" />

                    <TextView
                        android:id="@+id/textView5"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="5" />

                    <TextView
                        android:id="@+id/textView6"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="6" />

                    <TextView
                        android:id="@+id/textView7"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="7" />

                    <TextView
                        android:id="@+id/textView8"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="8" />

                    <TextView
                        android:id="@+id/textView9"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="9" />

                    <TextView
                        android:id="@+id/textView10"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="10" />

                    <TextView
                        android:id="@+id/textView11"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="11" />

                    <TextView
                        android:id="@+id/textView12"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="12" />

                    <TextView
                        android:id="@+id/textView13"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="13" />

                    <TextView
                        android:id="@+id/textView14"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="14" />

                    <TextView
                        android:id="@+id/textView15"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="15" />

                    <TextView
                        android:id="@+id/textView16"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="16" />

                    <TextView
                        android:id="@+id/textView17"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="17" />

                    <TextView
                        android:id="@+id/textView18"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="18" />

                    <TextView
                        android:id="@+id/textView19"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="19" />

                    <TextView
                        android:id="@+id/textView20"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="20" />

                    <TextView
                        android:id="@+id/textView21"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="21" />

                    <TextView
                        android:id="@+id/textView22"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="22" />

                    <TextView
                        android:id="@+id/textView23"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="23" />

                    <TextView
                        android:id="@+id/textView24"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="24" />

                    <TextView
                        android:id="@+id/textView25"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="25" />

                    <TextView
                        android:id="@+id/textView26"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="26" />

                    <TextView
                        android:id="@+id/textView27"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="27" />

                    <TextView
                        android:id="@+id/textView28"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="28" />

                    <TextView
                        android:id="@+id/textView29"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="29" />

                    <TextView
                        android:id="@+id/textView30"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="30" />

                    <TextView
                        android:id="@+id/textView31"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="31" />

                    <TextView
                        android:id="@+id/textView32"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="32" />

                    <TextView
                        android:id="@+id/textView33"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="33" />

                    <TextView
                        android:id="@+id/textView34"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="34" />

                    <TextView
                        android:id="@+id/textView35"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="35" />

                    <TextView
                        android:id="@+id/textView36"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="36" />

                    <TextView
                        android:id="@+id/textView37"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="37" />

                    <TextView
                        android:id="@+id/textView38"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="38" />

                    <TextView
                        android:id="@+id/textView39"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="39" />

                    <TextView
                        android:id="@+id/textView40"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="40" />

                    <TextView
                        android:id="@+id/textView41"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="41" />

                    <TextView
                        android:id="@+id/textView42"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="42" />

                    <TextView
                        android:id="@+id/textView43"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="43" />

                    <TextView
                        android:id="@+id/textView44"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="44" />

                    <TextView
                        android:id="@+id/textView45"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="45" />

                    <TextView
                        android:id="@+id/textView46"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="46" />

                    <TextView
                        android:id="@+id/textView47"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="47" />

                    <TextView
                        android:id="@+id/textView48"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="48" />

                    <TextView
                        android:id="@+id/textView49"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="49" />

                </LinearLayout>

            </androidx.core.widget.NestedScrollView>
        </LinearLayout>

    </androidx.coordinatorlayout.widget.CoordinatorLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

MainActivity.java

package com.example.bottomsheetwithscrollablecontent;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;

import com.google.android.material.bottomsheet.BottomSheetBehavior;

import androidx.appcompat.app.AppCompatActivity;
import androidx.coordinatorlayout.widget.CoordinatorLayout;

public class MainActivity extends AppCompatActivity {
    private CoordinatorLayout layout_coordinator;
    private View layout_coordinator_child;
    private View layout_bottom_sheet_header;

    private BottomSheetBehavior behavior;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        layout_coordinator = findViewById(R.id.layout_coordinator);
        layout_coordinator_child = layout_coordinator.findViewById(R.id.layout_coordinator_child);
        layout_bottom_sheet_header = layout_coordinator.findViewById(R.id.layout_bottom_sheet_header);

        behavior = BottomSheetBehavior.from(layout_coordinator_child);

        Button buttonPeek = findViewById(R.id.buttonPeek);
        buttonPeek.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                behavior.setPeekHeight(layout_bottom_sheet_header.getHeight());
                behavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
            }
        });

        Button buttonExpand = findViewById(R.id.buttonExpand);
        buttonExpand.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
            }
        });

        Button buttonClose = findViewById(R.id.buttonClose);
        buttonClose.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                behavior.setState(BottomSheetBehavior.STATE_HIDDEN);
            }
        });
    }
}

app / build.gradle

apply plugin: 'com.android.application'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.example.bottomsheetwithscrollablecontent"
        minSdkVersion 24
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'androidx.appcompat:appcompat:1.0.0-beta01'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.2'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test:runner:1.1.0-alpha4'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0-alpha4'
    implementation 'androidx.legacy:legacy-support-v4:1.0.0-beta01'
    implementation "com.google.android.material:material:1.1.0-alpha04"
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.