为了 实现这种效果。关键代码如下:
xyLayout = new XYLayout(this);
llp = new LinearLayout.LayoutParams(100, 30);
xyLayout.setBackgroundDrawable(new TwoColorRoundRectDrawable(Color
.argb(255, 230, 230, 230), Color.argb(255, 230, 230, 230)));
this.addContentView(xyLayout, llp);
onview = new OnView(this);
xyLayout.addView(onview);
xyLayout.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
onview = new OnView(OnOffViewDemo.this);
offview = new OffView(OnOffViewDemo.this);
if (i % 2 != 0) {
xyLayout.removeAllViews();
xyLayout.addView(onview);
} else {
xyLayout.removeAllViews();
xyLayout.addView(offview);
}
i++;
return false;
}
});
xyLayout.java如下:
package cn.bmy;
import java.util.HashMap;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
public class XYLayout extends ViewGroup {
private HashMap<String, Object> propMap = new HashMap<String, Object>();
public XYLayout(Context context) {
super(context);
}
public XYLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public XYLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public void setProperty(String property, Object value) {
propMap.put(property, value);
}
public Object getProperty(String property) {
return propMap.get(property);
}
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int count = getChildCount();
int maxHeight = 0;
int maxWidth = 0;
int specwidth = MeasureSpec.getSize(widthMeasureSpec);
int specheight = MeasureSpec.getSize(heightMeasureSpec);
// Find out how big everyone wants to be
measureChildren(widthMeasureSpec, heightMeasureSpec);
// Find rightmost and bottom-most child
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
if (child.getVisibility() != GONE) {
int childRight;
int childBottom;
XYLayout.LayoutParams lp = (XYLayout.LayoutParams) child
.getLayoutParams();
if (lp.x == LayoutParams.LEFT) {
childRight = child.getMeasuredWidth();
maxWidth = Math.max(maxWidth, childRight);
} else if (lp.x == LayoutParams.CENTER) {
childRight = (child.getMeasuredWidth() / 2)
+ (specwidth / 2);
maxWidth = Math.max(maxWidth, childRight);
} else if (lp.x == LayoutParams.RIGHT) {
childRight = specwidth;
maxWidth = Math.max(maxWidth, childRight);
} else {
childRight = lp.x + child.getMeasuredWidth();
maxWidth = Math.max(maxWidth, childRight);
}
if (lp.y == LayoutParams.TOP) {
childBottom = child.getMeasuredHeight();
maxHeight = Math.max(maxHeight, childBottom);
} else if (lp.y == LayoutParams.CENTER) {
childBottom = (child.getMeasuredHeight() / 2)
+ (specheight / 2);
maxHeight = Math.max(maxHeight, childBottom);
} else if (lp.y == LayoutParams.BOTTOM) {
childBottom = specheight;
maxHeight = Math.max(maxHeight, childBottom);
} else {
childBottom = lp.y + child.getMeasuredHeight();
maxHeight = Math.max(maxHeight, childBottom);
}
}
}
// Account for padding too
maxWidth += getPaddingLeft() + getPaddingRight();
maxHeight += getPaddingTop() + getPaddingBottom();
// Check against minimum height and width
maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight());
maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth());
setMeasuredDimension(resolveSize(maxWidth, widthMeasureSpec),
resolveSize(maxHeight, heightMeasureSpec));
}
/**
* Returns a set of layout parameters with a width of
* {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT}, a height of
* {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT} and with the
* coordinates (0, 0).
*/
protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
return new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT, 0, 0);
}
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int count = getChildCount();
int width = Math.abs(r - l) - getPaddingLeft() - getPaddingRight();
int height = Math.abs(b - t) - getPaddingTop() - getPaddingBottom();
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
if (child.getVisibility() != GONE) {
XYLayout.LayoutParams lp = (XYLayout.LayoutParams) child
.getLayoutParams();
int childWidth = child.getMeasuredWidth();
int childHeight = child.getMeasuredHeight();
if (lp.x == LayoutParams.LEFT && lp.y == LayoutParams.TOP) {
int childLeft = getPaddingLeft();
int childTop = getPaddingTop();
child.layout(childLeft, childTop,
childLeft + child.getMeasuredWidth(), childTop
+ child.getMeasuredHeight());
} else if (lp.x == LayoutParams.CENTER
&& lp.y == LayoutParams.TOP) {
int childLeft = getPaddingLeft() + (width - childWidth) / 2;
int childTop = getPaddingTop();
child.layout(childLeft, childTop,
childLeft + child.getMeasuredWidth(), childTop
+ child.getMeasuredHeight());
} else if (lp.x == LayoutParams.RIGHT
&& lp.y == LayoutParams.TOP) {
int childLeft = getPaddingLeft() + width - childWidth;
int childTop = getPaddingTop();
child.layout(childLeft, childTop,
childLeft + child.getMeasuredWidth(), childTop
+ child.getMeasuredHeight());
} else if (lp.x == LayoutParams.LEFT
&& lp.y == LayoutParams.CENTER) {
int childLeft = getPaddingLeft();
int childTop = getPaddingTop() + (height - childHeight / 2);
child.layout(childLeft, childTop,
childLeft + child.getMeasuredWidth(), childTop
+ child.getMeasuredHeight());
} else if (lp.x == LayoutParams.CENTER
&& lp.y == LayoutParams.CENTER) {
int childLeft = getPaddingLeft() + (width - childWidth) / 2;
int childTop = getPaddingTop() + (height - childHeight) / 2;
child.layout(childLeft, childTop,
childLeft + child.getMeasuredWidth(), childTop
+ child.getMeasuredHeight());
} else if (lp.x == LayoutParams.RIGHT
&& lp.y == LayoutParams.CENTER) {
int childLeft = getPaddingLeft() + width - childWidth;
int childTop = getPaddingTop() + (height - childHeight) / 2;
child.layout(childLeft, childTop,
childLeft + child.getMeasuredWidth(), childTop
+ child.getMeasuredHeight());
} else if (lp.x == LayoutParams.LEFT
&& lp.y == LayoutParams.BOTTOM) {
int childLeft = getPaddingLeft();
int childTop = getPaddingTop() + height - childHeight;
child.layout(childLeft, childTop,
childLeft + child.getMeasuredWidth(), childTop
+ child.getMeasuredHeight());
} else if (lp.x == LayoutParams.CENTER
&& lp.y == LayoutParams.BOTTOM) {
int childLeft = getPaddingLeft() + (width - childWidth) / 2;
int childTop = getPaddingTop() + height - childHeight;
child.layout(childLeft, childTop,
childLeft + child.getMeasuredWidth(), childTop
+ child.getMeasuredHeight());
} else if (lp.x == LayoutParams.RIGHT
&& lp.y == LayoutParams.BOTTOM) {
int childLeft = getPaddingLeft() + width - childWidth;
int childTop = getPaddingTop() + height - childHeight;
child.layout(childLeft, childTop,
childLeft + child.getMeasuredWidth(), childTop
+ child.getMeasuredHeight());
} else {
int childLeft = getPaddingLeft() + lp.x;
int childTop = getPaddingTop() + lp.y;
child.layout(childLeft, childTop,
childLeft + child.getMeasuredWidth(), childTop
+ child.getMeasuredHeight());
}
}
}
}
public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
return new XYLayout.LayoutParams(getContext(), attrs);
}
// Override to allow type-checking of LayoutParams.
protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
return p instanceof XYLayout.LayoutParams;
}
protected ViewGroup.LayoutParams generateLayoutParams(
ViewGroup.LayoutParams p) {
return new LayoutParams(p);
}
/**
* Per-child layout information associated with AbsoluteLayout. See
* {@link android.R.styleable#AbsoluteLayout_Layout Absolute Layout
* Attributes} for a list of all child view attributes that this class
* supports.
*/
public static class LayoutParams extends ViewGroup.LayoutParams {
public static final int LEFT = -31302;
public static final int RIGHT = -31301;
public static final int CENTER = -31300;
public static final int TOP = -31329;
public static final int BOTTOM = -31328;
/**
* The horizontal, or X, location of the child within the view group.
*/
public int x;
/**
* The vertical, or Y, location of the child within the view group.
*/
public int y;
/**
* Creates a new set of layout parameters with the specified width,
* height and location.
*
* @param width
* the width, either {@link #FILL_PARENT},
* {@link #WRAP_CONTENT} or a fixed size in pixels
* @param height
* the height, either {@link #FILL_PARENT},
* {@link #WRAP_CONTENT} or a fixed size in pixels
* @param x
* the X location of the child
* @param y
* the Y location of the child
*/
public LayoutParams(int width, int height, int x, int y) {
super(width, height);
this.x = x;
this.y = y;
}
/**
* Creates a new set of layout parameters. The values are extracted from
* the supplied attributes set and context. The XML attributes mapped to
* this set of layout parameters are:
*
* <ul>
* <li><code>layout_x</code>: the X location of the child</li>
* <li><code>layout_y</code>: the Y location of the child</li>
* <li>All the XML attributes from
* {@link android.view.ViewGroup.LayoutParams}</li>
* </ul>
*
* @param c
* the application environment
* @param attrs
* the set of attributes from which to extract the layout
* parameters values
*/
public LayoutParams(Context c, AttributeSet attrs) {
super(c, attrs);
x = Integer.parseInt(attrs.getAttributeValue(null, "layout_x"));
y = Integer.parseInt(attrs.getAttributeValue(null, "layout_y"));
}
/**
* {@inheritDoc}
*/
public LayoutParams(ViewGroup.LayoutParams source) {
super(source);
}
public String debug(String output) {
return output + "Absolute.LayoutParams={width="
+ Integer.toString(width) + ", height="
+ Integer.toString(height) + " x=" + x + " y=" + y + "}";
}
}
}
TwoColorRoundRectDrawable.java代码如下:
package cn.bmy;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Shader;
import android.graphics.Path.Direction;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
public class TwoColorRoundRectDrawable extends Drawable {
private int startcolor;
private int endcolor;
public TwoColorRoundRectDrawable(int startcolor, int endcolor){
this.startcolor = startcolor;
this.endcolor = endcolor;
}
public void draw(Canvas canvas) {
Rect bounds = getBounds();
Paint paint = new Paint();
paint.setShader(new LinearGradient(bounds.left, bounds.top, bounds.left, bounds.bottom, startcolor,
endcolor, Shader.TileMode.CLAMP));
Path path = new Path();
path.addRoundRect(new RectF(bounds.left, bounds.top, bounds.right, bounds.bottom),5,5,Direction.CW);
canvas.drawPath(path, paint);
}
protected void onBoundsChange(Rect bounds) {
}
public void setAlpha(int alpha) {
// TODO Auto-generated method stub
}
public void setColorFilter(ColorFilter cf) {
// TODO Auto-generated method stub
}
public int getOpacity() {
// TODO Auto-generated method stub
return 0;
}
}
OnView.java如下:
package cn.bmy;
import android.content.Context;
import android.graphics.Color;
import android.view.Gravity;
import android.widget.LinearLayout;
import android.widget.TextView;
public class OnView extends LinearLayout{
//AppInstance appInstance;
Context context;
LinearLayout.LayoutParams llp;
public OnView(Context context) {
super(context);
this.context = context;
buildView();
// TODO Auto-generated constructor stub
}
private void buildView() {
LinearLayout onoffView=new LinearLayout(context);
llp=new LinearLayout.LayoutParams(100,30);
this.addView(onoffView,llp);
onoffView.setBackgroundDrawable(new TwoColorRoundRectDrawable(Color.argb(255,230, 230, 230), Color.argb(255,230, 230, 230)));
onoffView.setOrientation(LinearLayout.HORIZONTAL);
final LinearLayout onView=new LinearLayout(context);
llp=new LinearLayout.LayoutParams(60,30);
onoffView.addView(onView,llp);
onView.setBackgroundDrawable(new TwoColorRoundRectDrawable(Color.argb(255, 24, 77, 156), Color.argb(255, 115, 163, 231)));
final TextView tvOn=new TextView(context);
llp=new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT,LinearLayout.LayoutParams.FILL_PARENT);
onView.addView(tvOn,llp);
tvOn.setText("ON");
tvOn.setTextSize(16);
tvOn.setGravity(Gravity.CENTER);
LinearLayout offView= new LinearLayout(context);
llp=new LinearLayout.LayoutParams(40,30,1);
onoffView.addView(offView,llp);
offView.setBackgroundDrawable(new TwoColorRoundRectDrawable(Color.argb(255,230, 230, 230), Color.argb(255,230, 230, 230)));
final TextView tvOff=new TextView(context);
llp=new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT,LinearLayout.LayoutParams.FILL_PARENT);
offView.addView(tvOff,llp);
tvOff.setText("");
tvOff.setTextSize(16);
tvOff.setGravity(Gravity.CENTER);
}
}
OffView.java代码如下:
package cn.bmy;
import android.content.Context;
import android.graphics.Color;
import android.view.Gravity;
import android.widget.LinearLayout;
import android.widget.TextView;
public class OffView extends LinearLayout{
//AppInstance appInstance;
Context context;
LinearLayout.LayoutParams llp;
public OffView(Context context) {
super(context);
this.context = context;
buildView();
// TODO Auto-generated constructor stub
}
private void buildView() {
LinearLayout onoffView=new LinearLayout(context);
llp=new LinearLayout.LayoutParams(100,30);
this.addView(onoffView,llp);
onoffView.setBackgroundDrawable(new TwoColorRoundRectDrawable(Color.argb(255,230, 230, 230), Color.argb(255,230, 230, 230)));
onoffView.setOrientation(LinearLayout.HORIZONTAL);
final LinearLayout onView=new LinearLayout(context);
llp=new LinearLayout.LayoutParams(40,30);
onoffView.addView(onView,llp);
onView.setBackgroundDrawable(new TwoColorRoundRectDrawable(Color.argb(255,230, 230, 230), Color.argb(255,230, 230, 230)));
final TextView tvOn=new TextView(context);
llp=new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT,LinearLayout.LayoutParams.FILL_PARENT);
onView.addView(tvOn,llp);
tvOn.setText("");
tvOn.setTextSize(16);
tvOn.setGravity(Gravity.CENTER);
LinearLayout offView= new LinearLayout(context);
llp=new LinearLayout.LayoutParams(60,30);
onoffView.addView(offView,llp);
onoffView.setBackgroundDrawable(new TwoColorRoundRectDrawable(Color.WHITE,Color.WHITE));
final TextView tvOff=new TextView(context);
llp=new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT,LinearLayout.LayoutParams.FILL_PARENT);
offView.addView(tvOff,llp);
tvOff.setText("OFF");
tvOff.setTextSize(16);
tvOff.setGravity(Gravity.CENTER);
}
}