zoukankan      html  css  js  c++  java
  • android实现六边形等不规则布局

    在去年广告机项目中,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://www.sjsjw.com/kf_mobile/article/10_3422_10725.asp

  • 相关阅读:
    ELK+Kafka+Beats实现海量日志收集平台(三)
    ELK+Kafka+Beats实现海量日志收集平台(二)
    ELK+Kafka+Beats实现海量日志收集平台(一)
    Linux 上安装logstash-6.6.0及配置kafka输入
    Linux 上安装filebeat-6.6.0
    SpringBoot与Kafka整合实现简单分布式消息队列
    logstash-6.6.0.tar.gz、filebeat-6.6.0-linux-x86_64.tar.gz 下载百度云
    Centos 7.X 上安装Kafka及一些常用命令
    Linux MariaDB 10.4.8 官网地址下载及百度云
    [Errno 28] No space left on device ERROR: Could not install packages due to an EnvironmentError
  • 原文地址:https://www.cnblogs.com/Nbox1989/p/4315088.html
Copyright © 2011-2022 走看看