高毅 涂小琴 張春紅 丁勇



摘? 要: Android系統的組件不能完全滿足開發人員的需求,尤其在數據展示方面,而雷達圖是一種很好的數據展示工具,本文提出了一種雷達圖組件的實現方法,從顏色值轉換方法、布局空間設計、背景關鍵點計算、數據點計算、雷達圖繪制等方面對自定義雷達圖的設計實現過程做詳細描述。該組件布局整齊,使用方便,支持自定義,用戶體驗好,相比現有的第三方開源方案,具有很好的實用性和創新性。
關鍵詞: 雷達圖;自定義;Android;數據可視化
中圖分類號: TP317? ? 文獻標識碼: A? ? DOI:10.3969/j.issn.1003-6970.2019.10.017
本文著錄格式:高毅,涂小琴,張春紅,等. 基于Android的自定義雷達圖組件[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? 引言
在進行Android應用開發時,離不開應用界面的設計,Android系統本身提供了很多組件用于界面設計,常用的有文本框、編輯框、按鈕、單選按鈕與單選按鈕組、復選框、圖片框、下拉列表框、列表框、開關按鈕等。這些組件基本上能滿足大多數應用的開發需求,但仍然有一些需求是滿足不了的,現今的大多數應用離不開數據展示,尤其是移動端的開發,需要用到圖表來向用戶展示數據。然而,隨著數據可視化技術的飛速發展,雷達圖已經進入我們的生活,不僅僅是企業財務,在個人帳務管理以及投資理財等其他領域,雷達圖也開始嶄露頭角,應用越來越廣泛[1]。但Android系統本身并不提供雷達圖組件,因此需要開發者來創建自定義的雷達圖組件,以實現用戶的特殊需求。
本文通過設計一個基于Android的雷達圖組件,實現了數據的可視化展示,該組件的實現繼承了View類,重寫了多個方法,加入了好多的組件屬性作為類的數據成員,并編寫了get方法和set方法,豐富了雷達圖組件的顯示樣式,根據ValueAnimator 對象值不斷的重繪,以實現動畫效果,增強了用戶體驗。下面將從顏色值轉換方法、布局空間設計、背景關鍵點計算、數據點計算、雷達圖繪制等方面對自定義雷達圖的設計實現過程做詳細描述。
1? 相關概念
1.1? 雷達圖
雷達又叫戴布拉圖、蜘蛛網圖。傳統的雷達圖被認為是一種表現多維指標(4維以上)數據的圖表。它將多個維度指標的數據量映射到坐標軸上,這些坐標軸起始于同一個圓心點,通常結束于圓周邊緣,將同一組的點使用線連接起來就稱為了雷達圖[2]。它可以將多維指標數據進行展示,但是點的相對位置和坐標軸之間的夾角是沒有任何信息量的。在坐標軸設置恰當的情況下雷達圖所圍面積能表現出一些信息量。
1.2? View
Android應用的絕大部分UI組件都放在android.widget包及其子包、android.view包及其子包中,Android應用的所有UI組件都繼承了View類,View組件非常類似于Swing編程的JPanel,它代表一個空白的矩形區域[3]。
基于Android UI組件的實現原理,開發者完全可以開發出項目定制的組件,當Android系統提供的UI組件不足以滿足需求時,可以通過繼承View來派生自定義組件。過程為,首先定義一個繼承View基類的子類,然后重寫View類的一個或多個方法來實現。
1.3? Canvas類
Canvas繪圖有三個基本要素:Canvas、繪圖坐標系以及Paint。Canvas是畫布,我們通過Canvas的各種drawXXX方法將圖形繪制到Canvas上面,在drawXXX方法中我們需要傳入要繪制的圖形的坐標形狀,還要傳入一個畫筆Paint。drawXXX方法以及傳入其中的坐標決定了要繪制的圖形的形狀,比如drawCircle方法,用來繪制圓形,需要我們傳入圓心的x和y坐標,以及圓的半徑。drawXXX方法中傳入的畫筆Paint決定了繪制的圖形的一些外觀,比如是繪制的圖形的顏色,再比如是繪制圓面還是圓的輪廓線等。Android系統的設計吸收了很多已有系統的諸多優秀之處,比如Canvas繪圖[4]。
1.4? Path類
Paint類保存了繪制幾何圖形、文本和位圖的樣式和顏色信息。也就是說我們可以使用Paint保存的樣式和顏色,來繪制圖形、文本和bitmap,這就是Paint的強大之處。接下來我們使用Paint來繪圖,并且看看該類有哪些樣式和顏色[3]。
2? 關鍵技術
2.1? 顏色值轉換方法
在Android程序設計中,我們可以在xml布局文件中使用井號加6位十六進制(形如:#XXXXXX)或者井號加8位十六進制(形如:#XXXXXXXX)來表示顏色值,而在java代碼中不行。用這種形式來表示顏色值還是非常直觀明了的,為了在java代碼中也能夠這樣表示,特地編寫FColor類來實現此功能。
FColor類的數據成員由alpha、red、green、blue構成。其中alpha表示透明度的值,red表示紅色分量的值,green表示綠色分量的值,blue表示藍色分量的值。它們數據類型為int,取值范圍介于0到255之間。
FColor類中的關鍵方法public void setColor(String color),是把字符串表示的顏色值分割并轉換到alpha、red、green、blue四個分量上面,關鍵代碼如下。
int m=Integer.parseInt(color.replaceAll("^#",""), 16);
//8位十六進制字符串顏色表示的轉換方法
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位十六進制字符串顏色表示的轉換方法
if(color.length()==7){
this. alpha=255;
this. red =(m&0XFF0000)>>16;
this. green =(m&0X00FF00)>>8;
this. blue=m&0X0000FF;
}
//若不是6位或者8位十六進制字符串顏色表示,則默認為黑色
else{
this. alpha=255;
this. red =0;
this. green =0;
this. blue=0;
}
}
2.2? 背景繪制
(1)布局空間設計
在實現雷達圖組件時,布局空間的設計尤為關鍵。移動端應用開發最大的特點之一就是可用顯示空間小,要讓雷達圖有更好的顯示效果,必需要合理的分配布局空間。雷達圖的布局空間設計如圖1所示,由圖表標題區、圖表繪制區和系列標題區構成[5-6]。其中,圖表標題區用來顯示雷達圖的總標題,圖表繪制區用來顯示雷達圖,系列標題區用來顯示雷達圖的系列標題。在雷達圖的設計過程中,為了能讓Android開發人員可以自定義標題文本字體大小,首先計算該雷達圖在移動設備端的顯示大小,再計算系列標題區所占大小,最后得到圖表繪制區的大小。
(2)背景關鍵點計算
雷達圖背景的繪制,最為重要的就是關鍵點坐標的計算,只要把關鍵點的點坐標計算出來,就很
容易繪制出背景。雷達圖的背景設計如圖2所示,這是以5維指標數據的雷達圖背景為例來設計的,該部分內容是包含在圖1的圖表繪制區中。
雷達圖背景的主要組成部分是由一些大小不一的正多邊形組成,為了便于計算和控制,雷達圖背景是在一個圓心點坐標為(centerX,centerY)、半徑為width/2的圓內進行繪制。Android中canvas的繪圖坐標和數學的平面直角坐標不同,向右代表X軸的正方向,向下代表Y軸的正方向。下面先以5維指標數據的雷達圖背景的關鍵點坐標進行計算,然后總結出一般化的計算公式。
雷達圖背景是在一個圓內繪制的,用(centerX, centerY)表示圓心坐標,r表示圓的半徑,N表示指標數據的維度,n表示每一維指標數據的刻度數,θ表示相鄰指標數據維度間的夾角。如圖2所示,Y軸的負方向作為起始參照線,從這條參照線順時針依次來布局指標數據的維度,每一維指標數據的刻度點是由內向外依次編號。
以5維指標數據的雷達圖為例,假設每一維指標數據的刻度數為4(n=4),那么總共要計算20個坐標點。這些坐標點表示為Pi,j,i表示維度編號,j表示維度內部的刻度編號,其中i=0,1,2,3,4,j=0,1,2,3。相鄰指標數據維度間的夾角為72度。
第1維共有P0,0、P0,1、P0,2、P0,3 4個刻度點,它們的坐標計算結果如下:
P0,0坐標為(0, –r/4)
P0,1坐標為(0, (–r/4)*2)
P0,2坐標為(0, (–r/4)*3)
P0,3坐標為(0, (–r/4)*4)
第2維共有P1,0、P1,1、P1,2、P1,3? 4個刻度點,它們的坐標計算結果如下:
P1,0坐標為(cos(90-72)*(r/4), –sin(90-72)*(r/4))
P1,1坐標為(cos(90-72)*(r/4)*2, –sin(90-72)* (r/4)*2)
P1,2坐標為(cos(90-72)*(r/4)*3, –sin(90-72)* (r/4)*3)
P1,3坐標為(cos(90-72)*(r/4)*4, –sin(90-72)* (r/4)*4)
第3維共有P2,0、P2,1、P2,2、P2,3 4個刻度點,它們的坐標計算結果如下:
P2,0坐標為(cos(90-72*2)*(r/4), –sin(90-72*2)* (r/4))
P2,1坐標為(cos(90-72*2)*(r/4)*2, –sin(90-72*2)* (r/4)*2)
P2,2坐標為(cos(90-72*2)*(r/4)*3, –sin(90-72*2)* (r/4)*3)
P2,3坐標為(cos(90-72*2)*(r/4)*4, –sin(90-72*2)* (r/4)*4)
第4維共有P3,0、P3,1、P3,2、P3,3 4個刻度點,它們的坐標計算結果如下:
P3,0坐標為(cos(90-72*3)*(r/4), –sin(90-72*3)* (r/4))
P3,1坐標為(cos(90-72*3)*(r/4)*2, –sin(90-72*3)* (r/4)*2)
P3,2坐標為(cos(90-72*3)*(r/4)*3, –sin(90-72*3)* (r/4)*3)
P3,3坐標為(cos(90-72*3)*(r/4)*4, –sin(90-72*3)* (r/4)*4)
第5維共有P4,0、P4,1、P4,2、P4,3 4個刻度點,它們的坐標計算結果如下:
P4,0坐標為(cos(90-72*4)*(r/4), –sin(90-72*4)* (r/4))
P4,1坐標為(cos(90-72*4)*(r/4)*2, –sin(90-72*4)* (r/4)*2)
P4,2坐標為(cos(90-72*4)*(r/4)*3, –sin(90-72*4)* (r/4)*3)
P4,3坐標為(cos(90-72*4)*(r/4)*4, –sin(90-72*4)* (r/4)*4)
由上面的計算過程可以歸納出一般化的關鍵點的坐標計算公式。一般化的關鍵點表示為Pi,j,i表示維度編號,j表示維度內部的刻度編號,其中i=0,1,2,…,N–1,j=0,1,2,…,n–1。
首先計算相鄰指標數據維度間的夾角θ。
(1)
Pi,j點x坐標值計算公式如下:
(2)
Pi,j點y坐標值計算公式如下:
(3)
2.3? 雷達圖繪制
(1)數據點計算
本文設計的雷達圖可以展示多個系列數據。在繪制雷達圖之前,要把每個數據對應的數據點坐標計算出來。數據點的坐標計算和上面描述的背景關鍵點計算非常類似,關鍵代碼如下。
//計算相鄰指標數據維度間的夾角
disTheta=360/keyItemsCount;
//遍歷系列數據
for(int i=0;i theta=0; //遍歷數據指標 for(int j=0;j //取數據指標的值 value=radarSeries.getSeriesValues().get(j); //根據數據指標的值計算該數據指標 在該維度上的線段長度 dis=radius*((value-valueMin)/(valueMa x-valueMin)); //計算數據指標值對應的數據點的X 坐標 seriesDataX[i][j]=Math. cos(Math.toRadians (90- theta *i))*dis; //計算數據指標值對應的數據點的Y 坐標 seriesDataY[i][j]= –1* Math.sin(Math. toRadians(90- theta *i))* dis; //計算下一個指標數據維度與Y軸負 方向的夾角 theta=theta+disTheta; } } (2)雷達圖繪制的關鍵代碼 當Android系統提供的UI組件不足以滿足需求時,可以通過繼承View來派生自定義組件,并重寫View類的一個或多個方法來實現,其中,onDraw方法尤為關鍵。onDraw方法的關鍵代碼如下: //遍歷系列數據 for(int i=0;i //設置畫筆對象顏色屬性 linePaint.setARGB(seriesItemColor.get(i). getA(),seriesItemColor.get(i).getR(),series ItemColor.get(i).getG(),seriesItemColor. get(i).getB()); //設置畫筆對象粗細 linePaint.setStrokeWidth(dpTopx(seriesItem StrokeWidth)); for(int j=0;j //取起始數據點坐標 startx=seriesDataX[i][j]; starty=seriesDataY[i][j]; //取終止數據點坐標 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? 實驗效果 本文實現的雷達圖組件的效果如圖3和圖4所示,圖3是不帶陰影效果的,圖4有陰影效果。該 雷達圖可以顯示多個系列數據,不同的系列數據顏色不一樣,而且還具有動畫效果,動畫效果為依次從內到外顯示,相比現有的第三方類似的組件,具有更好的用戶體驗。在實際應用中,該雷達圖還可以自定義背景顏色、背景線條粗細、背景線條顏色、文本大小、文本顏色等屬性,滿足了Android開發者更多的需求,顯示效果的設置多樣化,使用更加靈活。盡管目前也有一些基于Android的雷達圖組件,或多或少都存在一些問題,如使用不便、不夠靈活等,相比之下,本文描述的雷達圖組件還是具有一定的實用性和創新性。 4? 結語 雷達圖在日常生活更常見、更長用,可以展示出數據集中各個變量的權重高低情況,非常適用于展示性能數據。本文提出的基于Android的自定義雷達圖組件可以解決一些數據展示的問題,可以展示多個系列的數據,方便不同系列的數據進行對比,經過測試,布局整齊,響應速度快,動畫效果良好,大大增強了用戶體驗,能滿足大多數Android應用開發人員的需求。但是,還是存在一些不足,比如動態性方面,能和用戶進行交互展示,在以后的研究工作中,將在這一方面做深入研究。 參考文獻 [1]王魯. 信息技術[M]. 昆明: 云南人民出版社, 2013: 97-103. [2]張文彤, 鄺春偉. SPSS統計分析基礎教程[M]. 北京市: 高等教育出版社, 2011, 11. [3]李剛, 瘋狂Android講義(第3版)[M]. 北京: 電子工業出版社, 2015, 6: 123. [4]啟艦, Android自定義控件開發入門與實踐[M]. 北京: 電子工業出版社, 2018, 7: 54. [5]高毅, 王昕, 楊克光. Android平臺下折線圖組件的研究和實現[J]. 現代計算機, 2016, 5: 69-71. [6]高毅, 楊克光, 王昕. 基于Android平臺的柱狀圖組件的設計實現[J]. 現代計算機, 2016, 6: 77-80. [7]馬明明, 胡俊. 面向文本的標簽云可視化度量模型的研究[J]. 軟件, 2018, 39(5): 88-93. [8]羅宗祥. 基于新浪云的微博傳播可視化研究[J]. 軟件, 2012, 33(7): 117-119. [9]龔昊, 張琦. 數據中心三維可視化管理軟件的設計與實現[J]. 軟件, 2012, 33(11): 68-71. [10]鄺野, 馬璇. 信息可視化過程中色像差的補償方式研究[J]. 軟件, 2012, 33(12): 218-221.