Android 디자인 지원 라이브러리가 출시되었으므로받은 편지함 앱의 팹과 같이 확장 된 Fab 메뉴를 구현하는 방법을 아는 사람이 있습니까?
다음과 같이 보일 것입니다 :
Android 디자인 지원 라이브러리가 출시되었으므로받은 편지함 앱의 팹과 같이 확장 된 Fab 메뉴를 구현하는 방법을 아는 사람이 있습니까?
다음과 같이 보일 것입니다 :
답변:
현재 설계 라이브러리에는 위젯이 제공되지 않습니다. 빠르고 쉽게 할 수있는 유일한 방법 은 타사 라이브러리를 사용하는 것입니다.
분명히 디자인 라이브러리를 사용 하여이 작업을 수행 할 수는 있지만 엄청난 작업이며 많은 시간이 필요합니다. 나는 이것을 달성하는 데 도움이되는 유용한 라이브러리를 언급했다.
나는 네 번째 것을 사용하고 있습니다.
라이브러리를 사용하지 않고 애니메이션 FAB 메뉴를 구현하거나 애니메이션을위한 거대한 xml 코드를 작성하는 더 좋은 방법이 있습니다. 이것이 간단한 구현 방법이 필요한 사람에게 미래에 도움이되기를 바랍니다.
animate().translationY()
함수를 사용 하면 아래 코드에서 한 것처럼 모든 뷰를 위아래로 움직일 수 있습니다 .github에서 완전한 코드를 확인하십시오 . kotlin에서 동일한 코드를 찾고 있다면 kotlin code repo Animating FAB Menu를 확인하십시오 .
먼저 모든 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" />
이제 자바 클래스에서 모든 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에 레이블을 추가하려면 단순히 가로 LinearLayout을 가져 와서 텍스트보기가있는 레이블을 레이블로 사용 하고이 문제가있는 경우 레이아웃에 애니메이션을 적용하면 github에서 샘플 코드를 확인할 수 있습니다. 모든 하위 호환성을 처리했습니다. 해당 샘플 코드의 문제. Github에서 FABMenu에 대한 샘플 코드를 확인하십시오.
Backpress에서 FAB를 닫으려면 아래 표시된 것처럼 onBackPress ()를 재정의하십시오.
@Override
public void onBackPressed() {
if(!isFABOpen){
this.super.onBackPressed();
}else{
closeFABMenu();
}
}
스크린 샷에는 FAB과 제목이 있습니다 .Ingithub 샘플 앱 에서 가져 오기 때문입니다.
먼저 Activity layout xml 파일에서 메뉴 레이아웃을 작성하십시오. 예를 들어 가로 방향의 선형 레이아웃의 경우 레이블에 TextView를 포함시킨 다음 TextView 옆에 부동 작업 단추를 포함하십시오.
필요와 번호에 따라 메뉴 레이아웃을 만듭니다.
기본 부동 동작 버튼을 만들고 클릭하면 메뉴 레이아웃의 가시성이 변경됩니다.
아래 코드를 참조하고 자세한 내용은 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 ) 직접 작성하면 항상 더 재미 있습니다.)
layout_anchor
그리고 layout_anchorGravity
나를 위해 작동하지 않습니다
이 라이브러리를 사용 하여이 작업을 수행합니다 : https://github.com/futuresimple/android-floating-action-button
사용하기 매우 간단합니다.)
layout_anchor
그리고 layout_anchorGravity
나를 위해 작동하지 않습니다
ConstraintSet 애니메이션과 동일한 결과에 대한 또 다른 옵션 :
1) 모든 애니메이션 뷰를 하나의 ConstraintLayout에 넣습니다.
2) 이와 같은 코드에서 애니메이션을 적용하십시오 (더 많은 효과를 원하는 경우 .. 이것은 단지 예일뿐입니다)
menuItem1 및 menuItem2 는 메뉴의 첫 번째 및 두 번째 FAB이고 descriptionItem1 및 descriptionItem2 는 메뉴 왼쪽에 대한 설명이고 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)
}