圆形布局

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/likui19921224/article/details/79129622

在安卓中除了系统的几个布局外 我们会发现有时候根本满足不了我们的布局效果要求,今天给大家展示一个圆形布局效果,
其实圆形布局很简单:我们只需要对布局内的组件的位置方程圆形就可以了
因此我们的难点就只有一个 那就是如何计算圆形的样式:

我们初步想象一个圆,圆内放几个组件,那么第一步我们确定外圆的圆形
可以直接获取屏幕的信息来定义圆心
也可以重写onmeasure中根据我们布局参数来确定我们的圆心

通过从写onlayout方法 来让我们的组件按照圆形放置就可以了
通过view.layout就可以设置;

package com.CustomControl.View;

import com.example.customcontrol.R;

import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;

import android.view.View;
import android.view.ViewGroup;

/**
 * 圆形布局 其实按照圆形的方式放置 就是圆形布局 主要使用mSuanfa_radio 弧度计算 然后设置每个的坐标
 * 
 * @author Karin
 */
public class CircleViewGroup extends ViewGroup {

    private final String mTAG = "CircleViewGroup";

    private int mRadios = 200;//圆形布局内组件的间距

    private boolean openCenterCircle = false;//是否启动中心圆组件

    public CircleViewGroup(Context context) {
        super(context);
    }

    public CircleViewGroup(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CircleViewGroup(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
//这里说明下:我这里是可以让圆心处放一个组件
        TypedArray tp = context.obtainStyledAttributes(attrs, R.styleable.CircleLinearLayout);//属性样式
        //第一个属性时圆形布局内组件的间距
        mRadios = tp.getInt(R.styleable.CircleLinearLayout_circleRadius, 50);
        //是否启动中心出组件  如果为true  那么我们circleviewgroup处的第一个组件将被放在圆心
        openCenterCircle = tp.getBoolean(R.styleable.CircleLinearLayout_openCentercircle, false);
//记得回收噢
        tp.recycle();
    }
//
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//获取宽高模式   差不多就是我们xml中的wrap  还是具体参数还是fill_parent
        int PwidthMode = MeasureSpec.getMode(widthMeasureSpec);
        int PheightMode = MeasureSpec.getMode(heightMeasureSpec);

        int PwidthSize = MeasureSpec.getSize(widthMeasureSpec);
        int PheightSize = MeasureSpec.getSize(heightMeasureSpec);

        measureChildren(widthMeasureSpec, heightMeasureSpec);

        int mwidth = 0;
        int mheight = 0;

        mheight = getChildAt(1).getMeasuredHeight();
        mwidth = getChildAt(1).getMeasuredWidth();
//如果说是自适应我们需要跟距内部组件来定义外部组件大小(viewgroup)
        mheight = (mheight + mRadios) * getChildCount();
        mwidth = (mwidth + mRadios) * getChildCount();

        if(PwidthMode==MeasureSpec.AT_MOST&&
                PheightMode==MeasureSpec.AT_MOST) {
            setMeasuredDimension(
                    mwidth, 
                    mheight);
        }else  if(PwidthMode==MeasureSpec.AT_MOST) {
            setMeasuredDimension(
                    mwidth, 
                    PheightSize);
        }
        else  if(PheightMode==MeasureSpec.AT_MOST) {
            setMeasuredDimension(
                    PwidthSize, 
                    mheight);
        }else {
            setMeasuredDimension(
                    PwidthSize, 
                    PheightSize);
        }
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {

        CircleLayout();

    }





//这来才是重点    onmeasure不用重写也可以看
    private void CircleLayout() {
        int count = getChildCount();
        //这里我们设置的是更具圆形组件
        float[] circleCentre = { getWidth() / 2 * 1.0f, getHeight() / 2 * 1.0f };

        if (openCenterCircle == false) {
    //求每个组件的弧度
            float oItem = (float) (2 * Math.PI / count * 1.0f);
            float[][] xyPosition = new float[count][2];

            for (int i = 0; i < count; i++) {
                xyPosition[i] = mSuan_radio.getXYPoint(circleCentre, mRadios, oItem * (i));

                int xLabel = (int) xyPosition[i][0];

                int yLabel = (int) xyPosition[i][1];

                View view = getChildAt(i);
                view.layout((int) (xLabel - view.getMeasuredWidth() / 2 * 1.0f),
                        (int) (yLabel - view.getMeasuredHeight() / 2 * 1.0f),
                        (int) (xLabel + view.getMeasuredWidth() / 2 * 1.0f),
                        (int) (yLabel + view.getMeasuredHeight() / 2 * 1.0f));

            }

        } else {

            float oItem = (float) (2 * Math.PI / (count - 1) * 1.0f);
            float[][] xyPosition = new float[count - 1][2];

            for (int i = 0; i < count - 1; i++) {
                xyPosition[i] = mSuan_radio.getXYPoint(circleCentre, mRadios, oItem * (i));

                int xLabel = (int) xyPosition[i][0];

                int yLabel = (int) xyPosition[i][1];

                View view = getChildAt(i + 1);
                view.layout((int) (xLabel - view.getMeasuredWidth() / 2 * 1.0f),
                        (int) (yLabel - view.getMeasuredHeight() / 2 * 1.0f),
                        (int) (xLabel + view.getMeasuredWidth() / 2 * 1.0f),
                        (int) (yLabel + view.getMeasuredHeight() / 2 * 1.0f));

            }

            View view = getChildAt(0);
            view.layout((int) (circleCentre[0] - view.getMeasuredWidth() / 2 * 1.0f),
                    (int) (circleCentre[1] - view.getMeasuredHeight() / 2 * 1.0f),
                    (int) (circleCentre[0] + view.getMeasuredWidth() / 2 * 1.0f),
                    (int) (circleCentre[1] + view.getMeasuredHeight() / 2 * 1.0f));

        }

    }

}

猜你喜欢

转载自blog.csdn.net/likui19921224/article/details/79129622
今日推荐