Android Tasarım Destek Kütüphanesi genişletilebilir Kayan Eylem Düğmesi (FAB) menüsü


172

Artık Android Tasarım Destek Kütüphanesi çıktı, kimse Inbox App fab gibi onunla genişletilmiş Fab menüsünü uygulamak biliyor mu?

Şöyle görünmelidir:

resim açıklamasını buraya girin



Zaten tüm belgeleri kontrol ettim ama görünüşe göre FAB menüsünün hiçbir işareti yok :(
EkKoZ

8
Bu FloatingActionButton kütüphanesine göz atabilirsiniz .
Markus Rubey

3
@MarkusRubey teşekkürler, aslında şu anda kullandığım thats, onun sadece yerel olanla yapmak istedim, ama görünüşe göre henüz mümkün değil.
EkKoZ

İşi halledebilecek çok sayıda açık kaynak kütüphanesi var. Bunu kontrol edin: github.com/futuresimple/android-floating-action-button
capt.swag

Yanıtlar:


143

Şu anda, Tasarım Kitaplığı'nda bir pencere öğesi yoktur. Bunu hızlı ve kolay yapmanın tek yolu üçüncü taraf kütüphaneleri kullanmaktır.

Bunu açıkça Tasarım Kitaplığı'nı kullanarak da yapabilirsiniz, ancak çok büyük bir çalışma olacak ve çok zaman alacaktır. Bunu başarmanıza yardımcı olabilecek bazı yararlı kütüphanelerden bahsettim.

  1. Hızlı Yüzen Düğme (wangjiegulu)
  2. Yüzer Eylem Düğmesi (Klanlar)
  3. Yüzer Eylem Düğmesi (makovkastar)
  4. Android Kayan İşlem Düğmesi (futuresimple)

Ben dördüncüsünü kullanıyorum.


31
iyi, fikir yerel tasarım kütüphanesi ile yapmak oldu, ben zaten bu özelliği yapan birçok kütüphane olduğunu biliyorum. cevabın için teşekkürler.
EkKoZ

Dördüncüsüyle ilgili herhangi bir sorun buldunuz mu? Benimki lolipop + cihazlarda görünmüyor. Ayrıca arka plan kaplaması rengi ve metni çalışmıyor
Ajith Memana

@AjithMemana Hayır. Uygulamam 100.000'den fazla kullanıcıya üretiliyor ve bahsettiğiniz gibi hiç sorun yaşamadım.
Aritra Roy

Lütfen uygulamanıza bir bağlantı verebilir misiniz? Düğmeye tıklandığında ekranı kapsayan yarı saydam bir arka planla birlikte yukarıda gösterilene benzer bir şeye ihtiyacım var.
Ajith Memana

2
Not olarak, Klanlar ve makovkastar artık desteklenmemektedir. Bunun FAB tasarım kütüphanesindeki iyileştirmelerden kaynaklandığından şüpheleniyorum
Dürüst İtirazlar

162

Animasyonlu FAB menüsünü herhangi bir kütüphane kullanmadan uygulamak veya animasyonlar için büyük xml kodu yazmak için daha iyi bir yaklaşım var. umarım bu, bunu uygulamak için basit bir yola ihtiyaç duyan biri için gelecekte yardımcı olacaktır.

Sadece animate().translationY()fonksiyonunu kullanarak , aşağıdaki kodumda yaptığım herhangi bir görünümü yukarı veya aşağı canlandırabilir , github'da tam kodu kontrol edebilirsiniz . Kotlin'de aynı kodu arıyorsanız, kotlin kodu repo Animasyon FAB Menüsünü kontrol edebilirsiniz .

önce tüm FAB'nizi aynı yerde tanımlayın, böylece birbirleriyle örtüşürler, FAB'yi tıklayıp diğerini göstermek istediğiniz olmalıdır. Örneğin:

    <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" />

Şimdi java sınıfınızda tüm FAB'nizi tanımlayın ve aşağıda gösterildiği gibi tıklayın:

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

Kullan animation().translationY()senin FAB canlandırmak, ben sadece daha yüksek veya daha düşük çözünürlüklü çözünürlüğe sahip ekran uyumluluğu etkileyecek bir int kullanarak beri DP bu yöntemin özelliği kullanmayı tercih ediyorum. Aşağıda gösterildiği gibi:

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

Şimdi yukarıda belirtilen boyutu aşağıda gösterildiği gibi res-> değerleri-> dimens.xml içinde tanımlayın:

    <dimen name="standard_55">55dp</dimen>
<dimen name="standard_105">105dp</dimen>
<dimen name="standard_155">155dp</dimen>

Bu çözümün gelecekte basit çözüm arayan insanlara yardımcı olacağını umuyoruz.

REDAKTE

FAB üzerine etiket eklemek istiyorsanız, yatay bir LinearLayout alın ve etiket olarak textview ile FAB'yi koyun ve bunu yaparken herhangi bir sorun bulursanız, düzenleri canlandırın, örnek kodumu github'da kontrol edebilirsiniz, geriye dönük uyumluluğa el koydum Bu örnek koddaki sorunlar. Github'daki FABMenu için örnek kodumu kontrol et

Backpress'teki FAB'yi kapatmak için onBackPress () öğesini aşağıda gösterildiği gibi geçersiz kılın:

    @Override
public void onBackPressed() {
    if(!isFABOpen){
        this.super.onBackPressed();
    }else{
        closeFABMenu();
    }
}

Ekran Görüntüsü FAB ile de başlık var, çünkü ben örnek uygulama mevcut ingithub almak

resim açıklamasını buraya girin


8
menüye etiket eklemek bile basittir, sadece FAB'yi bir Linearlayout'a etiket olarak bazı metin görünümleri ile eklemeniz yeterlidir ve bundan sonra tüm doğrusal düzeni canlandırın açık ve kapalı fonksiyonu içindeki doğrusal düzeni gizlemeyi ve göstermeyi
unutmaz

1
ancak prashant animasyon için ayrı bir xml yapmıştı, ancak çözümümün animasyon için fazladan bir xml'ye ihtiyacı yok, bu yüzden görünümü canlandırmak için ekstra kod satırına ihtiyaç duymadığından cevabımın daha iyi olduğuna inanıyorum.
HAXM

2
En iyi cevap bu. Gerçek FAB'yi tasarım kitaplığından kullanabilirsiniz ve bu kadar karmaşık değil.
Stephane Mathis

3
Ben de bu yaklaşım hakkında sevdim android FAB kullandığımız için, zemin bir sürü zaten yapılmış olmasıdır. örneğin, özel görünüm davranışını sıfırdan yazmak yerine (kütüphaneler
FAB'yi

1
@droidHeaven bir framelayout alın ve tüm
FAB'nizi

31
  • Önce Etkinlik düzeni xml dosyanızda menü düzenlerini oluşturun. Örneğin, yatay yönlendirmeli doğrusal bir düzen ve etiket için bir TextView, ardından TextView'in yanında bir Kayan İşlem Düğmesi ekleyin.

  • İhtiyacınıza ve numaranıza göre menü düzenleri oluşturun.

  • Bir Temel Yüzen Eylem Düğmesi oluşturun ve tıklandığında Menü Düzenlerinin görünürlüğünü değiştirin.

Referans için aşağıdaki kodu kontrol edin ve daha fazla bilgi için github'dan projeme bakın

Github'dan ödeme projesi

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

Bunlar animasyonlar-

FAB Menüsünün açılış animasyonu:

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

FAB Menüsünün kapanış animasyonu:

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

Ardından, Etkinliğimde FAB menüsünü göstermek ve gizlemek için yukarıdaki animasyonları kullandım:

Fab Menüsünü Göster:

  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;

}

Fab Menüsünü Kapat:

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;

}

