我是靠谱客的博主 寒冷蜜蜂,这篇文章主要介绍Android实现卫星菜单效果,现在分享给大家,希望可以做个参考。

前言

最近需求中,需要实现 卫星菜单的需求,最终通过自定义View和动画属性来实现,具体功能如下:

1.自定义View

复制代码
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
import android.content.Context; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; import android.view.animation.Animation; import android.view.animation.AnimationSet; import android.view.animation.AnimationUtils; import android.view.animation.RotateAnimation; import android.view.animation.TranslateAnimation; import com.xinrui.headsettest.R; /** * 卫星菜单 */ public class SatelliteView extends ViewGroup { private View mBtnView; private MenuStatus mBStatus = MenuStatus.STATUS_CLOSE; private onSubItemClickListener onListener; public enum MenuStatus { STATUS_OPEN, STATUS_CLOSE } //子菜单点击接口 public interface onSubItemClickListener { void onItemClick(View view, int position); } public void setOnSubItemClickListener(onSubItemClickListener mListener) { this.onListener = mListener; } public SatelliteView(Context context) { super(context); // this(context, null); } public SatelliteView(Context context, AttributeSet attrs) { super(context, attrs); // this(context, attrs, 0); } public SatelliteView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int count = getChildCount(); for (int i = 0; i < count; i++) { measureChild(getChildAt(i), widthMeasureSpec, heightMeasureSpec); } super.onMeasure(widthMeasureSpec, heightMeasureSpec); } //添加布局,就是所要显示的控件View @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { if (changed) { //主菜单按钮 onMainButton(); //子菜单按钮 onSubItemButton(); } } //获取主菜单按钮 private void onMainButton() { mBtnView = getChildAt(0); mBtnView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { //主菜单动画旋转动画 Animation rotateAnim = AnimationUtils.loadAnimation(getContext(), R.anim.satellite_anim); mBtnView.startAnimation(rotateAnim); //子菜单动画 subItemAnim(); } }); int l, t, r = 0, b = 0; int mWidth = mBtnView.getMeasuredWidth(); int mHeight = mBtnView.getMeasuredHeight(); l = getMeasuredWidth() - mWidth; t = getMeasuredHeight() - mHeight; mBtnView.layout(l, t, getMeasuredWidth(), getMeasuredHeight()); } //获取子菜单按钮 private void onSubItemButton() { int count = getChildCount(); for (int i = 0; i < count - 1; i++) { View childView = getChildAt(i + 1); //开始时不呈现子菜单 childView.setVisibility(View.GONE); int radius = 350; int cl, ct, cr, cb; cr = (int) (radius * Math.sin(Math.PI / 2 / (count - 2) * i)); cb = (int) (radius * Math.cos(Math.PI / 2 / (count - 2) * i)); int cWidth = childView.getMeasuredWidth(); int cHeight = childView.getMeasuredHeight(); cl = getMeasuredWidth() - cWidth - cr; ct = getMeasuredHeight() - cHeight - cb; //layout(l,t,r,b);前两参数决定位置,后两参数决定大小 //参数(1,t)为View控件的左上角坐标 // (r-l,b-t)为View控件大小,r-l为控件宽度,b-t为控件高度 childView.layout(cl, ct, getMeasuredWidth() - cr, getMeasuredHeight() - cb); } } //子菜单散开回笼动画 public void subItemAnim() { int count = getChildCount(); for (int i = 0; i < count - 1; i++) { final View childView = getChildAt(i + 1); //点击主菜单后,子菜单就立刻呈现,否则后面的动画无法完成 childView.setVisibility(VISIBLE); int radius = 350; int l, t, r, d; r = (int) (radius * Math.sin(Math.PI / 2 / (count - 2) * i)); d = (int) (radius * Math.cos(Math.PI / 2 / (count - 2) * i)); // int cWidth = cView.getMeasuredWidth(); // int cHeight = cView.getMeasuredHeight(); // // l = getMeasuredWidth() - cWidth - r; // t = getMeasuredHeight() - cHeight - d; AnimationSet mAnimationSet = new AnimationSet(true); Animation mTranAnimation = null; if (mBStatus == MenuStatus.STATUS_CLOSE) { //散开动画 mTranAnimation = new TranslateAnimation(r, 0, d, 0); childView.setClickable(true); childView.setFocusable(true); } else { //回笼动画 mTranAnimation = new TranslateAnimation(0, r, 0, d); childView.setClickable(false); childView.setFocusable(false); } mTranAnimation.setDuration(300); // tranAnim.setFillAfter(true); //让最后一帧的动画不消失 mTranAnimation.setStartOffset(100 * i / count); mTranAnimation.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { if (mBStatus == MenuStatus.STATUS_CLOSE) { childView.setVisibility(GONE); } } @Override public void onAnimationRepeat(Animation animation) { } }); Animation rotateAnim = new RotateAnimation( 0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); rotateAnim.setDuration(300); // rotateAnim.setFillAfter(false); mAnimationSet.addAnimation(rotateAnim); mAnimationSet.addAnimation(mTranAnimation); childView.startAnimation(mAnimationSet); //散开后子菜单的点击监听事件 final int pos = i + 1; childView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (onListener != null) { onListener.onItemClick(childView, pos); } //散开后点击子菜单动画 subItemClickAnim(pos - 1); changStatus(); } }); } changStatus(); } //监听子菜单状态改变 private void changStatus() { mBStatus = (mBStatus == MenuStatus.STATUS_CLOSE ? MenuStatus.STATUS_OPEN : MenuStatus.STATUS_CLOSE); } //散开后点击子菜单动画 private void subItemClickAnim(int pos) { int count = getChildCount(); for (int i = 0;i<count-1;i++) { View mChildView = getChildAt(i+1); if(i == pos) { //变大,变透明 mChildView.startAnimation(toBig()); } else { //变小,变透明 mChildView.startAnimation(toSmall()); } mChildView.setClickable(false); mChildView.setFocusable(false); } } //变大,变透明 private Animation toBig(){ Animation big = AnimationUtils.loadAnimation(getContext(), R.anim.bigalpha); return big; } //变小,变透明 private Animation toSmall(){ Animation small = AnimationUtils.loadAnimation(getContext(),R.anim.smallalpha); return small; } //给ListView调用 public boolean isOpen() { return mBStatus == MenuStatus.STATUS_OPEN; } }

2.SatelliteActivity

复制代码
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
import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.AbsListView; import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.Toast; import com.xinrui.headsettest.arc.SatelliteView; import java.util.ArrayList; import java.util.List; public class SatelliteActivity extends Activity { private SatelliteView mSatelliteView; private ListView mListView; private List<String> mData; private ArrayAdapter mAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.satellite_layout); mSatelliteView = (SatelliteView) findViewById(R.id.view_arc); mSatelliteView.setOnSubItemClickListener(new SatelliteView.onSubItemClickListener() { @Override public void onItemClick(View view, int position) { Toast.makeText(SatelliteActivity.this, "position" + position, Toast.LENGTH_SHORT).show(); } }); initListView(); } private void initListView() { mListView = (ListView) findViewById(R.id.listview); mData = new ArrayList<String>(); for (int i = 'A'; i <= 'z'; i++) { mData.add((char) i + ""); } mAdapter = new ArrayAdapter<String>( SatelliteActivity.this, android.R.layout.simple_list_item_1, mData); mListView.setAdapter(mAdapter); mListView.setOnScrollListener(new AbsListView.OnScrollListener() { @Override public void onScrollStateChanged(AbsListView view, int scrollState) { } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { if (mSatelliteView.isOpen()) { mSatelliteView.subItemAnim(); } } }); } }

