Bây giờ Thư viện hỗ trợ thiết kế Android đã hết, có ai biết cách triển khai menu Fab mở rộng với nó, như fab trên Ứng dụng hộp thư đến không?
Nên trông như thế này:
Bây giờ Thư viện hỗ trợ thiết kế Android đã hết, có ai biết cách triển khai menu Fab mở rộng với nó, như fab trên Ứng dụng hộp thư đến không?
Nên trông như thế này:
Câu trả lời:
Hiện tại, không có widget nào được cung cấp trong Thư viện thiết kế. Cách duy nhất để làm điều đó nhanh chóng và dễ dàng là sử dụng các thư viện của bên thứ ba.
Rõ ràng bạn cũng có thể làm điều này bằng Thư viện thiết kế, nhưng nó sẽ là một công việc khổng lồ và đòi hỏi nhiều thời gian. Tôi đã đề cập đến một số thư viện hữu ích, có thể giúp bạn đạt được điều này.
Tôi đang sử dụng cái thứ 4
Có một cách tiếp cận tốt hơn để thực hiện menu FAB hoạt hình mà không cần sử dụng bất kỳ thư viện hoặc để viết mã xml lớn cho hình ảnh động. hy vọng điều này sẽ giúp ích trong tương lai cho những người cần một cách đơn giản để thực hiện điều này.
Chỉ cần sử dụng animate().translationY()
chức năng, bạn có thể làm động bất kỳ chế độ xem lên hoặc xuống như tôi đã làm trong mã dưới đây, kiểm tra mã hoàn chỉnh trong github . Trong trường hợp bạn đang tìm kiếm cùng một mã trong kotlin, bạn có thể kiểm tra mã kotlin repo Menu hoạt hình FAB .
trước tiên hãy xác định tất cả FAB của bạn tại cùng một vị trí để chúng chồng lên nhau, hãy nhớ trên FAB phải là bạn muốn nhấp và hiển thị khác. ví dụ:
<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" />
Bây giờ trong lớp java của bạn chỉ cần xác định tất cả FAB của bạn và thực hiện nhấp chuột như hiển thị bên dưới:
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();
}
}
});
Sử dụng animation().translationY()
để tạo hiệu ứng FAB của bạn, tôi thích bạn sử dụng thuộc tính của phương thức này trong DP vì chỉ sử dụng int sẽ có hiệu lực tương thích màn hình với độ phân giải cao hơn hoặc độ phân giải thấp hơn. như hình dưới đây:
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);
}
Bây giờ hãy xác định thứ nguyên được đề cập ở trên bên trong res-> giá trị-> dimens.xml như được hiển thị bên dưới:
<dimen name="standard_55">55dp</dimen>
<dimen name="standard_105">105dp</dimen>
<dimen name="standard_155">155dp</dimen>
Đó là tất cả hy vọng giải pháp này sẽ giúp những người trong tương lai, những người đang tìm kiếm giải pháp đơn giản.
EDITED
Nếu bạn muốn thêm nhãn qua FAB thì chỉ cần lấy linearLayout ngang và đặt FAB với textview làm nhãn và làm động các bố cục nếu tìm thấy bất kỳ vấn đề nào khi thực hiện điều này, bạn có thể kiểm tra mã mẫu của tôi trong github, tôi đã xử lý tất cả khả năng tương thích ngược các vấn đề trong mã mẫu đó. kiểm tra mã mẫu của tôi để tìm FABMothy trong Github
để đóng FAB trên Backpress, ghi đè onBackPress () như hiển thị bên dưới:
@Override
public void onBackPressed() {
if(!isFABOpen){
this.super.onBackPressed();
}else{
closeFABMenu();
}
}
Ảnh chụp màn hình cũng có tiêu đề với FAB, vì tôi lấy nó từ ứng dụng mẫu của tôi hiện tại ingithub
Trước tiên, hãy tạo bố cục menu trong tệp xml Bố cục hoạt động của bạn. Ví dụ: bố cục tuyến tính với hướng nằm ngang và bao gồm TextView cho nhãn sau đó là Nút hành động nổi bên cạnh TextView.
Tạo bố cục menu theo nhu cầu và số lượng của bạn.
Tạo Nút Hành động Nổi Cơ sở và khi nhấp vào nút đó sẽ thay đổi mức độ hiển thị của Bố cục Menu.
Vui lòng kiểm tra mã dưới đây để tham khảo và để biết thêm thông tin kiểm tra dự án của tôi từ 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>
Đây là những hình ảnh động-
Mở hoạt hình của 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>
Đóng hình động của 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>
Sau đó, trong Hoạt động của tôi, tôi chỉ đơn giản là sử dụng các hình ảnh động ở trên để hiển thị và ẩn menu FAB:
Hiển thị Menu Fab:
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;
}
Đóng menu Fab:
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;
}
Đây là lớp 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();
}
}
Dưới đây là ảnh chụp màn hình
Thêm một thư viện triển khai Quay số nhanh từ hướng dẫn Thiết kế Vật liệu:
Khi tôi cố gắng tạo một cái gì đó simillar để inbox nút hành động nổi, tôi nghĩ về việc tạo thành phần tùy chỉnh riêng.
Đó sẽ là bố cục khung đơn giản với chiều cao cố định (để chứa menu mở rộng) chứa nút FAB và 3 nút nữa được đặt dưới FAB. Khi bạn nhấp vào FAB, bạn chỉ cần làm động các nút khác để dịch lên từ bên dưới FAB.
Có một số thư viện làm điều đó (ví dụ https://github.com/futuresimple/android-floating-action-button ), nhưng sẽ luôn vui hơn nếu bạn tự tạo nó :)
layout_anchor
và layout_anchorGravity
không làm việc cho tôi
Bạn có thể sử dụng thư viện FloatingActionMothy hoặc bấm vào đây để hướng dẫn từng bước. Đầu ra của hướng dẫn:
Tôi sử dụng thư viện này để làm điều này: https://github.com/futuresimple/android-floating-action-button
Khá đơn giản để sử dụng;)
layout_anchor
và layout_anchorGravity
không làm việc cho tôi
Một tùy chọn khác cho cùng kết quả với hoạt hình Constraintset:
1) Đặt tất cả các chế độ xem hoạt hình trong một ConstraintLayout
2) Làm động nó từ mã như thế này (nếu bạn muốn thêm một số hiệu ứng tùy thuộc vào bạn .. đây chỉ là ví dụ)
menuItem1 và menuItem2 là FABs đầu tiên và thứ hai trong menu, descriptionItem1 và descriptionItem2 là mô tả bên trái của menu, parentConstraintLayout là gốc rễ ConstraintLayout Mà chứa tất cả các quan điểm động, isMenuOpened được một số chức năng để thay đổi mở / đóng cờ trong tiểu bang
Tôi đặt mã hoạt hình trong tập tin mở rộng nhưng nó không cần thiết.
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)
}