이번에 프로젝트를 진행하면서 Floating Action Button들이 감추어져 있다가 특정 버튼을 누르면 위로 애니메이션 되면서 올라오는 기능을 추가해야 했는데, 기존에 구글링하면 많은 라이브러리가 나왔지만 내가 원하는 기능만 집어넣어 보기 위해서 이번에 진행할 때는 다른 라이브러리 없이 한번 직접 구현해 봤습니다.
위와 같은 동작을 하는 Floating Action Menu를 구현해 보려고 합니다.
코드는 아래와 같습니다.
- MainActivity.class
더보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
package com.kyungmin.floatingactionmenu;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
private FloatingActionMenu mFloatingActionMenu;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mFloatingActionMenu = findViewById(R.id.floating_action_menu);
mFloatingActionMenu.addFloatingActionMenu(R.string.fab_text_share, R.drawable.ic_share);
mFloatingActionMenu.addFloatingActionMenu(R.string.fab_text_reload, R.drawable.ic_refresh);
mFloatingActionMenu.addFloatingActionMenu(R.string.fab_text_lock, R.drawable.ic_lock);
mFloatingActionMenu.addFloatingActionMenu(R.string.fab_text_download, R.drawable.ic_download);
}
}
|
cs |
- FolatingActionMenu.class
더보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
package com.kyungmin.floatingactionmenu;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import androidx.annotation.Nullable;
import java.util.ArrayList;
public class FloatingActionMenu extends FrameLayout implements View.OnClickListener {
private static final String TAG = "FloatingActionMenu";
private Context mContext;
private FrameLayout mFrameLayout;
private CustomFloatingActionButton mMenuFab;
private boolean mIsFabShown = false;
private float mMenuHeight;
private ArrayList<CustomFloatingActionButton> mFabList = new ArrayList<>();
public FloatingActionMenu(Context context) {
super(context);
intiLayout(context, null, 0, 0);
}
public FloatingActionMenu(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
intiLayout(context, attrs, 0, 0);
}
public FloatingActionMenu(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
intiLayout(context, attrs, defStyleAttr, 0);
}
public FloatingActionMenu(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
intiLayout(context, attrs, defStyleAttr, defStyleRes);
}
private void intiLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
mContext = context;
mIsFabShown = false;
mFabList.clear();
mMenuHeight = getResources().getDimensionPixelOffset(R.dimen.fab_size) + getResources().getDimensionPixelOffset(R.dimen.fab_menu_padding) * 2;
View.inflate(mContext, R.layout.floating_action_menu, (ViewGroup) getRootView());
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mFrameLayout = findViewById(R.id.fab_menu_container);
mMenuFab = mFrameLayout.findViewById(R.id.menu_fab);
mMenuFab.setOnClickListener(this);
}
public void addFloatingActionMenu(int menuTextRes, int menuIconRes) {
CustomFloatingActionButton fab = new CustomFloatingActionButton(mContext);
fab.setMenuIconRes(menuIconRes);
fab.setMenuText(menuTextRes);
fab.setVisibility(View.GONE);
mFrameLayout.addView(fab, 0);
mFabList.add(0, fab);
ViewGroup.LayoutParams params = mFrameLayout.getLayoutParams();
params.height = (int) (mMenuHeight * mFrameLayout.getChildCount());
mFrameLayout.setLayoutParams(params);
}
@Override
public void onClick(View v) {
Log.d(TAG, "onClick()");
toggleFabMenu();
}
private void toggleFabMenu() {
Log.d(TAG, "toggleFabMenu()");
mIsFabShown = !mIsFabShown;
mMenuFab.rotateIcon(mIsFabShown ? 45 : 0);
for (int idx = 0; idx < mFabList.size(); ++idx) {
toggleFab(mFabList.get(idx), idx, mIsFabShown);
}
}
private void toggleFab(final View view, int idx, boolean isFabShown) {
if (isFabShown) {
view.animate().alpha(1).translationY((-1) * mMenuHeight * (idx + 1)).withStartAction(new Runnable() {
@Override
public void run() {
view.setVisibility(View.VISIBLE);
}
}).start();
} else {
view.animate().alpha(0).translationY(0).withEndAction(new Runnable() {
@Override
public void run() {
view.setVisibility(View.GONE);
}
}).start();
}
}
}
|
cs |
- CustomFolatingActionButton.class
더보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
package com.kyungmin.floatingactionmenu;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.Nullable;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
public class CustomFloatingActionButton extends LinearLayout {
private static final String TAG = "CustomFloatingActionButton";
private Context mContext;
private TextView mTextView;
private FloatingActionButton mFloatingActionButton;
private int mMenuTextRes;
private int mMenuIconRes;
public CustomFloatingActionButton(Context context) {
super(context);
intiLayout(context, null, 0, 0);
}
public CustomFloatingActionButton(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
intiLayout(context, attrs, 0, 0);
}
public CustomFloatingActionButton(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
intiLayout(context, attrs, defStyleAttr, 0);
}
public CustomFloatingActionButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
intiLayout(context, attrs, defStyleAttr, defStyleRes);
}
private void intiLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
mContext = context;
View.inflate(mContext, R.layout.custom_floating_action_button, (ViewGroup) getRootView());
TypedArray typedArray = mContext.obtainStyledAttributes(attrs, R.styleable.CustomFloatingActionButtonAttr, defStyleAttr, defStyleRes);
try {
mMenuTextRes = typedArray.getResourceId(R.styleable.CustomFloatingActionButtonAttr_menu_text, 0);
mMenuIconRes = typedArray.getResourceId(R.styleable.CustomFloatingActionButtonAttr_menu_icon, 0);
} finally {
typedArray.recycle();
}
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
setMenuText(mMenuTextRes);
setMenuIconRes(mMenuIconRes);
}
public void setMenuText(int menuTextRes) {
mMenuTextRes = menuTextRes;
if (mMenuTextRes > 0) {
mTextView = findViewById(R.id.fab_menu_text);
mTextView.setText(mMenuTextRes);
}
}
public void setMenuIconRes(int menuIconRes) {
mMenuIconRes = menuIconRes;
if (mMenuIconRes > 0) {
mFloatingActionButton = findViewById(R.id.fab_menu_icon);
mFloatingActionButton.setImageResource(mMenuIconRes);
}
}
public void rotateIcon(float angle) {
Log.d(TAG, "rotateIcon(): angle: " + angle);
if (mFloatingActionButton == null) {
mFloatingActionButton = findViewById(R.id.fab_menu_icon);
}
mFloatingActionButton.animate().rotation(angle).start();
}
}
|
cs |
직접 구현하다 보니 사소한 오류들이 있을것 같기도 하고 지금은 FloatingActionButton이 펼쳐지는 동작만 하는데, 추가적으로 배경을 Dim시켜야 할수도 있을것 같아서 좀더 고민이 필요할것 같다.
https://github.com/KyungminYu/CustomFloatingActionButton/tree/FloatingActionMenu
'ComputerScience > Android' 카테고리의 다른 글
[Android] SVG파일 안드로이드에 집어넣기 (0) | 2020.04.15 |
---|