1. 程式人生 > >Android 自定義View實現圓形環繞效果

Android 自定義View實現圓形環繞效果

之前專案中需要實現一個四周環繞中心圓形頭像的效果,感覺還是自定義比較方便,於是就自己封裝了一個控制元件去實現。先貼張圖顯示最終效果。

這裡寫圖片描述

首先自定義一個View繼承自LinearLayout,通過動態新增childView的方式將子控制元件新增到View中。思路是先新增中間圓形頭像,然後新增周圍的小圖示。
1.實現了圓形頭像的顯示,可以去參考網上或github上的demo,圓形頭像的外圈其實是一個View,然後再把頭像這個View蓋到這個View上。
2.計算好周圍相鄰view之間的角度,這裡是要水平鋪滿,最多6個,所以相鄰之間的角度為180/ (6 - 1) = 36度。如果是360環繞,放n個圖示,則相鄰之間的角度應該為360 / n 。
3.設定圖示到圓心的距離r。距離要大於頭像的半徑加上圖示的半徑。
4.確定圖示的座標:控制元件的寬為width,高為height。假設左邊第一個圖示是起始位置。圖示的起始角度為α= 180 - 36 * i,則它的橫座標為width/2 + cos(α)r,縱座標為height/2 - sin(α)

r。
5.設定座標點,預設為圖示的左上角頂點和右下點,如果想設圖示的中心點為座標,則左上定點x、y分別減去width/2和height/2,右下角分別加上width/2、height/2。
下面附上主要程式碼:

package com.ihaveu.iuzuan.cardgame.widget;

import android.content.Context;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import
android.view.View; import android.widget.LinearLayout; import com.ihaveu.iuzuan.cardgame.R; import com.ihaveu.iuzuan.cardgame.util.MeasureUtil; import java.util.ArrayList; import java.util.List; /** * Created by zhouhui on 17-6-8. * 新增圓形子控制元件實現時鐘環繞效果 */ public class CircleImageLayout extends LinearLayout
{
private double mAngle = 0;//初始角度 private int mX, mY;//子控制元件位置 private int mWidth, mHeight;//控制元件長寬 private int mRadius;//子控制元件距離控制元件圓心位置 private int mCount; private List<CircleImageView> mCircleImageViewList; private CircleImageView mCircleImageView; public CircleImageLayout(Context context) { this(context, null); } public CircleImageLayout(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); } public CircleImageLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mCircleImageViewList = new ArrayList<>(); } /** * 設定子控制元件到控制元件圓心的位置 */ public void setRadius(int radius) { mRadius = radius; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); mWidth = getMeasuredWidth(); mHeight = getMeasuredHeight(); } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); initDraw(); } public void initDraw() { mCount = getChildCount(); for (int i = 0; i < mCount; i++) { View child = getChildAt(i); child.getWidth(); child.getHeight(); if (i == 0) { mX = mWidth / 2; mY = mHeight / 2; } else { mAngle = 180 - 180 / (mCount - 1) * (i - 1); mX = (int) (mWidth / 2 + Math.cos(Math.toRadians(mAngle)) * mRadius); mY = (int) (mHeight / 2 - Math.sin(Math.toRadians(mAngle)) * mRadius); } child.layout(mX - child.getWidth() / 2, mY - child.getHeight() / 2, mX + child.getWidth() / 2, mY + child.getHeight() / 2); } } /** * 初始化環繞數量半徑 */ public void init(int count, int radius) { mRadius = radius; for (int i = 0; i < count + 1; i++) { CircleImageView imageView = new CircleImageView(getContext()); if (i == 0) { //i為0時為圓型頭像 View view = LayoutInflater.from(getContext()).inflate(R.layout.layout_header, null, true); mCircleImageView = (CircleImageView) view.findViewById(R.id.iv_header); addView(view); } else { addView(imageView, MeasureUtil.dip2px(15), MeasureUtil.dip2px(15)); mCircleImageViewList.add(imageView); } } } }