android实现六边形等不规则布局
在去年⼴告机项⽬中,UI设计出⼀个⽐较华丽的UI,但是对于我来说⽆从下⼿,我试过view的叠加并设置外边距实现,虽然勉强可以实现,但是获取单击焦点是有很多问题;
效果图如下:
最后只有另外想办法;我对viewgroup进⾏了⾃定义,并且⾃定义了每个按钮
源码:
以下是我的实现⽅式:
1.SpecailButton.java
public class SpecailButton extends TextView implements View.OnClickListener {
private static final String TAG = "SpecailButton";
public static final int TEXT_ALIGN_LEFT              = 0x00000001;
public static final int TEXT_ALIGN_RIGHT            = 0x00000010;
public static final int TEXT_ALIGN_CENTER_VERTICAL  = 0x00000100;
public static final int TEXT_ALIGN_CENTER_HORIZONTAL = 0x00001000;
public static final int TEXT_ALIGN_TOP              = 0x00010000;
public static final int TEXT_ALIGN_BOTTOM            = 0x00100000;
/** 控件画笔 */
private Paint paint;
/** ⽂字的⽅位 */
private int textAlign;
/** ⽂字的颜⾊ */
private int textColor;
/** 控件的宽度 */
private int viewWidth;
/** 控件的⾼度 */
private int viewHeight;
/** ⽂本中轴线X坐标 */
private float textCenterX;
/** ⽂本baseline线Y坐标 */
private float textBaselineY;
private String text;
private FontMetrics fm;
private Context mContext;
private boolean checked = false;
public SpecailButton(Context context) {
super(context);
mContext = context;
init();
}
public SpecailButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mContext = context;
init();
}
public SpecailButton(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
android layout布局
init();
}
/**
* 变量初始化
*/
private void init() {
setOnClickListener(this);
text = getText().toString();
setText("");
paint = new Paint();
paint.setTextSize(22);
paint.setAntiAlias(true);
paint.setTextAlign(Align.CENTER);
//默认情况下⽂字居中显⽰
textAlign = TEXT_ALIGN_CENTER_HORIZONTAL | TEXT_ALIGN_CENTER_VERTICAL;
//默认的⽂本颜⾊是⿊⾊
textColor = Color.BLACK;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int wMode = Mode(widthMeasureSpec);
int wSize = Size(widthMeasureSpec);
int hMode = Mode(heightMeasureSpec);
int hSize = Size(heightMeasureSpec);
setMeasuredDimension(wSize, hSize);
Log.i(TAG, "onMeasure()--wMode=" + wMode + ",wSize=" + wSize + ",hMode=" + hMode+ ",hSize=" + hSize);        Measure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
Log.i(TAG, "onLayout");
viewWidth = right - left;
viewHeight = bottom - top;
}
@Override
protected void onDraw(Canvas canvas) {
//绘制控件内容
setTextLocation(text);
canvas.drawText(text, textCenterX, textBaselineY, paint);
}
/
**
* 定位⽂本绘制的位置
*/
private void setTextLocation(String text) {
//        paint.setTextSize(textSize);
paint.setColor(textColor);
fm = FontMetrics();
//⽂本的宽度
float textWidth = asureText(text);
float textCenterVerticalBaselineY = viewHeight / 2 - fm.descent + (fm.descent - fm.ascent) / 2;
switch (textAlign) {
case TEXT_ALIGN_CENTER_HORIZONTAL | TEXT_ALIGN_CENTER_VERTICAL:
textCenterX = (float)viewWidth / 2;
textBaselineY = textCenterVerticalBaselineY;
break;
case TEXT_ALIGN_LEFT | TEXT_ALIGN_CENTER_VERTICAL:
textCenterX = textWidth / 2;
textBaselineY = textCenterVerticalBaselineY;
break;
case TEXT_ALIGN_RIGHT | TEXT_ALIGN_CENTER_VERTICAL:
textCenterX = viewWidth - textWidth / 2;
textBaselineY = textCenterVerticalBaselineY;
break;
case TEXT_ALIGN_BOTTOM | TEXT_ALIGN_CENTER_HORIZONTAL:
textCenterX = viewWidth / 2;
textBaselineY = viewHeight - fm.bottom;
break;
case TEXT_ALIGN_TOP | TEXT_ALIGN_CENTER_HORIZONTAL:
textCenterX = viewWidth / 2;
textBaselineY = -fm.ascent;
break;
case TEXT_ALIGN_TOP | TEXT_ALIGN_LEFT:
textCenterX = textWidth / 2;
textBaselineY = -fm.ascent;
break;
case TEXT_ALIGN_BOTTOM | TEXT_ALIGN_LEFT:
textCenterX = textWidth / 2;
textBaselineY = viewHeight - fm.bottom;
break;
case TEXT_ALIGN_TOP | TEXT_ALIGN_RIGHT:
textCenterX = viewWidth - textWidth / 2;
textBaselineY = -fm.ascent;
break;
case TEXT_ALIGN_BOTTOM | TEXT_ALIGN_RIGHT:
textCenterX = viewWidth - textWidth / 2;
textBaselineY = viewHeight - fm.bottom;
break;
}
}
public interface OnClickListener {
void onClick(View v, boolean checked);
}
private OnClickListener mListener;
public void setOnClickListener(OnClickListener listener) {
mListener = listener;
}
@Override
public void onClick(View v) {
checked = !checked;
setBackgroundResource(checked ? 0 : R.drawable.logo);
if (mListener != null) {
}
}
public String getTextString() {
return text;
}
}
2.外⾯的⽗控件:
public class SpecailView extends ViewGroup {
private static final String TAG = "SpecailView";
private static final int RADIU_COUNT = 8;
private static final int PADDING = 10;
private int childRadius;
private int childWidth;
private int childHeight;
private int mChildCount;
private int centerX ,centerY;
public SpecailView(Context context) {
super(context);
Log.i(TAG, "SpecailView()");
}
public SpecailView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
Log.i(TAG, "SpecailView( , , )");
}
public SpecailView(Context context, AttributeSet attrs) {
super(context, attrs);
Log.i(TAG, "SpecailView( , )");
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        int wMode = Mode(widthMeasureSpec);
int wSize = Size(widthMeasureSpec);
int hMode = Mode(heightMeasureSpec);
int hSize = Size(heightMeasureSpec);
setMeasuredDimension(wSize, hSize);
centerX = wSize / 2;
centerY = hSize / 2;
childRadius = (wSize - PADDING * 2) / RADIU_COUNT;
childWidth = childRadius * 2;
childHeight = (int)(childRadius * Math.sqrt(3) / 2)*2;
final int count = getChildCount();
for (int index = 0; index < count; index++) {
View child = getChildAt(index);
// measure
}
if (mChildCount != count) {
mChildCount = count;
}
/
/        if (mChildCount > centers.size()) {
computerPoint(centerX, centerY, childHeight);
//        }
Log.i(TAG, "onMeasure()--childWidth="+childWidth+",childHeight="+childHeight);
Log.i(TAG, "onMeasure()--wMode=" + wMode + ",wSize=" + wSize + ",hMode=" + hMode+ ",hSize=" + hSize);        Measure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
final int count = getChildCount();
int childLeft, childTop;
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
childLeft = (int)((i).x-childRadius);
childTop =  (int)((i).y-childHeight/2);
child.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);
}
Log.i(TAG, "onLayout()--changed=" + changed + ",left=" + left + ",top=" + top + ",right="
+ right + ",bottom=" + bottom + ",count=" + count);
}
private int getCircleIndex(int i) {
int index = 0;
while (i > (3*index*index + 3*index)) {
index ++;
}
return index;
}
/**
*  index start from 0
*/
private int getCircleCount(int index) {
if (index == 0) {
return 1;
}
return index*6;
}
private void computerPoint(double a, double b, double h) {
double sqrt3 = Math.sqrt(3);
CircleCenteter c01 = new CircleCenteter(a, b);
CircleCenteter c11 = new CircleCenteter(a, b-h);
CircleCenteter c12 = new CircleCenteter(a + sqrt3*h/2, b - h/2);
CircleCenteter c13 = new CircleCenteter(a + sqrt3*h/2, b + h/2);
CircleCenteter c14 = new CircleCenteter(a, b + h);
CircleCenteter c15 = new CircleCenteter(a - sqrt3*h/2, b + h/2);
CircleCenteter c16 = new CircleCenteter(a - sqrt3*h/2, b - h/2);
CircleCenteter c21 = new CircleCenteter(a, b-2*h);
CircleCenteter c22 = new CircleCenteter(a + sqrt3*h/2, b-3*h/2);
CircleCenteter c23 = new CircleCenteter(a + sqrt3*h, b - h);
CircleCenteter c24 = new CircleCenteter(a + sqrt3*h, b);
CircleCenteter c25 = new CircleCenteter(a + sqrt3*h, b + h);
CircleCenteter c26 = new CircleCenteter(a + sqrt3*h/2, b + 3*h/2);
CircleCenteter c27 = new CircleCenteter(a, b + 2*h);
CircleCenteter c28 = new CircleCenteter(a - sqrt3*h/2, b + 3*h/2);
CircleCenteter c29 = new CircleCenteter(a - sqrt3*h, b + h);
CircleCenteter c210 = new CircleCenteter(a - sqrt3*h, b);
CircleCenteter c211 = new CircleCenteter(a - sqrt3*h, b - h);
CircleCenteter c212 = new CircleCenteter(a - sqrt3*h/2, b-3*h/2);
centers.clear();
centers.add(c01);
centers.add(c11);
centers.add(c12);
centers.add(c13);
centers.add(c14);
centers.add(c15);
centers.add(c16);
centers.add(c21);
centers.add(c22);
centers.add(c23);
centers.add(c24);
centers.add(c25);
centers.add(c26);
centers.add(c27);
centers.add(c28);
centers.add(c29);
centers.add(c210);
centers.add(c211);
centers.add(c212);
}
public void setOnItemClick(SpecailButton.OnClickListener l) {
int count = getChildCount();
for (int i = 0; i < count; i++) {
((SpecailButton)getChildAt(i)).setOnClickListener(l);
}
}
private ArrayList<CircleCenteter> centers = new ArrayList<SpecailView.CircleCenteter>(7);    class CircleCenteter {
double x ,y;
public CircleCenteter(double x, double y){
this.x = x;
this.y = y;
}
}
}
3.l
<RelativeLayout xmlns:android="schemas.android/apk/res/android"
xmlns:tools="schemas.android/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<stspecialview.SpecailView
android:id="@+id/specail_view"
android:layout_width="match_parent"
android:layout_height="400dip"
android:background="#78675645" >
<stspecialview.SpecailButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/logo"
android:gravity="center"
android:text="婚礼0"/>
<stspecialview.SpecailButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/logo"
android:gravity="center"
android:text="婚礼1"/>
<stspecialview.SpecailButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/logo"
android:gravity="center"
android:text="婚礼2"/>
<stspecialview.SpecailButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/logo"
android:gravity="center"
android:text="婚礼3"/>
<stspecialview.SpecailButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/logo"
android:gravity="center"
android:text="婚礼4"/>
<stspecialview.SpecailButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/logo"

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。