1. 程式人生 > >Android自定義view實現扇形

Android自定義view實現扇形

Android自定義view實現扇形

android可以通過Canvas實現各種形狀,其中drawArc這個方法可以繪製弧形。

public void drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)
oval :指定圓弧的外輪廓矩形區域。
startAngle: 圓弧起始角度,單位為度。
sweepAngle: 圓弧掃過的角度,順時針方向,單位為度。
useCenter: 如果為True時,在繪製圓弧時將圓心包括在內,通常用來繪製扇形。
paint: 繪製圓弧的畫板屬性,如顏色,是否填充等。

因為專案需要實現這樣一個效果,左右兩邊是半圓形凹槽 中間是虛線。

左右兩邊是半圓形凹槽

考慮可以把這個效果分為三部分來實現,既左右凹槽和中間實現部分。
左右凹槽可以使用shape繪製圓角矩形來實現,程式碼如下:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" 
    android:shape="rectangle"
    >
	<!-- 填充editView的顏色 -->
	<solid android:color="@color/background"/>
	<!-- 設定圓角的弧度,radius半徑越大,editView的邊角越圓 -->
	<corners
		android:bottomRightRadius="10dp"
		android:topRightRadius="10dp"
		android:bottomLeftRadius="0dp"
		android:topLeftRadius="0dp"
		/>
	<stroke
		android:color="@color/background"
		android:width="1dp" />
	<size android:height="20dp"
		android:width="10dp"/>
</shape>

使用此方法在genymotion android4.1的裝置上效果有問題,
這裡寫圖片描述
如黑框所示,不知為何不是半圓,同樣的程式碼在genymotion的5.1裝置上執行正常顯示半圓。
這裡寫圖片描述
如果有知道為啥的同學請不吝賜教。

後來就想不然就自己定義一個view來實現這個半圓吧。下面貼出自定義view的JAVA程式碼:

package com.feifan.elephantdoctor.platform.common.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;

import com.feifan.elephantdoctor.R;

/**
 * Created by qinyy on 2016/7/21.
 */
public class ArchView extends View
{
	//填充顏色
    private int mSolidColor;
    //元件寬度
    private int mWidth;
    //元件高度
    private int mHeight;
    //開始繪製圓弧(扇形)的角度;繪製跨度
    private int mStartAngle,mSweepAngle;
    //該弧形所面向的方向(弧相對圓心的方向)
    private int mOrientation;
    public ArchView(Context context)
    {
        super(context);

    }

    public ArchView(Context context, AttributeSet attrs)
    {
        super(context, attrs);
        //從xml中獲取屬性
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ArchView);
        mSolidColor = typedArray.getColor(R.styleable.ArchView_solidColor,context.getResources().getColor(R.color.trans));
        mWidth = (int) typedArray.getDimension(R.styleable.ArchView_archWidth,0);
        mHeight = (int) typedArray.getDimension(R.styleable.ArchView_archHeight,0);
        mStartAngle = typedArray.getInt(R.styleable.ArchView_startAngle,0);
        mSweepAngle = typedArray.getInt(R.styleable.ArchView_sweepAngle,0);
        mOrientation = typedArray.getInt(R.styleable.ArchView_orientation,-1);
    }


    @Override protected void onDraw(Canvas canvas)
    {
        super.onDraw(canvas);
        Paint paint = new Paint();
        paint.setColor(mSolidColor);
        //去除鋸齒效果
        paint.setAntiAlias(true);
        //如果方向向左
        //外輪廓oval要繪製成mWidth*2,不然繪製出的圖形很小,個人分析主要是因為圓心會在oval的中心繪製,所以如果oval的寬度如果設定和元件寬度一致的話,無法實現半圓的直徑和邊重疊的效果,最後顯示出來的尺寸在xml中的android:width中限制。
        if(mOrientation == 0)
        {
            RectF oval = new RectF(0,0,mWidth*2,mHeight);
            canvas.drawArc(oval,mStartAngle,mSweepAngle,false,paint);
        }
        //如果方向向右
        else if(mOrientation == 1)
        {
            RectF oval = new RectF(-mWidth,0,mWidth,mHeight);
            canvas.drawArc(oval,mStartAngle,mSweepAngle,false,paint);
        }

    }
}

自定義attrs

   <declare-styleable name="ArchView">
        <attr name="archWidth" format="dimension"/>
        <attr name="archHeight" format="dimension"/>
        <attr name="solidColor" format="color"/>
        <attr name="sweepAngle" format="integer"/>
        <attr name="startAngle" format="integer"/>
        <attr name="orientation" format="enum">
            <enum name="left" value="0"/>
            <enum name="right" value="1"/>
        </attr>
    </declare-styleable>

xml中使用自定義view:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/linear_tab"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center_vertical"
    android:orientation="horizontal">

    <com.feifan.elephantdoctor.platform.common.view.ArchView
        xmlns:archView="http://schemas.android.com/apk/res-auto"
        android:layout_width="7dp"
        android:layout_height="14dp"
        archView:archHeight="14dp"
        archView:archWidth="7dp"
        archView:solidColor="@color/background"
        archView:startAngle="270"
        archView:sweepAngle="180"
        archView:orientation="right"
         />

    <View
        android:layout_width="0dp"
        android:layout_height="2dp"
        android:layout_weight="1"
        android:background="@drawable/reservation_shape_line"
        android:layerType="software" />

    <com.feifan.elephantdoctor.platform.common.view.ArchView
        xmlns:archView="http://schemas.android.com/apk/res-auto"
        android:layout_width="7dp"
        android:layout_height="14dp"
        archView:archHeight="14dp"
        archView:archWidth="7dp"
        archView:solidColor="@color/background"
        archView:startAngle="90"
        archView:sweepAngle="180"
        archView:orientation="left"
        />

</LinearLayout>