在去年广告机项目中,UI设计出一个比较华丽的UI,但是对于我来说无从下手,我试过view的叠加并设置外边距实现,虽然勉强可以实现,但是获取单击焦点是有很多问题;

效果图如下:

最后只有另外想办法;我对viewgroup进行了自定义,并且自定义了每个按钮

源码:http://download.csdn.net/detail/hcb1230/6479979

以下是我的实现方式:

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;
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 = MeasureSpec.getMode(widthMeasureSpec);
int wSize = MeasureSpec.getSize(widthMeasureSpec); int hMode = MeasureSpec.getMode(heightMeasureSpec);
int hSize = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(wSize, hSize);
Log.i(TAG, "onMeasure()--wMode=" + wMode + ",wSize=" + wSize + ",hMode=" + hMode+ ",hSize=" + hSize);
super.onMeasure(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;
super.onLayout(changed, left, top, right, bottom);
} @Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//绘制控件内容
setTextLocation(text);
canvas.drawText(text, textCenterX, textBaselineY, paint);
} /**
* 定位文本绘制的位置
*/
private void setTextLocation(String text) {
// paint.setTextSize(textSize);
paint.setColor(textColor);
fm = paint.getFontMetrics();
//文本的宽度
float textWidth = paint.measureText(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) {
mListener.onClick(v, checked);
}
} 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 = MeasureSpec.getMode(widthMeasureSpec);
int wSize = MeasureSpec.getSize(widthMeasureSpec); int hMode = MeasureSpec.getMode(heightMeasureSpec);
int hSize = MeasureSpec.getSize(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
child.measure(childWidth, childHeight);
}
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);
super.onMeasure(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)(centers.get(i).x-childRadius);
childTop = (int)(centers.get(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.activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" > <com.qiang.testspecialview.SpecailView
android:id="@+id/specail_view"
android:layout_width="match_parent"
android:layout_height="400dip"
android:background="#78675645" > <com.qiang.testspecialview.SpecailButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/logo"
android:gravity="center"
android:text="婚礼0"/> <com.qiang.testspecialview.SpecailButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/logo"
android:gravity="center"
android:text="婚礼1"/> <com.qiang.testspecialview.SpecailButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/logo"
android:gravity="center"
android:text="婚礼2"/> <com.qiang.testspecialview.SpecailButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/logo"
android:gravity="center"
android:text="婚礼3"/> <com.qiang.testspecialview.SpecailButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/logo"
android:gravity="center"
android:text="婚礼4"/> <com.qiang.testspecialview.SpecailButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/logo"
android:gravity="center"
android:text="婚礼5"/> <com.qiang.testspecialview.SpecailButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/logo"
android:gravity="center"
android:text="婚礼6"/> <com.qiang.testspecialview.SpecailButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/logo"
android:gravity="center"
android:text="婚礼7"/> <com.qiang.testspecialview.SpecailButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/logo"
android:gravity="center"
android:text="婚礼8"/> <com.qiang.testspecialview.SpecailButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/logo"
android:gravity="center"
android:text="婚礼9"/> <com.qiang.testspecialview.SpecailButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/logo"
android:gravity="center"
android:text="婚礼10"/> <com.qiang.testspecialview.SpecailButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/logo"
android:gravity="center"
android:text="婚礼11"/> <com.qiang.testspecialview.SpecailButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/logo"
android:gravity="center"
android:text="婚礼12"/> <com.qiang.testspecialview.SpecailButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/logo"
android:gravity="center"
android:text="婚礼13"/> <com.qiang.testspecialview.SpecailButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/logo"
android:gravity="center"
android:text="婚礼14"/> <com.qiang.testspecialview.SpecailButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/logo"
android:gravity="center"
android:text="婚礼15"/> <com.qiang.testspecialview.SpecailButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/logo"
android:gravity="center"
android:text="婚礼16"/> <com.qiang.testspecialview.SpecailButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/logo"
android:gravity="center"
android:text="婚礼17"/> <com.qiang.testspecialview.SpecailButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/logo"
android:gravity="center"
android:text="婚礼18"/> </com.qiang.testspecialview.SpecailView> </RelativeLayout>

4.MainActivity.java

public class MainActivity extends Activity implements SpecailButton.OnClickListener  {

    private SpecailView layout;

    @Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); layout = (SpecailView)findViewById(R.id.specail_view);
layout.setOnItemClick(this);
} @Override
public void onClick(View v, boolean checked) {
String text = ((SpecailButton)v).getTextString();
Toast.makeText(this, text + checked, Toast.LENGTH_SHORT).show();
} }

好了最后运行效果如下:

有需要工程的,源码:http://download.csdn.net/detail/hcb1230/6479979

