本篇文章学习鸿洋自定义控价慕课网 https://www.imooc.com/video/6232
一.自定义属性attr文件自定义属性方法。
<attr name="position">
<enum name="left_top" value="0"></enum>
<enum name="left_bottom" value="1"></enum>
<enum name="right_bottom" value="3"></enum>
<enum name="right_top" value="2"></enum>
</attr>
<attr name="raidus" format="dimension"></attr>
<declare-styleable name="ArcMenu">
<attr name="raidus"></attr>
<attr name="position"></attr>
</declare-styleable>
二.具体功能
public class ArcMenu extends ViewGroup implements View.OnClickListener {
private static final int POS_LEFT_TOP = 0;
private static final int POS_LEFT_BOTTOM = 1;
private static final int POS_RIGHT_TOP = 2;
private static final int POS_RIGHT_BOTTOM = 3;
private String TAG = "ArcMenu";
public Positon mPosition = Positon.RIGHT_BOTTOM;
private int mRadius;
private Status mCurrentState = Status.CLOAST;
private View mButton;
private onMenuClickListener onMenuClickListener;
public enum Positon {
LEFT_TOP, LEFT_BOTTON, RIGHT_TOP, RIGHT_BOTTOM
}
public enum Status {
OPEN, CLOAST
}
public ArcMenu(Context context) {
this(context, null);
}
public ArcMenu(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ArcMenu(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mRadius = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 100, getResources().getDisplayMetrics());
TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.ArcMenu, defStyleAttr, 0);
mRadius = (int) typedArray.getDimension(R.styleable.ArcMenu_raidus, mRadius);
int pos = typedArray.getInt(R.styleable.ArcMenu_position, POS_RIGHT_BOTTOM);
switch (pos) {
case POS_LEFT_TOP:
mPosition = Positon.LEFT_TOP;
break;
case POS_LEFT_BOTTOM:
mPosition = Positon.LEFT_BOTTON;
break;
case POS_RIGHT_TOP:
mPosition = Positon.RIGHT_TOP;
break;
case POS_RIGHT_BOTTOM:
mPosition = Positon.RIGHT_BOTTOM;
break;
}
Log.e(TAG, "mRaidus--" + mRadius + " pos--" + pos);
typedArray.recycle();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int count = getChildCount();
for (int i = 0; i < count; i++) {
measureChild(getChildAt(i), widthMeasureSpec, heightMeasureSpec);
}
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
if (changed) {
layoutCButton();
int count = getChildCount();
for (int i = 0; i < count - 1; i++) {
View child = getChildAt(i + 1);
child.setVisibility(GONE);
int cl = (int) (mRadius * Math.sin(Math.PI / 2 / (count - 2) * i));
int ct = (int) (mRadius * Math.cos(Math.PI / 2 / (count - 2) * i));
Log.e(TAG, "mPosition---" + mPosition + "child---" + count + " cl---" + cl + " ct---" + ct);
int cWidth = child.getMeasuredWidth();
int cHeight = child.getMeasuredHeight();
if (mPosition == Positon.LEFT_TOP) {
cl += 0;
ct += 0;
}
if (mPosition == Positon.LEFT_BOTTON) {
ct = getMeasuredHeight() - cHeight - ct - 0;
cl += 0;
}
if (mPosition == Positon.RIGHT_BOTTOM) {
ct = getMeasuredHeight() - cHeight - ct - 0;
cl = getMeasuredWidth() - cWidth - cl - 0;
}
if (mPosition == Positon.RIGHT_TOP) {
cl = getMeasuredWidth() - cWidth - cl - 0;
ct += 0;
}
child.layout(cl, ct, cl + cWidth, ct + cHeight);
}
}
}
// 定位主菜单按钮
private void layoutCButton() {
mButton = getChildAt(0);
mButton.setOnClickListener(this);
int l = 0;
int t = 0;
int width = mButton.getMeasuredWidth();
int height = mButton.getMeasuredHeight();
switch (mPosition) {
case LEFT_TOP:
l = t = 0;
break;
case LEFT_BOTTON:
l = 0;
t = getMeasuredHeight() - height - 0;
break;
case RIGHT_TOP:
l = getMeasuredWidth() - width - 0;
t = 0;
break;
case RIGHT_BOTTOM:
l = getMeasuredWidth() - width - 0;
t = getMeasuredHeight() - height - 0;
break;
}
mButton.layout(l, t, l + width, t + width);
}
public interface onMenuClickListener {
void onClick(View view, int pos);
}
public void setOnMenuClickListener(onMenuClickListener onMenuClickListener) {
this.onMenuClickListener = onMenuClickListener;
}
@Override
public void onClick(View v) {
rotateBtn(v, 0f, 360f, 300);
toggleMenu(300);
}
private void toggleMenu(int duration) {
int count = getChildCount();
for (int i = 0; i < count - 1; i++) {
final View child = getChildAt(i + 1);
child.setVisibility(VISIBLE);
int cl = (int) (mRadius * Math.sin(Math.PI / 2 / (count - 2) * i));
int ct = (int) (mRadius * Math.cos(Math.PI / 2 / (count - 2) * i));
int xflag = 1;
int yflag = 1;
if (mPosition == Positon.LEFT_TOP || mPosition == Positon.LEFT_BOTTON) {
xflag = -1;
}
if (mPosition == Positon.RIGHT_TOP || mPosition == Positon.LEFT_TOP) {
yflag = -1;
}
AnimationSet animationSet = new AnimationSet(true);
Animation tranAnim = null;
if (mCurrentState == Status.CLOAST) {
tranAnim = new TranslateAnimation(xflag * cl, 0, yflag * ct, 0);
} else {
tranAnim = new TranslateAnimation(0, xflag * cl, 0, yflag * ct);
}
tranAnim.setFillAfter(true);
tranAnim.setDuration(duration);
tranAnim.setStartOffset(i * 100 / count);
tranAnim.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
if (mCurrentState == Status.CLOAST) {
child.setVisibility(GONE);
}
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
RotateAnimation rotateAnimation = new RotateAnimation(0, 720, Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0);
rotateAnimation.setFillAfter(true);
rotateAnimation.setDuration(duration);
animationSet.addAnimation(rotateAnimation);
animationSet.addAnimation(tranAnim);
child.startAnimation(animationSet);
final int pos = i + 1;
child.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (onMenuClickListener != null) {
onMenuClickListener.onClick(child, pos);
}
menuItmeAnim(pos - 1);
changeStates();
}
});
}
changeStates();
}
private void menuItmeAnim(int pos) {
for (int j = 0; j < getChildCount() - 1; j++) {
View childView = getChildAt(j + 1);
if (j == pos) {
childView.startAnimation(scaleBigAnim());
} else {
childView.setAnimation(scaleSmallAnim());
}
}
}
private Animation scaleSmallAnim() {
AnimationSet animationSet = new AnimationSet(true);
ScaleAnimation scaleAnimation = new ScaleAnimation(1.0f, 0.0f, 1.0f, 0.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
AlphaAnimation alphaAnimation = new AlphaAnimation(1f, 0.0f);
animationSet.addAnimation(scaleAnimation);
animationSet.addAnimation(alphaAnimation);
animationSet.setDuration(300);
animationSet.setFillAfter(true);
return animationSet;
}
private Animation scaleBigAnim() {
AnimationSet animationSet = new AnimationSet(true);
ScaleAnimation scaleAnimation = new ScaleAnimation(1.0f, 2.0f, 1.0f, 2.0F, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
AlphaAnimation alphaAnimation = new AlphaAnimation(1f, 0);
animationSet.addAnimation(scaleAnimation);
animationSet.addAnimation(alphaAnimation);
animationSet.setDuration(300);
animationSet.setFillAfter(true);
return animationSet;
}
private void changeStates() {
if (mCurrentState == Status.CLOAST) {
mCurrentState = Status.OPEN;
} else {
mCurrentState = Status.CLOAST;
}
Log.d(TAG, "mCurrentState:" + mCurrentState);
}
private void rotateBtn(View v, float start, float end, int duration) {
Log.d("ArcMenu", "点了");
RotateAnimation rotateAnimation = new RotateAnimation(start, end, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
rotateAnimation.setDuration(duration);
rotateAnimation.setFillAfter(true);
v.startAnimation(rotateAnimation);
}
}
三.使用控价
MainActivity布局文件中使用,postion具体位置,raduis半径。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Main4Activity">
<com.tk.myviewproject.view.ArcMenu
android:layout_width="match_parent"
android:layout_height="match_parent"
app:position="left_top"
app:raidus="200dp">
<ImageView
android:id="@+id/id_button"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="@mipmap/ic_launcher"></ImageView>
<ImageView
android:layout_width="30dp"
android:layout_height="30dp"
android:src="@mipmap/ic_launcher"
android:tag="tag1"></ImageView>
<ImageView
android:layout_width="30dp"
android:layout_height="30dp"
android:src="@mipmap/ic_launcher"
android:tag="tag2"></ImageView>
<ImageView
android:layout_width="30dp"
android:layout_height="30dp"
android:src="@mipmap/ic_launcher"
android:tag="tag3"></ImageView>
<ImageView
android:layout_width="30dp"
android:layout_height="30dp"
android:src="@mipmap/ic_launcher"
android:tag="tag4"></ImageView>
</com.tk.myviewproject.view.ArcMenu>
</RelativeLayout>