高毅 涂小琴 張春紅 丁勇
摘? 要: Android系統(tǒng)的組件不能完全滿足開發(fā)人員的需求,尤其在數(shù)據(jù)展示方面,而雷達(dá)圖是一種很好的數(shù)據(jù)展示工具,本文提出了一種雷達(dá)圖組件的實(shí)現(xiàn)方法,從顏色值轉(zhuǎn)換方法、布局空間設(shè)計(jì)、背景關(guān)鍵點(diǎn)計(jì)算、數(shù)據(jù)點(diǎn)計(jì)算、雷達(dá)圖繪制等方面對(duì)自定義雷達(dá)圖的設(shè)計(jì)實(shí)現(xiàn)過程做詳細(xì)描述。該組件布局整齊,使用方便,支持自定義,用戶體驗(yàn)好,相比現(xiàn)有的第三方開源方案,具有很好的實(shí)用性和創(chuàng)新性。
關(guān)鍵詞: 雷達(dá)圖;自定義;Android;數(shù)據(jù)可視化
中圖分類號(hào): TP317? ? 文獻(xiàn)標(biāo)識(shí)碼: A? ? DOI:10.3969/j.issn.1003-6970.2019.10.017
本文著錄格式:高毅,涂小琴,張春紅,等. 基于Android的自定義雷達(dá)圖組件[J]. 軟件,2019,40(10):7377
Custom Radar Chart Component Based on Android
GAO Yi, TU Xiao-qin, ZHANG Chun-hong, DING Yong
(College of Arts and Sciences, Yunnan Normal University, Kunming 650222, China)
【Abstract】: The components of the Android system can not fully meet the needs of developers, especially in the data display, and the radar chart is a good data display tool. This paper proposes a method for implementing the radar chart component, from the color value conversion method and layout, space design, background key point calculation, calculation of data points, and other aspects of a radar mapping of the radar chart design of the custom implementation is described in detail. The component is neatly arranged, easy to use, supports customization, and has a good user experience. Compared with existing third-party open source solutions, it has good practicability and innovation.
【Key words】: Radar chart; Custom; Android; Data visualization
0? 引言
在進(jìn)行Android應(yīng)用開發(fā)時(shí),離不開應(yīng)用界面的設(shè)計(jì),Android系統(tǒng)本身提供了很多組件用于界面設(shè)計(jì),常用的有文本框、編輯框、按鈕、單選按鈕與單選按鈕組、復(fù)選框、圖片框、下拉列表框、列表框、開關(guān)按鈕等。這些組件基本上能滿足大多數(shù)應(yīng)用的開發(fā)需求,但仍然有一些需求是滿足不了的,現(xiàn)今的大多數(shù)應(yīng)用離不開數(shù)據(jù)展示,尤其是移動(dòng)端的開發(fā),需要用到圖表來向用戶展示數(shù)據(jù)。然而,隨著數(shù)據(jù)可視化技術(shù)的飛速發(fā)展,雷達(dá)圖已經(jīng)進(jìn)入我們的生活,不僅僅是企業(yè)財(cái)務(wù),在個(gè)人帳務(wù)管理以及投資理財(cái)?shù)绕渌I(lǐng)域,雷達(dá)圖也開始嶄露頭角,應(yīng)用越來越廣泛[1]。但Android系統(tǒng)本身并不提供雷達(dá)圖組件,因此需要開發(fā)者來創(chuàng)建自定義的雷達(dá)圖組件,以實(shí)現(xiàn)用戶的特殊需求。
本文通過設(shè)計(jì)一個(gè)基于Android的雷達(dá)圖組件,實(shí)現(xiàn)了數(shù)據(jù)的可視化展示,該組件的實(shí)現(xiàn)繼承了View類,重寫了多個(gè)方法,加入了好多的組件屬性作為類的數(shù)據(jù)成員,并編寫了get方法和set方法,豐富了雷達(dá)圖組件的顯示樣式,根據(jù)ValueAnimator 對(duì)象值不斷的重繪,以實(shí)現(xiàn)動(dòng)畫效果,增強(qiáng)了用戶體驗(yàn)。下面將從顏色值轉(zhuǎn)換方法、布局空間設(shè)計(jì)、背景關(guān)鍵點(diǎn)計(jì)算、數(shù)據(jù)點(diǎn)計(jì)算、雷達(dá)圖繪制等方面對(duì)自定義雷達(dá)圖的設(shè)計(jì)實(shí)現(xiàn)過程做詳細(xì)描述。
1? 相關(guān)概念
1.1? 雷達(dá)圖
雷達(dá)又叫戴布拉圖、蜘蛛網(wǎng)圖。傳統(tǒng)的雷達(dá)圖被認(rèn)為是一種表現(xiàn)多維指標(biāo)(4維以上)數(shù)據(jù)的圖表。它將多個(gè)維度指標(biāo)的數(shù)據(jù)量映射到坐標(biāo)軸上,這些坐標(biāo)軸起始于同一個(gè)圓心點(diǎn),通常結(jié)束于圓周邊緣,將同一組的點(diǎn)使用線連接起來就稱為了雷達(dá)圖[2]。它可以將多維指標(biāo)數(shù)據(jù)進(jìn)行展示,但是點(diǎn)的相對(duì)位置和坐標(biāo)軸之間的夾角是沒有任何信息量的。在坐標(biāo)軸設(shè)置恰當(dāng)?shù)那闆r下雷達(dá)圖所圍面積能表現(xiàn)出一些信息量。
1.2? View
Android應(yīng)用的絕大部分UI組件都放在android.widget包及其子包、android.view包及其子包中,Android應(yīng)用的所有UI組件都繼承了View類,View組件非常類似于Swing編程的JPanel,它代表一個(gè)空白的矩形區(qū)域[3]。
基于Android UI組件的實(shí)現(xiàn)原理,開發(fā)者完全可以開發(fā)出項(xiàng)目定制的組件,當(dāng)Android系統(tǒng)提供的UI組件不足以滿足需求時(shí),可以通過繼承View來派生自定義組件。過程為,首先定義一個(gè)繼承View基類的子類,然后重寫View類的一個(gè)或多個(gè)方法來實(shí)現(xiàn)。
1.3? Canvas類
Canvas繪圖有三個(gè)基本要素:Canvas、繪圖坐標(biāo)系以及Paint。Canvas是畫布,我們通過Canvas的各種drawXXX方法將圖形繪制到Canvas上面,在drawXXX方法中我們需要傳入要繪制的圖形的坐標(biāo)形狀,還要傳入一個(gè)畫筆Paint。drawXXX方法以及傳入其中的坐標(biāo)決定了要繪制的圖形的形狀,比如drawCircle方法,用來繪制圓形,需要我們傳入圓心的x和y坐標(biāo),以及圓的半徑。drawXXX方法中傳入的畫筆Paint決定了繪制的圖形的一些外觀,比如是繪制的圖形的顏色,再比如是繪制圓面還是圓的輪廓線等。Android系統(tǒng)的設(shè)計(jì)吸收了很多已有系統(tǒng)的諸多優(yōu)秀之處,比如Canvas繪圖[4]。
1.4? Path類
Paint類保存了繪制幾何圖形、文本和位圖的樣式和顏色信息。也就是說我們可以使用Paint保存的樣式和顏色,來繪制圖形、文本和bitmap,這就是Paint的強(qiáng)大之處。接下來我們使用Paint來繪圖,并且看看該類有哪些樣式和顏色[3]。
2? 關(guān)鍵技術(shù)
2.1? 顏色值轉(zhuǎn)換方法
在Android程序設(shè)計(jì)中,我們可以在xml布局文件中使用井號(hào)加6位十六進(jìn)制(形如:#XXXXXX)或者井號(hào)加8位十六進(jìn)制(形如:#XXXXXXXX)來表示顏色值,而在java代碼中不行。用這種形式來表示顏色值還是非常直觀明了的,為了在java代碼中也能夠這樣表示,特地編寫FColor類來實(shí)現(xiàn)此功能。
FColor類的數(shù)據(jù)成員由alpha、red、green、blue構(gòu)成。其中alpha表示透明度的值,red表示紅色分量的值,green表示綠色分量的值,blue表示藍(lán)色分量的值。它們數(shù)據(jù)類型為int,取值范圍介于0到255之間。
FColor類中的關(guān)鍵方法public void setColor(String color),是把字符串表示的顏色值分割并轉(zhuǎn)換到alpha、red、green、blue四個(gè)分量上面,關(guān)鍵代碼如下。
int m=Integer.parseInt(color.replaceAll("^#",""), 16);
//8位十六進(jìn)制字符串顏色表示的轉(zhuǎn)換方法
if(color.length()==9){
this. alpha=(m&0XFF000000)>>24;
this. red =(m&0X00FF0000)>>16;
this. green =(m&0X0000FF00)>>8;
this. blue=m&0X000000FF;
}
else{//6位十六進(jìn)制字符串顏色表示的轉(zhuǎn)換方法
if(color.length()==7){
this. alpha=255;
this. red =(m&0XFF0000)>>16;
this. green =(m&0X00FF00)>>8;
this. blue=m&0X0000FF;
}
//若不是6位或者8位十六進(jìn)制字符串顏色表示,則默認(rèn)為黑色
else{
this. alpha=255;
this. red =0;
this. green =0;
this. blue=0;
}
}
2.2? 背景繪制
(1)布局空間設(shè)計(jì)
在實(shí)現(xiàn)雷達(dá)圖組件時(shí),布局空間的設(shè)計(jì)尤為關(guān)鍵。移動(dòng)端應(yīng)用開發(fā)最大的特點(diǎn)之一就是可用顯示空間小,要讓雷達(dá)圖有更好的顯示效果,必需要合理的分配布局空間。雷達(dá)圖的布局空間設(shè)計(jì)如圖1所示,由圖表標(biāo)題區(qū)、圖表繪制區(qū)和系列標(biāo)題區(qū)構(gòu)成[5-6]。其中,圖表標(biāo)題區(qū)用來顯示雷達(dá)圖的總標(biāo)題,圖表繪制區(qū)用來顯示雷達(dá)圖,系列標(biāo)題區(qū)用來顯示雷達(dá)圖的系列標(biāo)題。在雷達(dá)圖的設(shè)計(jì)過程中,為了能讓Android開發(fā)人員可以自定義標(biāo)題文本字體大小,首先計(jì)算該雷達(dá)圖在移動(dòng)設(shè)備端的顯示大小,再計(jì)算系列標(biāo)題區(qū)所占大小,最后得到圖表繪制區(qū)的大小。
(2)背景關(guān)鍵點(diǎn)計(jì)算
雷達(dá)圖背景的繪制,最為重要的就是關(guān)鍵點(diǎn)坐標(biāo)的計(jì)算,只要把關(guān)鍵點(diǎn)的點(diǎn)坐標(biāo)計(jì)算出來,就很
容易繪制出背景。雷達(dá)圖的背景設(shè)計(jì)如圖2所示,這是以5維指標(biāo)數(shù)據(jù)的雷達(dá)圖背景為例來設(shè)計(jì)的,該部分內(nèi)容是包含在圖1的圖表繪制區(qū)中。
雷達(dá)圖背景的主要組成部分是由一些大小不一的正多邊形組成,為了便于計(jì)算和控制,雷達(dá)圖背景是在一個(gè)圓心點(diǎn)坐標(biāo)為(centerX,centerY)、半徑為width/2的圓內(nèi)進(jìn)行繪制。Android中canvas的繪圖坐標(biāo)和數(shù)學(xué)的平面直角坐標(biāo)不同,向右代表X軸的正方向,向下代表Y軸的正方向。下面先以5維指標(biāo)數(shù)據(jù)的雷達(dá)圖背景的關(guān)鍵點(diǎn)坐標(biāo)進(jìn)行計(jì)算,然后總結(jié)出一般化的計(jì)算公式。
雷達(dá)圖背景是在一個(gè)圓內(nèi)繪制的,用(centerX, centerY)表示圓心坐標(biāo),r表示圓的半徑,N表示指標(biāo)數(shù)據(jù)的維度,n表示每一維指標(biāo)數(shù)據(jù)的刻度數(shù),θ表示相鄰指標(biāo)數(shù)據(jù)維度間的夾角。如圖2所示,Y軸的負(fù)方向作為起始參照線,從這條參照線順時(shí)針依次來布局指標(biāo)數(shù)據(jù)的維度,每一維指標(biāo)數(shù)據(jù)的刻度點(diǎn)是由內(nèi)向外依次編號(hào)。
以5維指標(biāo)數(shù)據(jù)的雷達(dá)圖為例,假設(shè)每一維指標(biāo)數(shù)據(jù)的刻度數(shù)為4(n=4),那么總共要計(jì)算20個(gè)坐標(biāo)點(diǎn)。這些坐標(biāo)點(diǎn)表示為Pi,j,i表示維度編號(hào),j表示維度內(nèi)部的刻度編號(hào),其中i=0,1,2,3,4,j=0,1,2,3。相鄰指標(biāo)數(shù)據(jù)維度間的夾角為72度。
第1維共有P0,0、P0,1、P0,2、P0,3 4個(gè)刻度點(diǎn),它們的坐標(biāo)計(jì)算結(jié)果如下:
P0,0坐標(biāo)為(0, –r/4)
P0,1坐標(biāo)為(0, (–r/4)*2)
P0,2坐標(biāo)為(0, (–r/4)*3)
P0,3坐標(biāo)為(0, (–r/4)*4)
第2維共有P1,0、P1,1、P1,2、P1,3? 4個(gè)刻度點(diǎn),它們的坐標(biāo)計(jì)算結(jié)果如下:
P1,0坐標(biāo)為(cos(90-72)*(r/4), –sin(90-72)*(r/4))
P1,1坐標(biāo)為(cos(90-72)*(r/4)*2, –sin(90-72)* (r/4)*2)
P1,2坐標(biāo)為(cos(90-72)*(r/4)*3, –sin(90-72)* (r/4)*3)
P1,3坐標(biāo)為(cos(90-72)*(r/4)*4, –sin(90-72)* (r/4)*4)
第3維共有P2,0、P2,1、P2,2、P2,3 4個(gè)刻度點(diǎn),它們的坐標(biāo)計(jì)算結(jié)果如下:
P2,0坐標(biāo)為(cos(90-72*2)*(r/4), –sin(90-72*2)* (r/4))
P2,1坐標(biāo)為(cos(90-72*2)*(r/4)*2, –sin(90-72*2)* (r/4)*2)
P2,2坐標(biāo)為(cos(90-72*2)*(r/4)*3, –sin(90-72*2)* (r/4)*3)
P2,3坐標(biāo)為(cos(90-72*2)*(r/4)*4, –sin(90-72*2)* (r/4)*4)
第4維共有P3,0、P3,1、P3,2、P3,3 4個(gè)刻度點(diǎn),它們的坐標(biāo)計(jì)算結(jié)果如下:
P3,0坐標(biāo)為(cos(90-72*3)*(r/4), –sin(90-72*3)* (r/4))
P3,1坐標(biāo)為(cos(90-72*3)*(r/4)*2, –sin(90-72*3)* (r/4)*2)
P3,2坐標(biāo)為(cos(90-72*3)*(r/4)*3, –sin(90-72*3)* (r/4)*3)
P3,3坐標(biāo)為(cos(90-72*3)*(r/4)*4, –sin(90-72*3)* (r/4)*4)
第5維共有P4,0、P4,1、P4,2、P4,3 4個(gè)刻度點(diǎn),它們的坐標(biāo)計(jì)算結(jié)果如下:
P4,0坐標(biāo)為(cos(90-72*4)*(r/4), –sin(90-72*4)* (r/4))
P4,1坐標(biāo)為(cos(90-72*4)*(r/4)*2, –sin(90-72*4)* (r/4)*2)
P4,2坐標(biāo)為(cos(90-72*4)*(r/4)*3, –sin(90-72*4)* (r/4)*3)
P4,3坐標(biāo)為(cos(90-72*4)*(r/4)*4, –sin(90-72*4)* (r/4)*4)
由上面的計(jì)算過程可以歸納出一般化的關(guān)鍵點(diǎn)的坐標(biāo)計(jì)算公式。一般化的關(guān)鍵點(diǎn)表示為Pi,j,i表示維度編號(hào),j表示維度內(nèi)部的刻度編號(hào),其中i=0,1,2,…,N–1,j=0,1,2,…,n–1。
首先計(jì)算相鄰指標(biāo)數(shù)據(jù)維度間的夾角θ。
(1)
Pi,j點(diǎn)x坐標(biāo)值計(jì)算公式如下:
(2)
Pi,j點(diǎn)y坐標(biāo)值計(jì)算公式如下:
(3)
2.3? 雷達(dá)圖繪制
(1)數(shù)據(jù)點(diǎn)計(jì)算
本文設(shè)計(jì)的雷達(dá)圖可以展示多個(gè)系列數(shù)據(jù)。在繪制雷達(dá)圖之前,要把每個(gè)數(shù)據(jù)對(duì)應(yīng)的數(shù)據(jù)點(diǎn)坐標(biāo)計(jì)算出來。數(shù)據(jù)點(diǎn)的坐標(biāo)計(jì)算和上面描述的背景關(guān)鍵點(diǎn)計(jì)算非常類似,關(guān)鍵代碼如下。
//計(jì)算相鄰指標(biāo)數(shù)據(jù)維度間的夾角
disTheta=360/keyItemsCount;
//遍歷系列數(shù)據(jù)
for(int i=0;i theta=0; //遍歷數(shù)據(jù)指標(biāo) for(int j=0;j //取數(shù)據(jù)指標(biāo)的值 value=radarSeries.getSeriesValues().get(j); //根據(jù)數(shù)據(jù)指標(biāo)的值計(jì)算該數(shù)據(jù)指標(biāo) 在該維度上的線段長(zhǎng)度 dis=radius*((value-valueMin)/(valueMa x-valueMin)); //計(jì)算數(shù)據(jù)指標(biāo)值對(duì)應(yīng)的數(shù)據(jù)點(diǎn)的X 坐標(biāo) seriesDataX[i][j]=Math. cos(Math.toRadians (90- theta *i))*dis; //計(jì)算數(shù)據(jù)指標(biāo)值對(duì)應(yīng)的數(shù)據(jù)點(diǎn)的Y 坐標(biāo) seriesDataY[i][j]= –1* Math.sin(Math. toRadians(90- theta *i))* dis; //計(jì)算下一個(gè)指標(biāo)數(shù)據(jù)維度與Y軸負(fù) 方向的夾角 theta=theta+disTheta; } } (2)雷達(dá)圖繪制的關(guān)鍵代碼 當(dāng)Android系統(tǒng)提供的UI組件不足以滿足需求時(shí),可以通過繼承View來派生自定義組件,并重寫View類的一個(gè)或多個(gè)方法來實(shí)現(xiàn),其中,onDraw方法尤為關(guān)鍵。onDraw方法的關(guān)鍵代碼如下: //遍歷系列數(shù)據(jù) for(int i=0;i //設(shè)置畫筆對(duì)象顏色屬性 linePaint.setARGB(seriesItemColor.get(i). getA(),seriesItemColor.get(i).getR(),series ItemColor.get(i).getG(),seriesItemColor. get(i).getB()); //設(shè)置畫筆對(duì)象粗細(xì) linePaint.setStrokeWidth(dpTopx(seriesItem StrokeWidth)); for(int j=0;j //取起始數(shù)據(jù)點(diǎn)坐標(biāo) startx=seriesDataX[i][j]; starty=seriesDataY[i][j]; //取終止數(shù)據(jù)點(diǎn)坐標(biāo) endx=seriesDataX[i][(j+1)%keyItems Count]; endy=seriesDataY[i][(j+1)%keyItems Count]; //畫線條 canvas.drawLine(centerX+startx*ani mated Value, centerY+starty*animated Value, centerX+ endx* animatedValue, centerY+endy*animatedValue, linePaint); } } 3? 實(shí)驗(yàn)效果 本文實(shí)現(xiàn)的雷達(dá)圖組件的效果如圖3和圖4所示,圖3是不帶陰影效果的,圖4有陰影效果。該 雷達(dá)圖可以顯示多個(gè)系列數(shù)據(jù),不同的系列數(shù)據(jù)顏色不一樣,而且還具有動(dòng)畫效果,動(dòng)畫效果為依次從內(nèi)到外顯示,相比現(xiàn)有的第三方類似的組件,具有更好的用戶體驗(yàn)。在實(shí)際應(yīng)用中,該雷達(dá)圖還可以自定義背景顏色、背景線條粗細(xì)、背景線條顏色、文本大小、文本顏色等屬性,滿足了Android開發(fā)者更多的需求,顯示效果的設(shè)置多樣化,使用更加靈活。盡管目前也有一些基于Android的雷達(dá)圖組件,或多或少都存在一些問題,如使用不便、不夠靈活等,相比之下,本文描述的雷達(dá)圖組件還是具有一定的實(shí)用性和創(chuàng)新性。 4? 結(jié)語 雷達(dá)圖在日常生活更常見、更長(zhǎng)用,可以展示出數(shù)據(jù)集中各個(gè)變量的權(quán)重高低情況,非常適用于展示性能數(shù)據(jù)。本文提出的基于Android的自定義雷達(dá)圖組件可以解決一些數(shù)據(jù)展示的問題,可以展示多個(gè)系列的數(shù)據(jù),方便不同系列的數(shù)據(jù)進(jìn)行對(duì)比,經(jīng)過測(cè)試,布局整齊,響應(yīng)速度快,動(dòng)畫效果良好,大大增強(qiáng)了用戶體驗(yàn),能滿足大多數(shù)Android應(yīng)用開發(fā)人員的需求。但是,還是存在一些不足,比如動(dòng)態(tài)性方面,能和用戶進(jìn)行交互展示,在以后的研究工作中,將在這一方面做深入研究。 參考文獻(xiàn) [1]王魯. 信息技術(shù)[M]. 昆明: 云南人民出版社, 2013: 97-103. [2]張文彤, 鄺春偉. SPSS統(tǒng)計(jì)分析基礎(chǔ)教程[M]. 北京市: 高等教育出版社, 2011, 11. [3]李剛, 瘋狂Android講義(第3版)[M]. 北京: 電子工業(yè)出版社, 2015, 6: 123. [4]啟艦, Android自定義控件開發(fā)入門與實(shí)踐[M]. 北京: 電子工業(yè)出版社, 2018, 7: 54. [5]高毅, 王昕, 楊克光. Android平臺(tái)下折線圖組件的研究和實(shí)現(xiàn)[J]. 現(xiàn)代計(jì)算機(jī), 2016, 5: 69-71. [6]高毅, 楊克光, 王昕. 基于Android平臺(tái)的柱狀圖組件的設(shè)計(jì)實(shí)現(xiàn)[J]. 現(xiàn)代計(jì)算機(jī), 2016, 6: 77-80. [7]馬明明, 胡俊. 面向文本的標(biāo)簽云可視化度量模型的研究[J]. 軟件, 2018, 39(5): 88-93. [8]羅宗祥. 基于新浪云的微博傳播可視化研究[J]. 軟件, 2012, 33(7): 117-119. [9]龔昊, 張琦. 數(shù)據(jù)中心三維可視化管理軟件的設(shè)計(jì)與實(shí)現(xiàn)[J]. 軟件, 2012, 33(11): 68-71. [10]鄺野, 馬璇. 信息可視化過程中色像差的補(bǔ)償方式研究[J]. 軟件, 2012, 33(12): 218-221.