版权声明:本文为博主原创文章,未经博主允许不得转载。 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));
}
}
}