作者:http://blog.csdn.net/wingmder
地址:http://blog.csdn.net/hcb1230/article/details/13766379#3056525

android实现六边形等不规则布局的更多相关文章

  1. Android 自定义View及其在布局文件中的使用示例(三):结合Android 4.4.2_r1源码分析onMeasure过程

    转载请注明出处 http://www.cnblogs.com/crashmaker/p/3549365.html From crash_coder linguowu linguowu0622@gami ...

  2. Android 自定义View及其在布局文件中的使用示例(二)

    转载请注明出处 http://www.cnblogs.com/crashmaker/p/3530213.html From crash_coder linguowu linguowu0622@gami ...

  3. android项目的结构和布局

    一.res文件夹 1.res文件夹用于存放Android的资源.包括:动画.静态图片.字符串.菜单.布局.视频.文件等. 1.drawable-ldpi:低分辨率图形(120像素/英寸) 2.draw ...

  4. Android UI基础之五大布局

    Android  UI基础之五大布局 Android的界面是有布局和组件协同完成的,布局好比是建筑里的框架,而组件则相当于建筑里的砖瓦.组件按照布局的要求依次排列,就组成了用户所看见的界面.Andro ...

  5. Android学习笔记④——页面的布局方式

    FrameLayout(帧布局) 这个布局的特点是简单的默认把每一个视图组件都放在边框内且放在左上角,即使添加多个视图组件,他们也都是重叠在左上角,新的视图会遮挡住旧的视图.可以根据gravity来改 ...

  6. Android UI学习 - FrameLayou和布局优化(viewstub)

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://android.blog.51cto.com/268543/308090 Fram ...

  7. Android 改变窗口标题栏的布局

    Android改变窗口标题栏的布局  第一种方式 --在XML文件里面引入配置文件作为标题. 第二种方式  --动态的代码加入进去. 第三种方式(网上的): 一. 重点 一般应用的Title都是建立应 ...

  8. 【Android Developers Training】 73. 布局变化的动画

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  9. Android之控件与布局,结构知识点,基础完结

    版权声明:未经博主允许不得转载 在Android中我们常常用到很多UI控件,如TextView,EditText,ImageView,Button,ImageButton,ToggleButton,C ...

随机推荐

  1. js取float型小数点后x位数的方法

    js中取小数点后两位方法最常用的就是四舍五入函数了,前面我介绍过js中四舍五入一此常用函数,这里正好用上,下面我们一起来看取float型小数点后两位一些方法总结 以下我们将为大家介绍 JavaScri ...

  2. centos7安装redis-4.0.1集群

    试验机操作系统:CentOS Linux release 7.2.1511 (Core) 本文的目的是教会大家快速搭建redis集群,完了再深入学习. 试问如果不上手试验,看的资料再多有个毛用? 下载 ...

  3. Git_安装Git

    最早Git是在Linux上开发的,很长一段时间内,Git也只能在Linux和Unix系统上跑.不过,慢慢地有人把它移植到了Windows上.现在,Git可以在Linux.Unix.Mac和Window ...

  4. 盘点Linux内核源码中使用宏定义的若干技巧(1)

    http://blog.chinaunix.net/uid-23769728-id-3141515.html

  5. 使用stream(流)实现多表数据传输

    使用stream(流)实现多表数据传输 几乎所有的TCP和HTTP通信控件都支持stream(流)的传输. 使用stream(流)是可以实现多表数据传输的. 但这需要自定义协议了: 合并后的strea ...

  6. Android之NDK开发环境r9

    需要的软件: android-ndk-r9-windows-x86_64.zip(我的系统是64位的,所以下载的是64的)下载地址:http://developer.android.com/tools ...

  7. pytest文档19-doctest测试框架

    前言 doctest从字面意思上看,那就是文档测试.doctest是python里面自带的一个模块,它实际上是单元测试的一种. 官方解释:doctest 模块会搜索那些看起来像交互式会话的 Pytho ...

  8. weblogic 12C 安全加强:更改Console及管理端口

    一.管理端口的好处:1.由于我们使用的是weblogic直接提供web访问,所以防火墙无法对80端口做安全策略. 2.所有用户都可以使用http://www.reyo.cn/console/来登陆我们 ...

  9. UITableView分页

    UITableView分页上拉加载简单,ARC环境,源码如下,以作备份: 原理是,点击最后一个cell,触发一个事件来处理数据,然后reloadData RootViewController.m + ...

  10. Iptables静态防火墙基础教程

    文章目录检查Iptables是否安装Iptables相关的文件配置Iptables规则自定义规则保存规则 Iptables对于刚入门Linux的新手都比较难理解和配置.但是如果你掌握了其中的诀窍,你就 ...