İşte Activity sınıfı -

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

İşte ekran görüntüleri

Android'in yeni Cursive Yazı Tipi Ailesinde Etiket Metin Görüntüleme ile Yüzer Eylem Menüsü

Android'in yeni Roboto Yazı Tipi Ailesinde Etiket Metin Görüntüleme ile Yüzer Eylem Menüsü



7

Gelen kutusu yüzen eylem düğmesine benzer bir şey oluşturmaya çalıştığımda kendi özel bileşen oluşturmayı düşündüm.

FAB düğmesi ve 3 tane daha FAB altına yerleştirilmiş sabit yükseklikte (genişletilmiş menü içerecek şekilde) basit çerçeve düzeni olacaktır. FAB'ı tıkladığınızda FAB'nin altından çevirmek için diğer düğmelere animasyon uygulamanız yeterlidir.

Bunu yapan bazı kütüphaneler vardır (örneğin, https://github.com/futuresimple/android-floating-action-button ), ancak kendiniz oluşturursanız her zaman daha eğlencelidir :)


Mükemmel açıklama! Bu kütüphaneyi araştırıyorum ama FAB'yi iki Views arasında hizalamakta sorun yaşıyorum. Bu soruda biraz soru soruluyor stackoverflow.com/questions/24459352/… . Nasıl yapılacağı hakkında bir fikrin var mı? layout_anchorve layout_anchorGravitybenim için çalışmıyor
acrespo

Futuresimple'ın kütüphanesi, FloatingActionMenu öğesine varsayılan olarak gelen artı üzerinde benzersiz bir simgeye izin vermiyor
Odaym

7

FloatingActionMenu kütüphanesini kullanabilir veya adım adım eğitim için buraya tıklayabilirsiniz . Öğreticinin çıktısı:

resim açıklamasını buraya girin


Basit ve iyi çalışıyor. Bağlantı gelecekte devam ederse öğretici bağlamak yerine ayrıntıları buraya eklemenizi öneririm. Başka bir şey, yeni öğrendim ki kütüphane artık maalesef geliştirilmiyor.
Ahmed salah


0

ConstraintSet animasyonu ile aynı sonuç için başka bir seçenek:

fab animasyon örneği

1) Tüm animasyonlu görünümleri bir ConstraintLayout'a koyun

2) Böyle bir koddan canlandırın (biraz daha fazla efekt istiyorsanız size kalmış .. bu sadece örnek)

menuItem1 ve menuItem2 , menüdeki ilk ve ikinci FAB'lardır, descriptionItem1 ve descriptionItem2 , menünün solundaki açıklamadır, parentConstraintLayout , tüm animasyonlu görünümleri içeren kök ConstraintLayout köküdür, isMenuOpened açık / kapalı bayrağı değiştirmek açık / kapalı bayrağı değiştirmek için kullanılan bir işlevdir

Animasyon kodunu uzantı dosyasına koydum ama gerekli değil.

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)
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.