Menu thư viện hỗ trợ thiết kế mở rộng (FAB) có thể mở rộng


172

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:

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



Tôi đã kiểm tra tất cả các tài liệu nhưng dường như không có bất kỳ dấu hiệu nào của menu FAB :(
EkKoZ

8
Bạn có thể xem thư viện FloatingActionButton này .
Markus Rubey

3
@MarkusRubey cảm ơn, thực sự đó là cái tôi đang sử dụng vào lúc này, chỉ là tôi muốn làm nó với bản địa, nhưng rõ ràng nó không thể thực hiện được.
EkKoZ

Có rất nhiều thư viện mã nguồn mở, có thể hoàn thành công việc. Kiểm tra cái này: github.com/futuresimple/android-floating-action-button
capt.swag

Câu trả lời:


143

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.

  1. Nút nổi nhanh (wangjiegulu)
  2. Nút hành động nổi (Clans)
  3. Nút hành động nổi (makovkastar)
  4. Nút hành động nổi trên Android (Futuresimple)

Tôi đang sử dụng cái thứ 4


31
tốt, ý tưởng là để làm điều đó với thư viện thiết kế riêng, tôi biết có rất nhiều thư viện đã thực hiện tính năng này. Cảm ơn vì đã trả lời.
EkKoZ

Bạn đã tìm thấy bất kỳ vấn đề với cái thứ tư? Của tôi không hiển thị trên kẹo mút + thiết bị. Ngoài ra, màu và văn bản lớp phủ nền không hoạt động
Ajith Memana

@AjithMemana Không. Ứng dụng của tôi đang được sản xuất cho hơn 100 nghìn người dùng và tôi chưa bao giờ gặp sự cố như bạn đã đề cập.
Aritra Roy

Bạn có thể vui lòng cung cấp cho tôi một liên kết đến ứng dụng của bạn? Tôi cần một cái gì đó tương tự như những gì được hiển thị ở trên, cùng với một nền mờ bao phủ màn hình khi nhấp vào nút.
Ajith Memana

2
Lưu ý, Clans và makovkastar không còn được hỗ trợ. Tôi nghi ngờ điều này là do những cải tiến trong thư viện thiết kế FAB
Phản đối trung thực

161

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

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


8
thậm chí việc thêm nhãn vào menu cũng đơn giản, bạn chỉ cần thêm FAB bên trong Linearlayout với một số textview dưới dạng nhãn và sau đó, toàn bộ bố cục tuyến tính không quên ẩn và hiển thị bố cục tuyến tính bên trong chức năng mở và đóng
HAXM

1
nhưng prashant đã tạo xml riêng cho hoạt hình, nhưng giải pháp của tôi không cần thêm xml cho hoạt hình, vì vậy hãy tin rằng câu trả lời của tôi tốt hơn, vì nó không cần thêm dòng mã để tạo hiệu ứng cho chế độ xem.
HAXM

2
Đó là câu trả lời tốt nhất. Bạn có thể sử dụng FAB thực từ thư viện thiết kế và nó không được khen ngợi.
Stephane Mathis

3
Điều tôi cũng thích về cách tiếp cận này là vì chúng tôi đang sử dụng Android FAB, rất nhiều nền tảng đã được thực hiện. ví dụ thay vì viết hành vi xem tùy chỉnh từ đầu (vì các thư viện không mở rộng FAB), bạn chỉ có thể mở rộng hành vi fab gốc, đó là một loạt mã lớn đã có sẵn
RJFares

1
@droidHeaven hãy dùng framelayout và đặt tất cả FAB của bạn vào đó
HAXM

31
  • 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

Dự án thanh toán 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

Menu hành động nổi với Textview nhãn trong Gia đình phông chữ chữ thảo mới của Android

Menu hành động nổi với Textview nhãn trong phông chữ Roboto mới của gia đình Android



7

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ó :)


Giải thích tuyệt vời! Tôi đang khám phá thư viện đó nhưng tôi gặp khó khăn khi sử dụng nó để căn chỉnh FAB giữa hai Chế độ xem. Loại những gì nó được hỏi trong câu hỏi này stackoverflow.com/questions/24459352/ . Bất kỳ ý tưởng về làm thế nào để làm điều đó? layout_anchorlayout_anchorGravitykhông làm việc cho tôi
acrespo

Thư viện của Futuresimple không cho phép một biểu tượng duy nhất trên dấu cộng mặc định với phần tử FloatingActionMothy của nó
Odaym

7

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:

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


Đơn giản và hoạt động tốt. Tôi sẽ đề nghị mặc dù bạn thêm các chi tiết ở đây thay vì liên kết hướng dẫn trong trường hợp liên kết bị hỏng trong tương lai. Một điều nữa, tôi vừa học được rằng thư viện không còn phát triển nữa, thật đáng buồn.
Ahmed salah

3

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

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


Một số nhận xét mà tôi đã thực hiện cho các câu trả lời tương tự khác. Tôi gặp sự cố khi sử dụng nó để căn chỉnh FAB giữa hai Chế độ xem. Loại những gì nó được hỏi trong câu hỏi này stackoverflow.com/questions/24459352/ . Bất kỳ ý tưởng về làm thế nào để làm điều đó? layout_anchorlayout_anchorGravitykhông làm việc cho tôi
acrespo

0

Một tùy chọn khác cho cùng kết quả với hoạt hình Constraintset:

ví dụ hoạt hình fab

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ụ)

menuItem1menuItem2 là FABs đầu tiên và thứ hai trong menu, descriptionItem1descriptionItem2 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)
}
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.