Android 디자인 지원 라이브러리 확장 가능 부동 액션 버튼(FAB) 메뉴
Android Design Support Library가 출시되었으니 Inbox App의 Fab과 같이 확장된 Fab 메뉴를 구현하는 방법을 아는 사람이 있습니까?
다음과 같이 표시해야 합니다.
라이브러리를 사용하지 않고 애니메이션 FAB 메뉴를 구현하거나 애니메이션을 위한 거대한 xml 코드를 작성할 수 있는 더 나은 접근 방식을 얻었습니다.이것이 미래에 이것을 구현할 간단한 방법이 필요한 사람에게 도움이 되기를 바랍니다.
그냥사기를 사용하는 것.animate().translationY()
기능, 당신은 아래 코드에서 내가 했던 것처럼 위나 아래의 모든 보기를 애니메이션화할 수 있습니다. 완전한 코드화를 확인하십시오.코틀린에서 동일한 코드를 찾는 경우 코틀린 코드 repo Animating FAB Menu를 확인할 수 있습니다.
먼저 모든 FAB를 동일한 위치에 정의하여 서로 겹치도록 합니다. 맨 위에 FAB는 클릭하고 다른 FAB를 표시해야 합니다.예:
<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" />
이제 Java 클래스에서 모든 FAB를 정의하고 아래와 같은 클릭을 수행합니다.
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();
}
}
});
을 합니다.animation().translationY()
당신의 FAB를 애니메이션화하기 위해서는, 오직 int를 사용하는 것이 더 높은 해상도 또는 더 낮은 해상도로 디스플레이 호환성에 영향을 미치기 때문에, 나는 당신이 DP에서 이 방법의 속성을 사용하는 것을 선호합니다.아래와 같이:
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);
}
이제 아래와 같이 res->values->dimens.xml 내부에 위에서 언급한 차원을 정의합니다.
<dimen name="standard_55">55dp</dimen>
<dimen name="standard_105">105dp</dimen>
<dimen name="standard_155">155dp</dimen>
이 모든 것이 이 솔루션이 간단한 해결책을 찾는 미래의 사람들에게 도움이 되기를 바라는 것입니다.
편집됨
FAB 위에 레이블을 추가하려면 수평 선형 레이아웃을 가져다가 텍스트 뷰가 있는 FAB를 레이블로 지정하고 레이아웃을 애니메이션화하면 문제가 발견되면 제 샘플 코드 github을 확인할 수 있습니다. 이 샘플 코드에서 모든 하위 호환성 문제를 처리했습니다.Github의 FAB Menu 샘플 코드 확인
Backpress에서 FAB를 닫으려면 아래와 같이 Backpress()에서 재정의합니다.
@Override
public void onBackPressed() {
if(!isFABOpen){
this.super.onBackPressed();
}else{
closeFABMenu();
}
}
스크린샷은 제가 허브를 제시하는 샘플 앱에서 가져오기 때문에 FAB와 함께 제목도 있습니다.
먼저 활동 레이아웃 xml 파일에 메뉴 레이아웃을 만듭니다.예를 들어 수평 방향이 있는 선형 레이아웃의 경우 레이블에 대한 텍스트 보기를 포함한 다음 텍스트 보기 옆에 부동 작업 버튼을 포함합니다.
필요에 따라 메뉴 레이아웃을 만듭니다.
기본 부동 수행 단추를 만들고 단추를 클릭하면 메뉴 레이아웃의 가시성이 변경됩니다.
참조를 위해 아래 코드를 확인하고 자세한 내용은 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>
이게 바로 애니메이션입니다.
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>
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>
그런 다음 활동에서 위의 애니메이션을 사용하여 FAB 메뉴를 표시하거나 숨깁니다.
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;
}
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;
}
활동 클래스입니다.
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();
}
}
여기 스크린샷이 있습니다.
내가 받은 편지함 부동 동작 버튼과 비슷한 것을 만들려고 했을 때 나는 자체 사용자 정의 구성 요소를 만드는 것에 대해 생각했습니다.
FAB 버튼이 포함된 고정 높이(확장 메뉴 포함)와 FAB 아래에 3개 이상 배치된 간단한 프레임 레이아웃입니다. FAB를 클릭하면 FAB 아래에서 번역할 다른 버튼을 애니메이션화하기만 하면 됩니다.
그렇게 하는 라이브러리도 있습니다(예: https://github.com/futuresimple/android-floating-action-button), 하지만 직접 만들면 항상 더 재미있습니다:).
여전히 이 기능을 찾고 있는 경우:저는 확장 가능한 팹(https://github.com/nambicompany/expandable-fab) )이라는 안드로이드 라이브러리를 만들었습니다.
재료 설계 사양은 이 기능을 '스피드 다이얼'이라고 하며, 확장 가능한 패브릭은 많은 추가 기능과 함께 이 기능을 구현합니다.
거의 모든 항목(색상, 텍스트, 크기, 배치, 여백, 애니메이션 등)을 사용자 지정할 수 있으며 옵션(Overlay, FabOptions, 레이블 또는 아이콘 등이 필요 없음)도 선택할 수 있습니다.모든 속성은 XML 레이아웃을 통해 또는 원하는 대로 프로그래밍 방식으로 액세스하거나 설정할 수 있습니다.
100% Kotlin으로 작성되었지만 전체 JavaDoc 및 KDoc과 함께 제공됩니다(공개된 API는 잘 문서화되어 있습니다).예제 앱도 함께 제공되므로 0 코딩으로 다양한 사용 사례를 확인할 수 있습니다.
Github: https://github.com/nambicompany/expandable-fab
도서관 웹사이트(전체 설명서 링크 포함): https://nambicompany.github.io/expandable-fab/
제약 조건 집합 애니메이션과 동일한 결과에 대한 다른 옵션:
모든 애니메이션 뷰를 하나의 구속조건 레이아웃에 배치
이런 코드에서 애니메이션을 만듭니다. (만약 당신이 더 많은 효과를 원한다면 그것은 당신에게 달려있습니다.이것은 단지 예시일 뿐입니다)
menuItem1 및 menuItem2는 메뉴의 첫 번째 및 두 번째 FAB, 설명항목 1 및 설명Item2는 메뉴 왼쪽의 설명이고, parentConstraintLayout은 모든 애니메이션 보기를 포함하는 루트ConstraintLayout입니다. isMenuOpened는 상태에서 열기/닫기 플래그를 변경하는 일부 기능입니다.
나는 확장 파일에 애니메이션 코드를 넣었지만 필요하지 않습니다.
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)
}
언급URL : https://stackoverflow.com/questions/30699302/android-design-support-library-expandable-floating-action-buttonfab-menu
'sourcecode' 카테고리의 다른 글
server.cnf에 대한 my.cnf에서 skip-name-resolve?를 추가할 위치는 어디입니까? (0) | 2023.08.02 |
---|---|
고유한 제약 조건을 위반하지 않고 MySQL에서 두 행의 값을 교환하는 방법은 무엇입니까? (0) | 2023.08.02 |
Android 앱과 웹 서버 간의 데이터 동기화 (0) | 2023.08.02 |
타임스탬프가 지정된 이벤트 일치 오류: 일치 요소를 찾지 못했습니다. (0) | 2023.08.02 |
jQuery에서 null 객체를 확인하는 방법 (0) | 2023.08.02 |