安卓圓形佈局

這些日子一直想自己在安卓平臺上寫個類似蘋果小白球的小程序,仗着自己會點JAVA就決定開始幹了。
然後在其中需要做一個圓形的佈局,於是在網上各種搜索,終究還是實現了。
覺得這個圓形佈局很有意思,於是有了這篇文章,新手開寫,請老師傅們多多指導。

首先我們分析一下這個圓形佈局的佈局,分成三個大的部分:

  1. 原點
  2. 以原點爲中心承載元素的圓
  3. 需要佈局在圓上的元素

那麼,先從這個圓來說,我們在一個佈局內(可以是RelativeLayout或LinearLayout)弄出一個圓,圓最大直徑爲佈局寬高中的最小值。如下圖:

佈局圖解析

最外圍的深灰色長方形爲我們的佈局;紅色圓爲佈局內最大的圓;
黃色小圓,爲中心元素;分佈四周的8個綠色的爲參與圓形佈局的子元素。
其中o爲原點(圓心),oa爲圓的半徑,ab爲佈局的高度,也就是圓的直徑。
角aor的角度爲360/8;
以oa爲起點,oa至or的弧度爲(2 * Math.PI / 360) * (360 / 8) * 1;
爲了參與圓形佈局的元素不跑到我們的佈局外面,
所以在計算位置時,圓的半徑應該爲or = oa – 元素寬度/2;所以圖中灰色圓,纔是我們真正計算時使用到的圓。
現在我們要計算黃色圓的XY座標值,通過getX();getY();我們能獲取到中心元素左上角的XY座標值,即下圖中m的位置;
那麼中心元素元心的位置則爲o.x = m.x + 中心元素寬度/2;o.y = m.y + 中心元素高度/2;
假設m的xy爲{0,0},中心元素的寬度爲50,高度爲50,那麼中心元素中心點的xy爲{0+50/2,0+50/2},即中心元素中心位置的XY座標爲{25,25},同理,其他各個分佈在圓上的子元素的中心位置也以此類推。

這裏寫圖片描述

佈局分析先到這兒,我們接下來直接上代碼,在代碼裏,我們以6個元素參與圓形佈局爲例。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.demo.MainActivity">

    <RelativeLayout
        android:id="@+id/circle_layout"
        android:layout_width="300dp"
        android:layout_height="200dp"
        android:background="#837f7f"
        android:layout_centerInParent="true"
        >

        <Button
            android:id="@+id/btn_000"
            android:layout_width="60dp"
            android:layout_height="60dp"
            android:text="0"
            />
        <Button
            android:id="@+id/btn_001"
            android:layout_width="60dp"
            android:layout_height="60dp"
            android:text="1"
            />
        <Button
            android:id="@+id/btn_002"
            android:layout_width="60dp"
            android:layout_height="60dp"
            android:text="2"
            />
        <Button
            android:id="@+id/btn_003"
            android:layout_width="60dp"
            android:layout_height="60dp"
            android:text="3"
            />
        <Button
            android:id="@+id/btn_004"
            android:layout_width="60dp"
            android:layout_height="60dp"
            android:text="4"
            />
        <Button
            android:id="@+id/btn_005"
            android:layout_width="60dp"
            android:layout_height="60dp"
            android:text="5"
            />

        <Button
            android:id="@+id/client_btn"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_margin="50dp"
            android:layout_centerInParent="true"
            android:text="中"
            android:background="@xml/shape"
            />

    </RelativeLayout>

</RelativeLayout>

代碼效果如下圖:
這裏寫圖片描述

我們要以”中”這個中心元素,在灰色佈局類範圍內,將另外6個子元素進行圓形佈局,爲了省事,我沒有將6個子元素再做佈局,直接堆一塊兒了。

我們先獲取佈局內除“中”元素以外的其他6個子元素,代碼:

/**
     * 獲取指定元素下的子元素
     * @param parentView
     * @return
     */
    private List<View> getChildView(ViewGroup parentView){
        List<View> views = new ArrayList<View>();
        int child_count = parentView.getChildCount() - 1;//排除掉中心元素
        String packageName = getApplicationContext().getPackageName();//獲取當前應用包名
        View view;
        String id_name;
        Integer id;
        for (int i = 0; i< child_count; i++){
            id_name = "btn_00" + i; //拼接ID名稱
            /**
            因爲懶,所以用了循環去找元素,前提是元素ID有規律
            當然,也可以用getChilds()的方式獲取所有子元素,再排除掉中心元素
            */
            id = getResources().getIdentifier(id_name, "id", packageName);//根據ID名稱獲取ID值
            view = findViewById(id);//根據ID找元素
            views.add(view);//添加元素
        }
        return views;
    }

找完子元素,再將這6個子元素相對“中”元素進行佈局,代碼:

/**
     * 創建圓形佈局
     * @param clientView 圓形佈局的中心元素
     * @param views 參與圓形佈局的元素
     */
    private void createCircleLayout(View clientView,List<View> views){
        //大圓的中心
        int[] location = new int[2] ;
        location[0] = (int) clientView.getX();//獲取中心元素相對父級的X座標
        location[1] = (int) clientView.getY();//獲取中心元素相對父級的Y座標
        //當前中心元素的X座標
        Double zeroX = Double.valueOf(location[0]);
        //X座標加元素寬度的一半,則爲元素X的中心座標
        zeroX = zeroX + clientView.getWidth()/2;
        //當前中心元素的Y座標
        Double zeroY = Double.valueOf(location[1]);
        //Y座標加中心元素高度的一半,則爲元素Y的中心座標
        zeroY = zeroY + clientView.getHeight()/2;
        /**
         * 以上定下了圓的中心座標
         */

        /**
         * 獲取圓的半徑
         * 1.獲取當前中心元素的父元素
         * 2.計算父元素內圓的最大半徑
         */
        View clientViewParent = (View) clientView.getParent();
        Integer radius = Math.min(clientViewParent.getWidth(), clientViewParent.getHeight()) / 2;

        //參與圓形佈局的元素數量
        int count = views.size();
        View child_view;
        //定義弧度,計算子項在圓上位置時需要用到
        Double hudu = 0d;
        //根據子項的數量,計算每個子項間的平均角度
        Double angleDelay = 360d / count;
        Double tmpX;//子項X位置
        Double tmpY;//子項Y位置

        for (int i = 0; i<count; i++){
            child_view = views.get(i);

            Integer tmp_radius = radius - Math.max(child_view.getWidth(),child_view.getHeight()) / 2;

            //循環計算每一個子項的弧度
            hudu = (2 * Math.PI / 360) * angleDelay * i;
            tmpX = zeroX + Math.sin(hudu) * tmp_radius;//計算子項的X座標
            tmpY = zeroY - Math.cos(hudu) * tmp_radius;//計算子項的Y座標

            tmpX = tmpX - child_view.getWidth() / 2; //計算子項的中心點X座標
            tmpY = tmpY - child_view.getHeight() / 2;//計算子項的中心點Y座標

            child_view.setBackgroundDrawable(clientView.getBackground());//將中心元素的圓形樣式copy給子元素

            child_view.setX(tmpX.intValue()); //設置子項的X座標
            child_view.setY(tmpY.intValue()); //設置子項的Y座標
        }
    }

最後呢,我們將圓形佈局綁定在“中”元素的點擊事件上,代碼:

        Button button = (Button) findViewById(R.id.client_btn);
        button.setOnClickListener(new ClientBtnOnClick());
class ClientBtnOnClick implements View.OnClickListener{
        @Override
        public void onClick(View v) {
            //需要圓形佈局的元素
            ViewGroup circle_layout = (ViewGroup) findViewById(R.id.circle_layout);
            //獲取子元素
            List<View> views = getChildView(circle_layout);
            //對子元素進行圓形佈局
            createCircleLayout(v,views);
        }
    }

上下極簡效果圖
這裏寫圖片描述

最後上下稍微漂亮點的效果圖
這裏寫圖片描述

大家若是有什麼不懂或需要指正的,可以在下面評論區中留言哈,我看到後會回的,另外對android有興趣的同學可以加我們程序員劉某人的羣:555974449,羣裏面有很多大神的,而且很熱情,很熱心的,大家不懂的可以問的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章