3.satellite_layout.xml

复制代码
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
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <ListView android:id="@+id/listview" android:layout_width="match_parent" android:layout_height="match_parent"/> <com.xinrui.headsettest.arc.SatelliteView android:id="@+id/view_arc" android:layout_width="match_parent" android:layout_height="match_parent"> <RelativeLayout android:layout_width="wrap_content" android:layout_height="wrap_content"> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:src="@drawable/menu" /> </RelativeLayout> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/camera" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/chat" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/contacts" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/music" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/moon" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/location" /> </com.xinrui.headsettest.arc.SatelliteView> </RelativeLayout>

4.anim动画 在res 新建anim文件夹

satellite_anim.xml

复制代码
1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <rotate android:duration="300" android:fromDegrees="0" android:toDegrees="360" android:pivotX="50%" android:pivotY="50%"/> </set>

bigalpha.xml

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!--android:fillAfter="true"得加,取动画结束后的最后一帧--> <set xmlns:android="http://schemas.android.com/apk/res/android" android:fillAfter="true"> <alpha android:duration="200" android:fromAlpha="1" android:toAlpha="0"/> <scale android:duration="200" android:fromXScale="1" android:fromYScale="1" android:toXScale="3" android:toYScale="3" android:pivotX="50%" android:pivotY="50%" /> </set>

smallalpha.xml

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!--android:fillAfter="true"得加,取动画结束后的最后一帧--> <set xmlns:android="http://schemas.android.com/apk/res/android" android:fillAfter="true"> <alpha android:duration="200" android:fromAlpha="1" android:toAlpha="0"/> <scale android:duration="200" android:fromXScale="1" android:fromYScale="1" android:toXScale="0" android:toYScale="0" android:pivotX="50%" android:pivotY="50%" /> </set>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持靠谱客。

最后

以上就是寒冷蜜蜂最近收集整理的关于Android实现卫星菜单效果的全部内容,更多相关Android实现卫星菜单效果内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(101)

评论列表共有 0 条评论

立即
投稿
返回
顶部