Latar Belakang
Saya ditugaskan untuk membuat UI yang berperilaku mirip dengan bagaimana Google Maps menampilkan lembaran bawah untuk hasil yang ditemukan.
Ini memiliki tiga fase berbeda:
- Konten bawah. Area atas masih dapat disentuh dan tidak akan menggulir apa pun di bagian bawah
- Konten layar penuh, sedangkan area atas memiliki header berukuran besar.
- Konten layar penuh, sedangkan area atas hanya memiliki toolbar.
Inilah yang saya bicarakan di Google Maps:
Masalah
Masalahnya, lembar bawah belum menjadi bagian dari pustaka desain (meskipun diminta, di sini ).
Tidak hanya itu, UI-nya terlihat cukup rumit dan membutuhkan penanganan toolbar pada beberapa fase.
Apa yang saya coba
Saya telah menemukan pustaka (cukup) yang bagus untuk lembar bawah (di sini ), dan menambahkan konten ke sampel fragmennya, untuk memiliki tampilan yang hampir sama seperti yang ditunjukkan pada sampel desain material (seperti di sini ), untuk memiliki CollapsingToolbarLayout yang akan menangani dari fase 2 + 3.
Dalam aplikasi yang saya buat, saya juga harus memindahkan ikon saat Anda menggulir, tetapi saya rasa jika saya berhasil dengan yang lainnya, ini akan mudah. Berikut kodenya:
fragment_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);
}
});
}
}
Ini hampir bekerja dengan baik. Satu-satunya masalah adalah transisi dari # 3 kembali ke # 2:
Pertanyaan
Apa yang salah dengan kode tersebut? Apa yang dapat saya lakukan untuk mencapai perilaku yang diperlukan?
sumber
CoordinatorLayout
di layar ke-2?Jawaban:
Catatan : Baca edit di bagian bawah
Oke, saya telah menemukan cara untuk melakukannya, tetapi saya harus mengubah kode dari beberapa kelas, sehingga lembar bawah akan mengetahui status appBarLayout (diperluas atau tidak), dan mengabaikan scroll-up jika tidak diperluas:
BottomSheetLayout.java
Bidang yang ditambahkan:
init () - menambahkan ini:
Menambahkan fungsi untuk mengatur appBarLayout:
onDetachedFromWindow () - menambahkan ini:
onTouchEvent () - menambahkan ini:
Itu adalah perubahan utama. Sekarang untuk apa yang membuat mereka:
MyFragment.java
onCreateView () - menambahkan ini:
Saya juga menambahkan fungsi ini:
Inilah cara aktivitas memberi tahu fragmen tentang appBarLayout:
Proyek sekarang tersedia di GitHub:
https://github.com/AndroidDeveloperLB/ThreePhasesBottomSheet
Saya harap tidak ada bug.
Solusinya memiliki bug, sayangnya, jadi saya tidak akan menandai jawaban ini sebagai yang benar:
Jika ada yang bisa membantu, tolong lakukan.
Untuk masalah # 1, saya telah mencoba menambahkan perbaikan dengan mengatur visibilitas ke TIDAK TERLIHAT ketika lembar bawah belum diintip, tetapi tidak selalu berfungsi, terutama jika keyboard ditampilkan.
Untuk masalah # 1, saya telah menemukan cara memperbaikinya, dengan hanya membungkus (dalam "fragment_my.xml") CoordinatorLayout dengan tampilan apa pun yang ingin Anda gunakan (saya menggunakan FrameLayout), dan juga meletakkan tampilan berukuran penuh di itu (saya hanya meletakkan "View"), seperti:
Ini mungkin membingungkan bottomSheet ketika saya melihat CoordinatorLayout sebagai tampilannya. Saya telah memperbarui proyek tersebut, tetapi tetap saja, jika ada cara untuk mendapatkan solusi yang lebih baik, saya ingin mengetahuinya.
Dalam beberapa bulan terakhir, Google telah menerbitkan kelas bottomSheet-nya sendiri, tetapi seperti yang saya temukan memiliki banyak masalah, jadi saya bahkan tidak dapat mencobanya.
sumber
PEMBARUAN BESAR
Karena ada 4 atau 5 pertanyaan tentang topik yang sama, TETAPI dengan persyaratan yang BERBEDA, dan saya mencoba menjawab semuanya, tetapi admin yang tidak sopan menghapus / menutupnya, membuat saya membuat tiket untuk masing-masing dan mengubahnya menjadi hindari "salin tempel" Saya akan memberi Anda tautan ke jawaban lengkap di mana Anda dapat menemukan semua penjelasan tentang cara mendapatkan perilaku lengkap seperti Google Maps.
Menjawab pertanyaan Anda
Dengan support library 23.x.x + Anda dapat melakukannya dengan memodifikasi default
BottomSheetBehavior
, menambahkan satu stat lagi dengan langkah-langkah berikut:CoordinatorLayout.Behavior<V>
BottomSheetBehavior
file default ke yang baru.Ubah metode
clampViewPositionVertical
dengan kode berikut:Tambahkan negara bagian baru:
Memodifikasi metode berikutnya:
onLayoutChild
,onStopNestedScroll
,BottomSheetBehavior<V> from(V view)
dansetState
(opsional)Saya akan menambahkan metode yang dimodifikasi tersebut dan tautan ke proyek contoh .
Dan inilah tampilannya:
sumber
CoordinatorLayout
dalamactivity_main.xml
. Saya kira Anda memiliki pengalaman yang baik dengan tata letak koordinator, jika tidak lihat tautanApakah kamu sudah mencobanya? http://android-developers.blogspot.in/2016/02/android-support-library-232.html?m=1 Di sini dikatakan bahwa kita hanya dapat menentukan perilaku tata letak lembar bawah.
MEMPERBARUI:
Pada dasarnya tautan menyatakan-
Dengan melampirkan BottomSheetBehavior ke Tampilan anak dari CoordinatorLayout (yaitu, menambahkan app: layout_behavior = "android.support.design.widget.BottomSheetBehavior"), Anda secara otomatis akan mendapatkan deteksi sentuhan yang sesuai untuk transisi antara lima keadaan:
Jika Anda ingin menerima callback dari perubahan status, Anda dapat menambahkan BottomSheetCallback:
Sementara BottomSheetBehavior menangkap kasus lembar bawah yang persisten, rilis ini juga menyediakan BottomSheetDialog dan BottomSheetDialogFragment untuk mengisi kasus penggunaan lembar dasar modal. Cukup ganti AppCompatDialog atau AppCompatDialogFragment dengan lembar bawahnya yang setara agar dialog Anda diberi gaya sebagai lembar bawah.
sumber
Saya juga harus menerapkan tampilan yang mirip dengan cara Google Maps menampilkan lembaran bawah untuk hasil yang ditemukan.
Begini penampilan saya:
Pada awalnya, saya mendefinisikan lembar bawah dengan header dan konten yang dapat digulir tetapi layout_height tampaknya tidak membungkus konten baik dari header maupun konten yang dapat digulir meskipun ditentukan
wrap_content
.Masalah itu hilang ketika saya menggunakan
LinearLayout
alih-alihConstraintLayout
untukCoordinatorLayout
tata letak anak (dan untuk anaknya).activity_main.xml
MainActivity.java
app / build.gradle
sumber