1.自定义布局继承RelativeLayout:
public class composerLayout extends RelativeLayout {
public static byte RIGHTBOTTOM = 1, CENTERBOTTOM = 2, LEFTBOTTOM = 3, LEFTCENTER = 4, LEFTTOP = 5, CENTERTOP = 6, RIGHTTOP = 7,
RIGHTCENTER = 8;
private boolean hasInit = false;
private boolean areButtonsShowing = false;
private Context mycontext;
private ImageView cross;
private RelativeLayout rlButton;
private myAnimations myani;
private LinearLayout[] llayouts;
private int duretime = 300;
public composerLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.mycontext = context;
}
public composerLayout(Context context, AttributeSet attrs) {
super(context, attrs);
this.mycontext = context;
}
public composerLayout(Context context) {
super(context);
this.mycontext = context;
}
public void init(int[] imgResId, int showhideButtonId, int crossId, byte pCode, int radius, final int durationMillis) {
duretime = durationMillis;
int align1 = 12, align2 = 14;
if (pCode == RIGHTBOTTOM) {
align1 = ALIGN_PARENT_RIGHT;
align2 = ALIGN_PARENT_BOTTOM;
} else if (pCode == CENTERBOTTOM) {
align1 = CENTER_HORIZONTAL;
align2 = ALIGN_PARENT_BOTTOM;
} else if (pCode == LEFTBOTTOM) {
align1 = ALIGN_PARENT_LEFT;
align2 = ALIGN_PARENT_BOTTOM;
} else if (pCode == LEFTCENTER) {
align1 = ALIGN_PARENT_LEFT;
align2 = CENTER_VERTICAL;
} else if (pCode == LEFTTOP) {
align1 = ALIGN_PARENT_LEFT;
align2 = ALIGN_PARENT_TOP;
} else if (pCode == CENTERTOP) {
align1 = CENTER_HORIZONTAL;
align2 = ALIGN_PARENT_TOP;
} else if (pCode == RIGHTTOP) {
align1 = ALIGN_PARENT_RIGHT;
align2 = ALIGN_PARENT_TOP;
} else if (pCode == RIGHTCENTER) {
align1 = ALIGN_PARENT_RIGHT;
align2 = CENTER_VERTICAL;
}
RelativeLayout.LayoutParams thislps = (LayoutParams) this.getLayoutParams();
Bitmap mBottom = BitmapFactory.decodeResource(mycontext.getResources(), imgResId[0]);
if (pCode == CENTERBOTTOM || pCode == CENTERTOP) {
if (thislps.width != -1 && thislps.width != -2 && thislps.width < (radius + mBottom.getWidth() + radius * 0.1) * 2) {
thislps.width = (int) ((radius * 1.1 + mBottom.getWidth()) * 2);
}
} else {
if (thislps.width != -1 && thislps.width != -2 && thislps.width < radius + mBottom.getWidth() + radius * 0.1) {
thislps.width = (int) ((radius * 1.1 + mBottom.getWidth())*2);
}
}
if (pCode == LEFTCENTER || pCode == RIGHTCENTER) {
if (thislps.height != -1 && thislps.height != -2 && thislps.height < (radius + mBottom.getHeight() + radius * 0.1) * 2) {
thislps.width = (int) ((radius * 1.1 + mBottom.getHeight()) * 2);
}
} else {
if (thislps.height != -1 && thislps.height != -2 && thislps.height < radius + mBottom.getHeight() + radius * 0.1) {
thislps.height = (int) (radius * 1.1 + mBottom.getHeight());
}
}
this.setLayoutParams(thislps);
RelativeLayout rl1 = new RelativeLayout(mycontext);
rlButton = new RelativeLayout(mycontext);
llayouts = new LinearLayout[imgResId.length];
for (int i = 0; i < imgResId.length; i++) {
ImageView img = new ImageView(mycontext);
img.setImageResource(imgResId[i]);
LinearLayout.LayoutParams llps = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
img.setLayoutParams(llps);
llayouts[i] = new LinearLayout(mycontext);
llayouts[i].setId(100 + i);
llayouts[i].addView(img);
RelativeLayout.LayoutParams rlps = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
rlps.alignWithParent = true;
rlps.addRule(align1, RelativeLayout.TRUE);
rlps.addRule(align2, RelativeLayout.TRUE);
llayouts[i].setLayoutParams(rlps);
llayouts[i].setVisibility(View.INVISIBLE);
rl1.addView(llayouts[i]);
}
RelativeLayout.LayoutParams rlps1 = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.FILL_PARENT,
RelativeLayout.LayoutParams.FILL_PARENT);
rlps1.alignWithParent = true;
rlps1.addRule(align1, RelativeLayout.TRUE);
rlps1.addRule(align2, RelativeLayout.TRUE);
rl1.setLayoutParams(rlps1);
RelativeLayout.LayoutParams buttonlps = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
buttonlps.alignWithParent = true;
buttonlps.addRule(align1, RelativeLayout.TRUE);
buttonlps.addRule(align2, RelativeLayout.TRUE);
rlButton.setLayoutParams(buttonlps);
rlButton.setBackgroundResource(showhideButtonId);
cross = new ImageView(mycontext);
cross.setImageResource(crossId);
RelativeLayout.LayoutParams crosslps = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
crosslps.alignWithParent = true;
crosslps.addRule(CENTER_IN_PARENT, RelativeLayout.TRUE);
cross.setLayoutParams(crosslps);
rlButton.addView(cross);
myani = new myAnimations(rl1, pCode, radius);
rlButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (areButtonsShowing) {
myani.startAnimationsOut(duretime);
cross.startAnimation(myAnimations.getRotateAnimation(-270, 0, duretime));
} else {
myani.startAnimationsIn(duretime);
cross.startAnimation(myAnimations.getRotateAnimation(0, -270, duretime));
}
areButtonsShowing = !areButtonsShowing;
}
});
cross.startAnimation(myAnimations.getRotateAnimation(0, 360, 200));
this.addView(rl1);
this.addView(rlButton);
hasInit = true;
}
public void collapse() {
myani.startAnimationsOut(duretime);
cross.startAnimation(myAnimations.getRotateAnimation(-270, 0, duretime));
areButtonsShowing = false;
}
public void expand() {
myani.startAnimationsIn(duretime);
cross.startAnimation(myAnimations.getRotateAnimation(0, -270, duretime));
areButtonsShowing = true;
}
public boolean isInit() {
return hasInit;
}
public boolean isShow() {
return areButtonsShowing;
}
public void setButtonsOnClickListener(final OnClickListener l) {
if (llayouts != null) {
for (int i = 0; i < llayouts.length; i++) {
if (llayouts[i] != null)
llayouts[i].setOnClickListener(new OnClickListener() {
@Override
public void onClick(final View view) {
// collapse();
l.onClick(view);
}
});
}
}
}
}
2.定义动画类:
public class myAnimations {
public final int R;
public static byte RIGHTBOTTOM = 1, CENTERBOTTOM = 2, LEFTBOTTOM = 3, LEFTCENTER = 4, LEFTTOP = 5, CENTERTOP = 6, RIGHTTOP = 7,
RIGHTCENTER = 8;
private int pc;
private ViewGroup clayout;
private final int amount;
private double fullangle = 180.0;
private byte xOri = 1, yOri = 1;
private boolean isOpen = false;
private List<ViewPropertyAnimator> viewAnimators = new ArrayList<ViewPropertyAnimator>();
public myAnimations(ViewGroup comlayout, int poscode, int radius) {
this.pc = poscode;
this.clayout = comlayout;
this.amount = clayout.getChildCount();
this.R = radius;
for (int i = 0; i < amount; i++) {
View childAt = clayout.getChildAt(i);
ViewPropertyAnimator anim = animate(childAt);
viewAnimators.add(anim);
}
if (poscode == RIGHTBOTTOM) {
fullangle = 90;
xOri = -1;
yOri = -1;
} else if (poscode == CENTERBOTTOM) {
fullangle = 180;
xOri = -1;
yOri = -1;
} else if (poscode == LEFTBOTTOM) {
fullangle = 90;
xOri = 1;
yOri = -1;
} else if (poscode == LEFTCENTER) {
fullangle = 180;
xOri = 1;
yOri = -1;
} else if (poscode == LEFTTOP) {
fullangle = 90;
xOri = 1;
yOri = 1;
} else if (poscode == CENTERTOP) {
fullangle = 180;
xOri = -1;
yOri = 1;
} else if (poscode == RIGHTTOP) {
fullangle = 90;
xOri = -1;
yOri = 1;
} else if (poscode == RIGHTCENTER) {
fullangle = 180;
xOri = -1;
yOri = -1;
}
}
private class AnimListener implements AnimatorListener {
private View target;
public AnimListener(View _target) {
target = _target;
}
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
if (!isOpen) {
target.setVisibility(View.INVISIBLE);
}
}
@Override
public void onAnimationCancel(Animator animation) {
// TODO Auto-generated method stub
}
@Override
public void onAnimationRepeat(Animator animation) {
// TODO Auto-generated method stub
}
}
public void startAnimationsIn(int durationMillis) {
isOpen = true;
for (int i = 0; i < clayout.getChildCount(); i++) {
final LinearLayout inoutimagebutton = (LinearLayout) clayout.getChildAt(i);
double offangle = fullangle / (amount - 1);
final double deltaY, deltaX;
if (pc == LEFTCENTER || pc == RIGHTCENTER) {
deltaX = Math.sin(offangle * i * Math.PI / 180) * R;
deltaY = Math.cos(offangle * i * Math.PI / 180) * R;
} else {
deltaY = Math.sin(offangle * i * Math.PI / 180) * R;
deltaX = Math.cos(offangle * i * Math.PI / 180) * R;
}
ViewPropertyAnimator viewPropertyAnimator = viewAnimators.get(i);
viewPropertyAnimator.setListener(null);
inoutimagebutton.setVisibility(View.VISIBLE);
viewPropertyAnimator.x((float) (inoutimagebutton.getLeft() + xOri * deltaX)).y(
(float) (inoutimagebutton.getTop() + yOri * deltaY));
}
}
public void startAnimationsOut(int durationMillis) {
isOpen = false;
for (int i = 0; i < clayout.getChildCount(); i++) {
final LinearLayout inoutimagebutton = (LinearLayout) clayout.getChildAt(i);
ViewPropertyAnimator viewPropertyAnimator = viewAnimators.get(i);
viewPropertyAnimator.setListener(null);
viewPropertyAnimator.x((float) inoutimagebutton.getLeft()).y((float) inoutimagebutton.getTop());
viewPropertyAnimator.setListener(new AnimListener(inoutimagebutton));
}
}
public int getPosCode() {
return this.pc;
}
public static Animation getRotateAnimation(float fromDegrees, float toDegrees, int durationMillis) {
RotateAnimation rotate = new RotateAnimation(fromDegrees, toDegrees, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
0.5f);
rotate.setDuration(durationMillis);
rotate.setFillAfter(true);
return rotate;
}
}
自定义动画需要用到nineoldandroids类。
3.布局文件:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/rlparent"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#ABCDEF"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:text="@string/hello_world"
android:textColor="#000000"
tools:context=".MainActivity" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" >
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/hello_world"
android:textColor="#000000"
tools:context=".MainActivity" />
<geniuz.myPathbutton.composerLayout
android:id="@+id/test"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true" >
</geniuz.myPathbutton.composerLayout>
</RelativeLayout>
</LinearLayout>
</LinearLayout>
4。用法:
composerLayout clayout = (composerLayout) findViewById(R.id.test);
clayout.init(new int[] { R.drawable.composer_camera,
R.drawable.composer_music, R.drawable.composer_place,
R.drawable.composer_sleep, R.drawable.composer_thought,
R.drawable.composer_with }, R.drawable.composer_button,
R.drawable.composer_icn_plus, composerLayout.CENTERBOTTOM, 180,
300);
OnClickListener clickit = new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (v.getId() == 100 + 0) {
System.out.println("composer_camera");
} else if (v.getId() == 100 + 1) {
System.out.println("composer_music");
} else if (v.getId() == 100 + 2) {
System.out.println("composer_place");
} else if (v.getId() == 100 + 3) {
System.out.println("composer_sleep");
} else if (v.getId() == 100 + 4) {
System.out.println("composer_thought");
} else if (v.getId() == 100 + 5) {
System.out.println("composer_with");
}
}
};
clayout.setButtonsOnClickListener(clickit);