Sekarang setelah Pustaka Dukungan Desain Android keluar, apakah ada yang tahu cara menerapkan menu Fab yang diperluas dengannya, seperti hebat di Aplikasi Kotak Masuk?
Seharusnya terlihat seperti ini:
Sekarang setelah Pustaka Dukungan Desain Android keluar, apakah ada yang tahu cara menerapkan menu Fab yang diperluas dengannya, seperti hebat di Aplikasi Kotak Masuk?
Seharusnya terlihat seperti ini:
Jawaban:
Saat ini, tidak ada widget yang disediakan di Perpustakaan Desain. Satu-satunya cara untuk melakukannya dengan cepat dan mudah adalah dengan menggunakan perpustakaan pihak ketiga.
Anda jelas dapat melakukan ini menggunakan Perpustakaan Desain juga, tetapi itu akan menjadi pekerjaan besar dan membutuhkan banyak waktu. Saya telah menyebutkan beberapa perpustakaan yang bermanfaat, yang dapat membantu Anda mencapai ini.
Saya menggunakan yang ke-4.
Mendapat pendekatan yang lebih baik untuk menerapkan menu FAB animating tanpa menggunakan pustaka atau untuk menulis kode xml besar untuk animasi. Semoga ini akan membantu di masa depan bagi seseorang yang membutuhkan cara sederhana untuk mengimplementasikan ini.
Hanya dengan menggunakan animate().translationY()
fungsi, Anda dapat menggerakkan tampilan mana pun naik atau turun seperti yang saya lakukan pada kode di bawah ini, periksa kode lengkap di github . Jika Anda mencari kode yang sama di kotlin, Anda dapat checkout kode kotlin repo Menu FAB Bergerak .
pertama-tama tentukan semua FAB Anda di tempat yang sama sehingga mereka saling tumpang tindih, ingat di atas FAB seharusnya Anda ingin mengklik dan menunjukkan yang lain. misalnya:
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab3"
android:layout_width="@dimen/standard_45"
android:layout_height="@dimen/standard_45"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/standard_21"
app:srcCompat="@android:drawable/ic_btn_speak_now" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab2"
android:layout_width="@dimen/standard_45"
android:layout_height="@dimen/standard_45"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/standard_21"
app:srcCompat="@android:drawable/ic_menu_camera" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab1"
android:layout_width="@dimen/standard_45"
android:layout_height="@dimen/standard_45"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/standard_21"
app:srcCompat="@android:drawable/ic_dialog_map" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/fab_margin"
app:srcCompat="@android:drawable/ic_dialog_email" />
Sekarang di kelas java Anda cukup tentukan semua FAB Anda dan lakukan klik seperti yang ditunjukkan di bawah ini:
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab1 = (FloatingActionButton) findViewById(R.id.fab1);
fab2 = (FloatingActionButton) findViewById(R.id.fab2);
fab3 = (FloatingActionButton) findViewById(R.id.fab3);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(!isFABOpen){
showFABMenu();
}else{
closeFABMenu();
}
}
});
Gunakan animation().translationY()
untuk menghidupkan FAB Anda, saya lebih suka Anda menggunakan atribut metode ini di DP karena hanya menggunakan int akan mempengaruhi kompatibilitas tampilan dengan resolusi yang lebih tinggi atau resolusi yang lebih rendah. seperti yang ditunjukkan di bawah ini:
private void showFABMenu(){
isFABOpen=true;
fab1.animate().translationY(-getResources().getDimension(R.dimen.standard_55));
fab2.animate().translationY(-getResources().getDimension(R.dimen.standard_105));
fab3.animate().translationY(-getResources().getDimension(R.dimen.standard_155));
}
private void closeFABMenu(){
isFABOpen=false;
fab1.animate().translationY(0);
fab2.animate().translationY(0);
fab3.animate().translationY(0);
}
Sekarang tentukan dimensi yang disebutkan di atas dalam res-> values-> dimens.xml seperti yang ditunjukkan di bawah ini:
<dimen name="standard_55">55dp</dimen>
<dimen name="standard_105">105dp</dimen>
<dimen name="standard_155">155dp</dimen>
Itu semua berharap solusi ini akan membantu orang-orang di masa depan, yang sedang mencari solusi sederhana.
Diedit
Jika Anda ingin menambahkan label di atas FAB maka cukup ambil LinearLayout horizontal dan tempatkan FAB dengan tampilan teks sebagai label, dan hidupkan tata letak jika menemukan masalah saat melakukan ini, Anda dapat memeriksa kode sampel saya di github, saya telah menangani semua kompatibilitas mundur masalah dalam kode sampel itu. periksa kode sampel saya untuk FABMenu di Github
untuk menutup FAB pada Backpress, timpa onBackPress () seperti yang ditunjukkan di bawah ini:
@Override
public void onBackPressed() {
if(!isFABOpen){
this.super.onBackPressed();
}else{
closeFABMenu();
}
}
Screenshot memiliki judul juga dengan FAB, karena saya mengambilnya dari ingithub aplikasi sampel saya
Pertama-tama buat layout menu di file xml Layout aktivitas Anda. Untuk misalnya tata letak linier dengan orientasi horizontal dan sertakan label TextView untuk kemudian Tombol Tindakan yang Mengambang di samping TextView.
Buat tata letak menu sesuai kebutuhan dan nomor Anda.
Buat Tombol Tindakan Mengambang Basis dan klik itu yang mengubah visibilitas Tata Letak Menu.
Silakan periksa kode di bawah ini untuk referensi dan untuk info lebih lanjut checkout proyek saya dari github
<android.support.constraint.ConstraintLayout
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.app.fabmenu.MainActivity">
<android.support.design.widget.FloatingActionButton
android:id="@+id/baseFloatingActionButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:clickable="true"
android:onClick="@{FabHandler::onBaseFabClick}"
android:tint="@android:color/white"
app:fabSize="normal"
app:layout_constraintBottom_toBottomOf="@+id/activity_main"
app:layout_constraintRight_toRightOf="@+id/activity_main"
app:srcCompat="@drawable/ic_add_black_24dp" />
<LinearLayout
android:id="@+id/shareLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="12dp"
android:layout_marginEnd="24dp"
android:layout_marginRight="24dp"
android:gravity="center_vertical"
android:orientation="horizontal"
android:visibility="invisible"
app:layout_constraintBottom_toTopOf="@+id/createLayout"
app:layout_constraintLeft_toLeftOf="@+id/createLayout"
app:layout_constraintRight_toRightOf="@+id/activity_main">
<TextView
android:id="@+id/shareLabelTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:background="@drawable/shape_fab_label"
android:elevation="2dp"
android:fontFamily="sans-serif"
android:padding="5dip"
android:text="Share"
android:textColor="@android:color/white"
android:typeface="normal" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/shareFab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
android:onClick="@{FabHandler::onShareFabClick}"
android:tint="@android:color/white"
app:fabSize="mini"
app:srcCompat="@drawable/ic_share_black_24dp" />
</LinearLayout>
<LinearLayout
android:id="@+id/createLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="24dp"
android:layout_marginEnd="24dp"
android:layout_marginRight="24dp"
android:gravity="center_vertical"
android:orientation="horizontal"
android:visibility="invisible"
app:layout_constraintBottom_toTopOf="@+id/baseFloatingActionButton"
app:layout_constraintRight_toRightOf="@+id/activity_main">
<TextView
android:id="@+id/createLabelTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:background="@drawable/shape_fab_label"
android:elevation="2dp"
android:fontFamily="sans-serif"
android:padding="5dip"
android:text="Create"
android:textColor="@android:color/white"
android:typeface="normal" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/createFab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
android:onClick="@{FabHandler::onCreateFabClick}"
android:tint="@android:color/white"
app:fabSize="mini"
app:srcCompat="@drawable/ic_create_black_24dp" />
</LinearLayout>
</android.support.constraint.ConstraintLayout>
Ini adalah animasi-
Animasi pembukaan Menu FAB:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true">
<scale
android:duration="300"
android:fromXScale="0"
android:fromYScale="0"
android:interpolator="@android:anim/linear_interpolator"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1"
android:toYScale="1" />
<alpha
android:duration="300"
android:fromAlpha="0.0"
android:interpolator="@android:anim/accelerate_interpolator"
android:toAlpha="1.0" />
</set>
Animasi Penutupan Menu FAB:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true">
<scale
android:duration="300"
android:fromXScale="1"
android:fromYScale="1"
android:interpolator="@android:anim/linear_interpolator"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="0.0"
android:toYScale="0.0" />
<alpha
android:duration="300"
android:fromAlpha="1.0"
android:interpolator="@android:anim/accelerate_interpolator"
android:toAlpha="0.0" />
</set>
Kemudian di Aktivitas saya, saya cukup menggunakan animasi di atas untuk menampilkan dan menyembunyikan menu FAB:
Tampilkan Menu Hebat:
private void expandFabMenu() {
ViewCompat.animate(binding.baseFloatingActionButton).rotation(45.0F).withLayer().setDuration(300).setInterpolator(new OvershootInterpolator(10.0F)).start();
binding.createLayout.startAnimation(fabOpenAnimation);
binding.shareLayout.startAnimation(fabOpenAnimation);
binding.createFab.setClickable(true);
binding.shareFab.setClickable(true);
isFabMenuOpen = true;
}
Tutup Menu Luar Biasa:
private void collapseFabMenu() {
ViewCompat.animate(binding.baseFloatingActionButton).rotation(0.0F).withLayer().setDuration(300).setInterpolator(new OvershootInterpolator(10.0F)).start();
binding.createLayout.startAnimation(fabCloseAnimation);
binding.shareLayout.startAnimation(fabCloseAnimation);
binding.createFab.setClickable(false);
binding.shareFab.setClickable(false);
isFabMenuOpen = false;
}
Ini adalah kelas Activity -
package com.app.fabmenu;
import android.databinding.DataBindingUtil;
import android.os.Bundle;
import android.support.design.widget.Snackbar;
import android.support.v4.view.ViewCompat;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.OvershootInterpolator;
import com.app.fabmenu.databinding.ActivityMainBinding;
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding binding;
private Animation fabOpenAnimation;
private Animation fabCloseAnimation;
private boolean isFabMenuOpen = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
binding.setFabHandler(new FabHandler());
getAnimations();
}
private void getAnimations() {
fabOpenAnimation = AnimationUtils.loadAnimation(this, R.anim.fab_open);
fabCloseAnimation = AnimationUtils.loadAnimation(this, R.anim.fab_close);
}
private void expandFabMenu() {
ViewCompat.animate(binding.baseFloatingActionButton).rotation(45.0F).withLayer().setDuration(300).setInterpolator(new OvershootInterpolator(10.0F)).start();
binding.createLayout.startAnimation(fabOpenAnimation);
binding.shareLayout.startAnimation(fabOpenAnimation);
binding.createFab.setClickable(true);
binding.shareFab.setClickable(true);
isFabMenuOpen = true;
}
private void collapseFabMenu() {
ViewCompat.animate(binding.baseFloatingActionButton).rotation(0.0F).withLayer().setDuration(300).setInterpolator(new OvershootInterpolator(10.0F)).start();
binding.createLayout.startAnimation(fabCloseAnimation);
binding.shareLayout.startAnimation(fabCloseAnimation);
binding.createFab.setClickable(false);
binding.shareFab.setClickable(false);
isFabMenuOpen = false;
}
public class FabHandler {
public void onBaseFabClick(View view) {
if (isFabMenuOpen)
collapseFabMenu();
else
expandFabMenu();
}
public void onCreateFabClick(View view) {
Snackbar.make(binding.coordinatorLayout, "Create FAB tapped", Snackbar.LENGTH_SHORT).show();
}
public void onShareFabClick(View view) {
Snackbar.make(binding.coordinatorLayout, "Share FAB tapped", Snackbar.LENGTH_SHORT).show();
}
}
@Override
public void onBackPressed() {
if (isFabMenuOpen)
collapseFabMenu();
else
super.onBackPressed();
}
}
Berikut screenshotnya
Satu lagi perpustakaan yang menerapkan Panggilan Cepat dari pedoman Desain Bahan:
Ketika saya mencoba untuk membuat sesuatu yang mirip dengan tombol aksi mengambang inbox saya berpikir tentang membuat komponen kustom sendiri.
Ini akan menjadi tata letak bingkai sederhana dengan ketinggian tetap (berisi menu yang diperluas) yang berisi tombol FAB dan 3 lagi ditempatkan di bawah FAB. ketika Anda mengklik FAB, Anda cukup menghidupkan tombol lain untuk menerjemahkan dari bawah FAB.
Ada beberapa perpustakaan yang melakukan itu (misalnya https://github.com/futuresimple/android-floating-action-button ), tetapi selalu lebih menyenangkan jika Anda membuatnya sendiri :)
layout_anchor
dan layout_anchorGravity
tidak bekerja untuk saya
Anda dapat menggunakan perpustakaan FloatingActionMenu atau klik di sini untuk tutorial langkah demi langkah. Output dari tutorial:
Saya menggunakan perpustakaan ini untuk melakukan ini: https://github.com/futuresimple/android-floating-action-button
Cukup mudah digunakan;)
layout_anchor
dan layout_anchorGravity
tidak bekerja untuk saya
Pilihan lain untuk hasil yang sama dengan animasi ConstraintSet:
1) Letakkan semua tampilan animasi dalam satu ConstraintLayout
2) Buat animasi dari kode seperti ini (jika Anda ingin beberapa efek lagi terserah Anda..ini hanya contoh)
menuItem1 dan menuItem2 adalah FAB pertama dan kedua dalam menu, descriptionItem1 dan descriptionItem2 adalah deskripsi di sebelah kiri menu, parentConstraintLayout adalah root ConstraintLayout yang berisi semua tampilan animasi, adalahMenuOpened adalah beberapa fungsi untuk mengubah bendera terbuka / tertutup di negara bagian
Saya memasukkan kode animasi dalam file ekstensi tetapi itu tidak perlu.
fun FloatingActionButton.expandMenu(
menuItem1: View,
menuItem2: View,
descriptionItem1: TextView,
descriptionItem2: TextView,
parentConstraintLayout: ConstraintLayout,
isMenuOpened: (Boolean)-> Unit
) {
val constraintSet = ConstraintSet()
constraintSet.clone(parentConstraintLayout)
constraintSet.setVisibility(descriptionItem1.id, View.VISIBLE)
constraintSet.clear(menuItem1.id, ConstraintSet.TOP)
constraintSet.connect(menuItem1.id, ConstraintSet.BOTTOM, this.id, ConstraintSet.TOP, 0)
constraintSet.connect(menuItem1.id, ConstraintSet.START, this.id, ConstraintSet.START, 0)
constraintSet.connect(menuItem1.id, ConstraintSet.END, this.id, ConstraintSet.END, 0)
constraintSet.setVisibility(descriptionItem2.id, View.VISIBLE)
constraintSet.clear(menuItem2.id, ConstraintSet.TOP)
constraintSet.connect(menuItem2.id, ConstraintSet.BOTTOM, menuItem1.id, ConstraintSet.TOP, 0)
constraintSet.connect(menuItem2.id, ConstraintSet.START, this.id, ConstraintSet.START, 0)
constraintSet.connect(menuItem2.id, ConstraintSet.END, this.id, ConstraintSet.END, 0)
val transition = AutoTransition()
transition.duration = 150
transition.interpolator = AccelerateInterpolator()
transition.addListener(object: Transition.TransitionListener {
override fun onTransitionEnd(p0: Transition) {
isMenuOpened(true)
}
override fun onTransitionResume(p0: Transition) {}
override fun onTransitionPause(p0: Transition) {}
override fun onTransitionCancel(p0: Transition) {}
override fun onTransitionStart(p0: Transition) {}
})
TransitionManager.beginDelayedTransition(parentConstraintLayout, transition)
constraintSet.applyTo(parentConstraintLayout)
}