Android表格自定義控件使用詳解
近期公司要做報(bào)表功能,在網(wǎng)上搜索下表格的樣式后便自己寫了一個(gè)自定義的表格控件,該表格控件能根據(jù)設(shè)置的數(shù)據(jù)中數(shù)據(jù)的最大值自動(dòng)設(shè)置左側(cè)信息欄顯示的值,使得條形圖能盡量的充滿控件,條形圖部分支持左右滑動(dòng),數(shù)據(jù)的長(zhǎng)度可能超過(guò)控件本身所能容納的長(zhǎng)度,所以在繪制的時(shí)候做了判斷,當(dāng)需要繪制的部分不再控件范圍內(nèi)則不進(jìn)行繪制,具體請(qǐng)閱讀代碼,目前只支持一個(gè)名稱對(duì)應(yīng)一條數(shù)據(jù),如有不足之處,大家提出幫忙修改
使用方法如下:
在xml文件中定義控件屬性
<RelativeLayout ? ? xmlns:android="http://schemas.android.com/apk/res/android" ? ? xmlns:tools="http://schemas.android.com/tools" ? ? android:layout_width="match_parent" ? ? android:layout_height="match_parent" ? ? android:background="#333333" ? ? tools:context=".MainActivity"> ? ? <com.example.administrator.widget.MyChatView ? ? ? ? android:id="@+id/chatView" ? ? ? ? android:layout_width="match_parent" ? ? ? ? android:layout_height="250dp" ? ? ? ? android:layout_marginTop="100dp" ? ? ? ? android:background="#FFFFFF" ? ? ? ? /> </RelativeLayout>
在Activity中設(shè)置控件要顯示的數(shù)據(jù)、設(shè)置顯示的樣式
public class MainActivity extends AppCompatActivity { ? ? private MyChatView mMyChatView; ? ? @Override ? ? protected void onCreate(Bundle savedInstanceState) { ? ? ? ? super.onCreate(savedInstanceState); ? ? ? ? setContentView(R.layout.activity_main); ? ? ? ? mMyChatView = (MyChatView) this.findViewById(R.id.chatView); ? ? ? ? mMyChatView.setData(getData1()) ? ? ? ? ? ? ? ? .setDataCompany("美元") ? ? ? ? ? ? ? ? .setDataTitle("測(cè)試") ? ? ? ? ? ? ? ? .setLeftTextColor(Color.RED) ? ? ? ? ? ? ? ? .setBottomTextColor(Color.BLUE) ? ? ? ? ? ? ? ? .setmDataTopTextColor(Color.RED) ? ? ? ? ? ? ? ? ? ? ? ? .setDataBackgroundColor(Color.parseColor("#ABCDEF")) ? ? ? ? ? ? ? ? .setDataColor(Color.RED) ? ? ? ? ? ? ? ? .setTitleColor(Color.BLUE) ? ? ? ? ? ? ? ? .setLeftTextSize(12) ? ? ? ? ? ? ? ? .setBottomTextSize(15) ? ? ? ? ? ? ? ? .setDataTopTextSize(10) ? ? ? ? ? ? ? ? .setTitleTextSize(20) ? ? ? ? ? ? ? ? .setSpanBottomText(15); ? ? } ? ? /** ? ? ?* 獲取測(cè)試數(shù)據(jù) ? ? ?* @return 測(cè)試用的數(shù)據(jù) ? ? ?*/ ? ? private List<Map<String, String>> getData1(){ ? ? ? ? List<Map<String, String>> data = new ArrayList<>(); ? ? ? ? HashMap<String, String> map; ? ? ? ? int temp; ? ? ? ? for (int i=0; i<100; i++) { ? ? ? ? ? ? map = new HashMap<>(); ? ? ? ? ? ? map.put(MyChatView.NAME, "name:"+i); ? ? ? ? ? ? temp = (int) (Math.random()*100); ? ? ? ? ? ? map.put(MyChatView.VALUE, temp +"."+i*i); ? ? ? ? ? ? data.add(map); ? ? ? ? } ? ? ? ? return data; ? ? } }
自定義控件代碼:
public class MyChatView extends View { ? ? /** 數(shù)據(jù)集合中的 Map 集合存放信息的鍵 */ ? ? public static final String NAME = "name"; ? ? /** 數(shù)據(jù)集合中的 Map 集合存放數(shù)據(jù)的鍵 */ ? ? public static final String VALUE = "value"; ? ? /** 上下文 */ ? ? private Context mContext; ? ? /** 控件的高度 */ ? ? private int mHeight; ? ? /** 控件的寬度 */ ? ? private int mWidget; ? ? /** 數(shù)據(jù) */ ? ? private List<Map<String, String>> mData; ? ? /** 數(shù)據(jù)單位 */ ? ? private String mDataCompany = "單位: "; ? ? /** 底部表格名稱 */ ? ? private String mDataTitle = null; ? ? /** 底部信息欄文字的大小 */ ? ? private int mBottomTextSize; ? ? /** 左側(cè)等分信息欄文字的大小 */ ? ? private int mLeftTextSize; ? ? /** 柱狀圖頂部文字的大小 */ ? ? private int mDataTopTextSize; ? ? /** 表格標(biāo)題文字大小 */ ? ? private int mTitleTextSize; ? ? /** 左側(cè)文字與數(shù)據(jù)區(qū)域的間隔 */ ? ? private int mSpanLeftText; ? ? /** 柱狀圖頂部文字與柱狀圖的間隔 */ ? ? int mSpanDataTopText; ? ? /** 底部信息字符串間隔 */ ? ? int mSpanBottomText; ? ? /** 底部信息字符串與控件底部間隔 */ ? ? int mSpanBottom; ? ? /** 繪制數(shù)據(jù)部分的背景顏色 */ ? ? private int mDataBackgroundColor = Color.WHITE; ? ? /** 底部信息字符串顏色 */ ? ? private int mBottomTextColor = Color.BLACK; ? ? /** 柱狀圖柱狀部分顏色 */ ? ? private int mDataColor = Color.BLACK; ? ? /** 左邊信息欄文字顏色 */ ? ? private int mLeftTextColor = Color.BLACK; ? ? /** 柱狀圖頂部文字顏色 */ ? ? private int mDataTopTextColor = Color.BLACK; ? ? /** 標(biāo)題顏色 */ ? ? private int mTitleColor = Color.BLACK; ? ? /** 表格移動(dòng)的位置 */ ? ? private int mChartMovedSize = 0; ? ? /** 用戶按下時(shí) X 方向位置 */ ? ? private int mDownX = 0; ? ? /** 用戶松手是 X 方向位置 */ ? ? private int mUpX = 0; ? ? /** 表格 X 方向移動(dòng)的最大距離 */ ? ? private int mChartMaxMovedLengthX; ? ? public MyChatView(Context context) { ? ? ? ? this(context, null); ? ? } ? ? public MyChatView(Context context, AttributeSet attrs) { ? ? ? ? this(context, attrs, 0); ? ? } ? ? public MyChatView(Context context, AttributeSet attrs, int defStyleAttr) { ? ? ? ? super(context, attrs, defStyleAttr); ? ? ? ? this.mContext = context; ? ? ? ? this.mBottomTextSize = dpToPx(context, 15); ? ? ? ? this.mLeftTextSize = dpToPx(context, 10); ? ? ? ? this.mDataTopTextSize = dpToPx(context, 10); ? ? ? ? this.mSpanLeftText = dpToPx(context, 2); ? ? ? ? this.mSpanDataTopText = dpToPx(context, 3); ? ? ? ? this.mSpanBottomText = dpToPx(context, 10); ? ? ? ? this.mSpanBottom = dpToPx(context, 8); ? ? ? ? this.mTitleTextSize = dpToPx(context, 20); ? ? } ? ? @Override ? ? protected void onSizeChanged(int w, int h, int oldw, int oldh) { ? ? ? ? super.onSizeChanged(w, h, oldw, oldh); ? ? ? ? this.mHeight = h; ? ? ? ? this.mWidget = w; ? ? } ? ? @Override ? ? public boolean onTouchEvent(@NonNull MotionEvent event) { ? ? ? ? int action = event.getAction(); ? ? ? ? switch (action) { ? ? ? ? ? ? case MotionEvent.ACTION_DOWN: ? ? ? ? ? ? ? ? mDownX = (int) event.getX(); ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? case MotionEvent.ACTION_MOVE: ? ? ? ? ? ? ? ? mUpX = (int) event.getX(); ? ? ? ? ? ? ? ? shouldMoveChart(); ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? case MotionEvent.ACTION_UP: ? ? ? ? ? ? ? ? mUpX = (int) event.getX(); ? ? ? ? ? ? ? ? shouldMoveChart(); ? ? ? ? ? ? ? ? break; ? ? ? ? } ? ? ? ? return true; ? ? } ? ? /** ? ? ?* 判斷移動(dòng)的距離大于規(guī)定距離就移動(dòng)表格 ? ? ?*/ ? ? private void shouldMoveChart (){ ? ? ? ? if (mChartMaxMovedLengthX<mWidget) { ? ? ? ? ? ? this.mChartMaxMovedLengthX = (getXTotalLength() - mWidget*2/3); ? ? ? ? } ? ? ? ? int size = dpToPx(mContext, 2); ? ? ? ? if ((mUpX-mDownX)>=size || (mDownX-mUpX)>=size ) { ? ? ? ? ? ? mChartMovedSize += (mUpX - mDownX); ? ? ? ? ? ? mDownX = mUpX; ? ? ? ? ? ? if (mChartMovedSize>=0) { ? ? ? ? ? ? ? ? mChartMovedSize = 0; ? ? ? ? ? ? } ? ? ? ? ? ? if (mChartMovedSize<-mChartMaxMovedLengthX) { ? ? ? ? ? ? ? ? mChartMovedSize = -mChartMaxMovedLengthX; ? ? ? ? ? ? } ? ? ? ? ? ? this.invalidate(); ? ? ? ? } ? ? } ? ? private InnerDraw innerDraw; ? ? @Override ? ? protected void onDraw(Canvas canvas) { ? ? ? ? super.onDraw(canvas); ? ? ? ? if (innerDraw==null) { ? ? ? ? ? ? innerDraw = new InnerDraw(canvas); ? ? ? ? } else { ? ? ? ? ? ? innerDraw.initData(canvas); ? ? ? ? } ? ? ? ? innerDraw.drawLeftMenue(); ? ? ? ? innerDraw.drawDataBackground(); ? ? ? ? innerDraw.drawDataTitle(); ? ? ? ? innerDraw.drawCompany(); ? ? ? ? int dataSize = mData.size(); ? ? ? ? for (int i=0; i<dataSize; i++) { ? ? ? ? ? ? //設(shè)置數(shù)據(jù),必須在第一行 ? ? ? ? ? ? int state = innerDraw.startDrawBody(mData.get(i), i); ? ? ? ? ? ? if (state==0) { ? ? ? ? ? ? ? ? continue; ? ? ? ? ? ? } else if (state==-1) { ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? } ? ? ? ? ? ? innerDraw.drawDataTopText(); ? ? ? ? ? ? innerDraw.drawDataBar(); ? ? ? ? ? ? innerDraw.drawBottomMessage(); ? ? ? ? ? ? innerDraw.endDrawBody(); ? ? ? ? } ? ? } ? ? /** ? ? ?* 根據(jù)文字大小獲取文字高度 ? ? ?* @param paint 畫筆 ? ? ?* @param textSize 要繪制的文字的大小 ? ? ?* @return 要繪制文字的高度 ? ? ?*/ ? ? private int getTextHeight (Paint paint, int textSize){ ? ? ? ? String text = "測(cè)試"; ? ? ? ? Rect rect = new Rect(); ? ? ? ? paint.setTextSize(textSize); ? ? ? ? paint.getTextBounds(text, 0, text.length(), rect); ? ? ? ? return rect.height(); ? ? } ? ? /** ? ? ?* 根據(jù)文字大小獲取文字寬度 ? ? ?* @param paint 畫筆 ? ? ?* @param text 要繪制的文字 ? ? ?* @param textSize 要繪制的文字的大小 ? ? ?* @return 要繪制文字的寬度 ? ? ?*/ ? ? private int getTextWidth (Paint paint, String text, int textSize){ ? ? ? ? Rect rect = new Rect(); ? ? ? ? paint.setTextSize(textSize); ? ? ? ? paint.getTextBounds(text, 0, text.length(), rect); ? ? ? ? return rect.width(); ? ? } ? ? /** ? ? ?* 獲取左側(cè)等分等分信息中文字最長(zhǎng)的字符串 ? ? ?* @return 字符串,抹去數(shù)字后面小數(shù)點(diǎn) ? ? ?*/ ? ? private String getLeftValueMaxString (){ ? ? ? ? int size = mData.size(); ? ? ? ? String maxLengthString = "1"; ? ? ? ? String tempString; ? ? ? ? for (int i=0; i<size; i++) { ? ? ? ? ? ? tempString = mData.get(i).get(VALUE); ? ? ? ? ? ? if (tempString.length()>maxLengthString.length()) { ? ? ? ? ? ? ? ? maxLengthString = tempString; ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? if (maxLengthString.contains(".")) { ? ? ? ? ? ? maxLengthString = maxLengthString.substring(0, maxLengthString.indexOf('.')+2); ? ? ? ? } ? ? ? ? return maxLengthString; ? ? } ? ? /** ? ? ?* 獲取最長(zhǎng)信息字符串 ? ? ?* @return 底部信息欄中最長(zhǎng)字符串 ? ? ?*/ ? ? private String getBottomMaxLegthString (){ ? ? ? ? int size = mData.size(); ? ? ? ? String maxString = "你好我好大家好才是真的好"; ? ? ? ? String tempString; ? ? ? ? for (int i=0; i<size; i++) { ? ? ? ? ? ? tempString = mData.get(i).get(NAME); ? ? ? ? ? ? if (maxString.length()>tempString.length()) { ? ? ? ? ? ? ? ? maxString = tempString; ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? return maxString; ? ? } ? ? /** ? ? ?* 獲取數(shù)據(jù)中的最大值 ? ? ?* @return 數(shù)據(jù)中的最大值 int float 類型 ? ? ?*/ ? ? private int getMaxValue (){ ? ? ? ? int maxValue = Float.valueOf(mData.get(0).get(VALUE)).intValue(); ? ? ? ? int tempValue; ? ? ? ? for (Map<String, String> map : mData) { ? ? ? ? ? ? tempValue = Float.valueOf(map.get(VALUE)).intValue(); ? ? ? ? ? ? if (maxValue<tempValue) { ? ? ? ? ? ? ? ? maxValue = tempValue + tempValue/10; ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? return maxValue; ? ? } ? ? /** ? ? ?* 獲取表格 X 方向的總長(zhǎng) ? ? ?* @return X 方向總長(zhǎng) int ? ? ?*/ ? ? private int getXTotalLength(){ ? ? ? ? int xTotalLength = 0; ? ? ? ? Paint paint = new Paint(); ? ? ? ? for (Map<String, String> map : mData) { ? ? ? ? ? ? xTotalLength += getTextWidth(paint, map.get(NAME), mBottomTextSize); ? ? ? ? ? ? xTotalLength = ?xTotalLength + mSpanBottomText; ? ? ? ? } ? ? ? ? return xTotalLength; ? ? } ? ? /** ? ? ?* 根據(jù)數(shù)據(jù)中的最大值將數(shù)據(jù)分成10等分,每等分為10的倍數(shù) ? ? ?* @param maxValue 數(shù)據(jù)中的最大值 ? ? ?* @return 左側(cè)等分欄的每一等分的數(shù)值 int 類型 ? ? ?*/ ? ? private int getPiceValue (int maxValue){ ? ? ? ? int piceValue = 1; ? ? ? ? while (maxValue>10) { ? ? ? ? ? ? maxValue = maxValue/10; ? ? ? ? ? ? piceValue = piceValue * 10; ? ? ? ? } ? ? ? ? if (maxValue<=5) { ? ? ? ? ? ? piceValue = piceValue / 2; ? ? ? ? } ? ? ? ? return piceValue; ? ? } ? ? /** ? ? ?* 根據(jù)手機(jī)的分辨率從 dp 的單位 轉(zhuǎn)成為 px(像素) ? ? ?* @param context 上下文 ? ? ?* @param dpValue 要轉(zhuǎn)換的 dp 值 ? ? ?* @return 轉(zhuǎn)換后的 px 值 ? ? ?*/ ? ? private int dpToPx(Context context, float dpValue) { ? ? ? ? final float scale = context.getResources().getDisplayMetrics().density; ? ? ? ? return (int) (dpValue * scale + 0.5f); ? ? } ? ? /** ? ? ?* 設(shè)置數(shù)據(jù) ? ? ?* @param data 表中的數(shù)據(jù) ? ? ?* ? ? ? ? ? ? data集合中的Map ? ? ?* ? ? ? ? ? ? "name"存放名稱,使用MyCharView中的常量 NAME ? ? ?* ? ? ? ? ? ? "value"存放數(shù)據(jù),數(shù)據(jù)為int類型的字符串,使用MyCharView中的常量 VALUE ? ? ?*/ ? ? public MyChatView setData (List<Map<String, String>> data){ ? ? ? ? try { ? ? ? ? ? ? this.mData = data==null? new ArrayList<Map<String, String>>():data; ? ? ? ? }catch (Exception e) { ? ? ? ? ? ? e.printStackTrace(); ? ? ? ? } ? ? ? ? return this; ? ? } ? ? /** ? ? ?* 設(shè)置繪制數(shù)據(jù)部分背景顏色 ? ? ?* @param dataBackgroundColor 16進(jìn)制 int 類型顏色 ? ? ?* @return 對(duì)象本身 ? ? ?*/ ? ? public MyChatView setDataBackgroundColor (int dataBackgroundColor){ ? ? ? ? try { ? ? ? ? ? ? this.mDataBackgroundColor = dataBackgroundColor; ? ? ? ? }catch (Exception e) { ? ? ? ? ? ? e.printStackTrace(); ? ? ? ? } ? ? ? ? return this; ? ? } ? ? /** ? ? ?* 設(shè)置左邊信息欄文字顏色 ? ? ?* @param leftTextColor 16進(jìn)制 int 類型顏色 ? ? ?* @return 對(duì)象本身 ? ? ?*/ ? ? public MyChatView setLeftTextColor (int leftTextColor){ ? ? ? ? try { ? ? ? ? ? ? this.mLeftTextColor = leftTextColor; ? ? ? ? }catch (Exception e) { ? ? ? ? ? ? e.printStackTrace(); ? ? ? ? } ? ? ? ? return this; ? ? } ? ? /** ? ? ?* 設(shè)置底部信息文字顏色 ? ? ?* @param bottomTextColor 16進(jìn)制 int 類型顏色 ? ? ?* @return 對(duì)象本身 ? ? ?*/ ? ? public MyChatView setBottomTextColor (int bottomTextColor){ ? ? ? ? try { ? ? ? ? ? ? this.mBottomTextColor = bottomTextColor; ? ? ? ? }catch (Exception e) { ? ? ? ? ? ? e.printStackTrace(); ? ? ? ? } ? ? ? ? return this; ? ? } ? ? /** ? ? ?* 設(shè)置柱狀條的背景顏色 ? ? ?* @param dataColor 16進(jìn)制 int 類型顏色 ? ? ?* @return 對(duì)象本身 ? ? ?*/ ? ? public MyChatView setDataColor (int dataColor){ ? ? ? ? try { ? ? ? ? ? ? this.mDataColor = dataColor; ? ? ? ? }catch (Exception e) { ? ? ? ? ? ? e.printStackTrace(); ? ? ? ? } ? ? ? ? return this; ? ? } ? ? /** ? ? ?* 設(shè)置柱狀條頂部文字顏色 ? ? ?* @param dataTopTextColor 16進(jìn)制 int 類型顏色 ? ? ?* @return 對(duì)象本身 ? ? ?*/ ? ? public MyChatView setmDataTopTextColor (int dataTopTextColor){ ? ? ? ? try { ? ? ? ? ? ? this.mDataTopTextColor = dataTopTextColor; ? ? ? ? }catch (Exception e) { ? ? ? ? ? ? e.printStackTrace(); ? ? ? ? } ? ? ? ? return this; ? ? } ? ? /** ? ? ?* 設(shè)置標(biāo)題顏色 ? ? ?* @param titleColor 顏色16進(jìn)制的 int 類型 ? ? ?* @return 對(duì)象本身 ? ? ?*/ ? ? public MyChatView setTitleColor (int titleColor){ ? ? ? ? try { ? ? ? ? ? ? this.mTitleColor = titleColor; ? ? ? ? }catch (Exception e){ ? ? ? ? ? ? e.printStackTrace(); ? ? ? ? } ? ? ? ? return this; ? ? } ? ? /** ? ? ?* 設(shè)置底部信息文字大小 ? ? ?* @param bottomTextSize int 類型 dp ? ? ?* @return 對(duì)象本身 ? ? ?*/ ? ? public MyChatView setBottomTextSize (int bottomTextSize){ ? ? ? ? try { ? ? ? ? ? ? this.mBottomTextSize = dpToPx(mContext, bottomTextSize); ? ? ? ? }catch (Exception e) { ? ? ? ? ? ? e.printStackTrace(); ? ? ? ? } ? ? ? ? return this; ? ? } ? ? /** ? ? ?* 設(shè)置左側(cè)信息文字大小 ? ? ?* @param leftTextSize int 類型 dp ? ? ?* @return 對(duì)象本身 ? ? ?*/ ? ? public MyChatView setLeftTextSize (int leftTextSize){ ? ? ? ? try { ? ? ? ? this.mLeftTextSize = dpToPx(mContext, leftTextSize); ? ? }catch (Exception e) { ? ? ? ? ? ? e.printStackTrace(); ? ? ? ? } ? ? ? ? return this; ? ? } ? ? /** ? ? ?* 設(shè)置柱狀條頂部文字大小 ? ? ?* @param dataTopTextSize int 類型 dp ? ? ?* @return 對(duì)象本身 ? ? ?*/ ? ? public MyChatView setDataTopTextSize (int dataTopTextSize){ ? ? ? ? try { ? ? ? ? ? ? this.mDataTopTextSize = dpToPx(mContext, dataTopTextSize); ? ? ? ? }catch (Exception e) { ? ? ? ? ? ? e.printStackTrace(); ? ? ? ? } ? ? ? ? return this; ? ? } ? ? /** ? ? ?* 設(shè)置底部表格標(biāo)題文字大小 ? ? ?* @param titleTextSize 標(biāo)題文字大小 ? ? ?* @return 對(duì)象本身 ? ? ?*/ ? ? public MyChatView setTitleTextSize (int titleTextSize){ ? ? ? ? try { ? ? ? ? ? ? this.mTitleTextSize = dpToPx(mContext,titleTextSize); ? ? ? ? } catch (Exception e) { ? ? ? ? ? ? e.printStackTrace(); ? ? ? ? } ? ? ? ? return this; ? ? } ? ? /** ? ? ?* 設(shè)置表格數(shù)據(jù)單位 ? ? ?* @param dataCompany 數(shù)據(jù)單位 ? ? ?* @return 對(duì)象本身 ? ? ?*/ ? ? public MyChatView setDataCompany (String dataCompany){ ? ? ? ? try { ? ? ? ? ? ? this.mDataCompany += dataCompany==null? "空":dataCompany; ? ? ? ? } catch (Exception e) { ? ? ? ? ? ? e.printStackTrace(); ? ? ? ? } ? ? ? ? return this; ? ? } ? ? /** ? ? ?* 設(shè)置表格標(biāo)題 ? ? ?* @param dataTitle 表格標(biāo)題 ? ? ?* @return 對(duì)象本身 ? ? ?*/ ? ? public MyChatView setDataTitle (String dataTitle){ ? ? ? ? try { ? ? ? ? ? ? mDataTitle = dataTitle; ? ? ? ? } catch (Exception e) { ? ? ? ? ? ? e.printStackTrace(); ? ? ? ? } ? ? ? ? return this; ? ? } ? ? /** ? ? ?* 設(shè)置底部信息欄文字的間隔 默認(rèn)為 10dp ? ? ?* @param spanBottomText 間隔距離 dp ? ? ?* @return 對(duì)象本身 ? ? ?*/ ? ? public MyChatView setSpanBottomText (int spanBottomText){ ? ? ? ? try { ? ? ? ? ? ? this.mSpanBottomText = dpToPx(mContext, spanBottomText); ? ? ? ? } catch (Exception e){ ? ? ? ? ? ? e.printStackTrace(); ? ? ? ? } ? ? ? ? return this; ? ? } ? ? //****************************** 繪制表格的類 ********************************** ? ? /** ? ? ?* 繪制控件界面的類 ? ? ?*/ ? ? private class InnerDraw{ ? ? ? ? private Canvas canvas; ? ? ? ? private ?Paint paint; ? ? ? ? /** 記錄繪制到的位置 */ ? ? ? ? private ?int bottomTextPainted; ? ? ? ? /** 底部標(biāo)題高度 */ ? ? ? ? private ?int bottomTitleHeight; ? ? ? ? /** 底部信息的高度 */ ? ? ? ? private ?int bottomMessageHeight; ? ? ? ? /** 左側(cè)信息欄最長(zhǎng)文字 */ ? ? ? ? private ?String leftValueMaxString; ? ? ? ? /** 表格中柱狀圖上文字高度 */ ? ? ? ? private ?int dataTopTextHeight; ? ? ? ? /** 左側(cè)信息欄寬度 */ ? ? ? ? private ?int leftValueWidth; ? ? ? ? /** 繪制數(shù)據(jù)部分的高度 */ ? ? ? ? private ?int chartDataHeight; ? ? ? ? /** 左側(cè)等分欄的每等分高度 */ ? ? ? ? private ?int piceValueHeight; ? ? ? ? /** 左側(cè)等分欄每等分的數(shù)值 */ ? ? ? ? private ?int piceValue; ? ? ? ? /** 柱狀的寬度 */ ? ? ? ? private ?int dataBarWidth; ? ? ? ? /** 底部信息 */ ? ? ? ? String bottomMessage; ? ? ? ? /** 底部信息的寬度 */ ? ? ? ? private int bottomMessageWidth; ? ? ? ? /** 數(shù)據(jù)信息 */ ? ? ? ? Map<String, String> data; ? ? ? ? /** 要繪制信息的位置 */ ? ? ? ? int index; ? ? ? ? public InnerDraw (Canvas canvas){ ? ? ? ? ? ? initData(canvas); ? ? ? ? } ? ? ? ? /** ? ? ? ? ?* 初始化數(shù)據(jù) ? ? ? ? ?*/ ? ? ? ? public void initData(Canvas canvas){ ? ? ? ? ? ? this.canvas = canvas; ? ? ? ? ? ? this.paint = new Paint(); ? ? ? ? ? ? this.bottomTitleHeight = mDataTitle==null? 0:(getTextHeight(paint, mTitleTextSize)+mSpanBottom/2); ? ? ? ? ? ? this.bottomTextPainted = 0; ? ? ? ? ? ? this.bottomMessageHeight = getTextHeight(paint, mBottomTextSize) + ?mSpanBottom + bottomTitleHeight; ? ? ? ? ? ? this.leftValueMaxString = getLeftValueMaxString(); ? ? ? ? ? ? this.dataTopTextHeight = getTextHeight(paint, mDataTopTextSize); ? ? ? ? ? ? this.leftValueWidth = getTextWidth(paint, leftValueMaxString , mLeftTextSize) + mSpanLeftText; ? ? ? ? ? ? this.chartDataHeight = mHeight - bottomMessageHeight - mSpanBottom; ? ? ? ? ? ? this.piceValueHeight = (chartDataHeight-dataTopTextHeight-getTextHeight(paint, mSpanDataTopText))/10; ? ? ? ? ? ? this.piceValue = getPiceValue(getMaxValue()); ? ? ? ? ? ? this.dataBarWidth = getTextWidth(paint, getBottomMaxLegthString(), mBottomTextSize); ? ? ? ? ? ? this.bottomMessage = ""; ? ? ? ? ? ? this.bottomMessageWidth = 0; ? ? ? ? ? ? this.data = new HashMap<>(); ? ? ? ? ? ? this.index = 0; ? ? ? ? } ? ? ? ? /** ? ? ? ? ?* 繪制左側(cè)等分欄 ? ? ? ? ?*/ ? ? ? ? public void drawLeftMenue(){ ? ? ? ? ? ? paint.setColor(mLeftTextColor); ? ? ? ? ? ? paint.setTextSize(mLeftTextSize); ? ? ? ? ? ? int textLeft; ? ? ? ? ? ? int textTop; ? ? ? ? ? ? String valueStr; ? ? ? ? ? ? int strLength; ? ? ? ? ? ? String maxValueStr = String.valueOf(piceValue * 10); ? ? ? ? ? ? int textMaxLength = maxValueStr.length(); ? ? ? ? ? ? int topTextHeight = getTextHeight(paint, mDataTopTextSize); ? ? ? ? ? ? int leftTextHeight = getTextHeight(paint, mLeftTextSize); ? ? ? ? ? ? for (int i=0; i<=10; i++) { ? ? ? ? ? ? ? ? textLeft = 0; ? ? ? ? ? ? ? ? valueStr = String.valueOf(i * piceValue); ? ? ? ? ? ? ? ? strLength = valueStr.length(); ? ? ? ? ? ? ? ? if (strLength<textMaxLength) { ? ? ? ? ? ? ? ? ? ? textLeft = getTextWidth(paint, maxValueStr.substring(strLength), mLeftTextSize); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? textTop = (10-i)*piceValueHeight + topTextHeight + mSpanDataTopText + leftTextHeight/2; ? ? ? ? ? ? ? ? canvas.drawText(valueStr+"", textLeft, textTop, paint); ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? /** ? ? ? ? ?* 繪制表格中數(shù)據(jù)部分背景 ? ? ? ? ?*/ ? ? ? ? public void drawDataBackground() { ? ? ? ? ? ? paint.setColor(mDataBackgroundColor); ? ? ? ? ? ? Rect rect = new Rect(leftValueWidth, 0, mWidget, chartDataHeight); ? ? ? ? ? ? canvas.drawRect(rect, paint); ? ? ? ? } ? ? ? ? /** ? ? ? ? ?* 繪制底部標(biāo)題 ? ? ? ? ?*/ ? ? ? ? public void drawDataTitle() { ? ? ? ? ? ? if (mDataTitle != null) { ? ? ? ? ? ? ? ? paint.setColor(mTitleColor); ? ? ? ? ? ? ? ? paint.setTextSize(mTitleTextSize); ? ? ? ? ? ? ? ? int titleWidget = getTextWidth(paint, mDataTitle, mTitleTextSize); ? ? ? ? ? ? ? ? float titleLeft = (mWidget - titleWidget) / 2; ? ? ? ? ? ? ? ? float titleTop = mHeight - mSpanBottom; ? ? ? ? ? ? ? ? canvas.drawText(mDataTitle, titleLeft, titleTop, paint); ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? /** ? ? ? ? ?* 繪制數(shù)據(jù)單位 ? ? ? ? ?*/ ? ? ? ? public void drawCompany() { ? ? ? ? ? ? paint.setTextSize(mLeftTextSize); ? ? ? ? ? ? paint.setColor(mLeftTextColor); ? ? ? ? ? ? int comPanyLeft = mWidget - getTextWidth(paint, mDataCompany + "111", mLeftTextSize); ? ? ? ? ? ? int companyBottom = dataTopTextHeight + getTextHeight(paint, mLeftTextSize); ? ? ? ? ? ? canvas.drawText(mDataCompany, comPanyLeft, companyBottom, paint); ? ? ? ? } ? ? ? ? /** ? ? ? ? ?* 開始繪制,設(shè)置數(shù)據(jù),同事設(shè)置底部信息寬度 ? ? ? ? ?* @param data ?數(shù)據(jù)信息 ? ? ? ? ?* @param index ?繪制到的位置 ? ? ? ? ?* @return 狀態(tài)碼: -1 為結(jié)束循環(huán),0 為繼續(xù)下一個(gè)循環(huán),1 為正常繪制 ? ? ? ? ?*/ ? ? ? ? public int startDrawBody(Map<String, String> data, int index){ ? ? ? ? ? ? this.data = data; ? ? ? ? ? ? this.bottomMessage = data.get(NAME).trim(); ? ? ? ? ? ? this.bottomMessageWidth = getTextWidth(paint, bottomMessage, mBottomTextSize); ? ? ? ? ? ? this.index = index; ? ? ? ? ? ? int bottomMsgBegainDrawX = (index + 1) * mSpanBottomText + mChartMovedSize + leftValueWidth + bottomTextPainted; ? ? ? ? ? ? if ((bottomMsgBegainDrawX+bottomMessageWidth)<leftValueWidth) {//需要繪制的區(qū)域在繪制區(qū)域的左側(cè) ? ? ? ? ? ? ? ? bottomTextPainted += bottomMessageWidth; ? ? ? ? ? ? ? ? return 0; ? ? ? ? ? ? } ? ? ? ? ? ? if (bottomMsgBegainDrawX>mWidget) {//需要繪制的區(qū)域超出了控件的右邊,結(jié)束繪制 ? ? ? ? ? ? ? ? return -1; ? ? ? ? ? ? } ? ? ? ? ? ? return 1; ? ? ? ? } ? ? ? ? /** ? ? ? ? ?* 結(jié)束繪制 ? ? ? ? ?*/ ? ? ? ? public void endDrawBody(){ ? ? ? ? ? ? bottomTextPainted += bottomMessageWidth; ? ? ? ? } ? ? ? ? /** ? ? ? ? ?* 繪制底部信息欄 ? ? ? ? ?*/ ? ? ? ? public void drawBottomMessage() { ? ? ? ? ? ? paint.setColor(mBottomTextColor); ? ? ? ? ? ? paint.setTextSize(mBottomTextSize); ? ? ? ? ? ? int bottomLeft = (index + 1) * mSpanBottomText + mChartMovedSize + leftValueWidth + bottomTextPainted; ? ? ? ? ? ? int bottomTop = chartDataHeight + bottomMessageHeight - bottomTitleHeight - dpToPx(mContext, 2); ? ? ? ? ? ? if (bottomLeft >= leftValueWidth && bottomLeft < mWidget) { ? ? ? ? ? ? ? ? canvas.drawText(bottomMessage, bottomLeft, bottomTop, paint); ? ? ? ? ? ? } else if ((bottomLeft+bottomMessageWidth)>leftValueWidth) { ? ? ? ? ? ? ? ? int index = (leftValueWidth-bottomLeft)*bottomMessage.length()/bottomMessageWidth+1; ? ? ? ? ? ? ? ? if (index>=0 && index <bottomMessage.length()) { ? ? ? ? ? ? ? ? ? ? canvas.drawText(bottomMessage.substring(index), leftValueWidth, bottomTop, paint); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? /** ? ? ? ? ?* 繪制條形數(shù)據(jù) ? ? ? ? ?*/ ? ? ? ? public void drawDataBar() { ? ? ? ? ? ? paint.setColor(mDataColor); ? ? ? ? ? ? int dataValue = Float.valueOf(data.get(VALUE)).intValue(); ? ? ? ? ? ? int bottomLeft = (index + 1) * mSpanBottomText + mChartMovedSize + leftValueWidth + bottomTextPainted; ? ? ? ? ? ? int dataLeft = bottomLeft + bottomMessageWidth / 2 - dataBarWidth / 4; ? ? ? ? ? ? int dataBottom = chartDataHeight; ? ? ? ? ? ? int dataTop = chartDataHeight - (dataValue * (chartDataHeight - dataTopTextHeight - mSpanDataTopText) / piceValue) / 10; ? ? ? ? ? ? int dataRight = dataLeft + dataBarWidth / 2; ? ? ? ? ? ? if (dataLeft < leftValueWidth && dataRight > leftValueWidth) { ? ? ? ? ? ? ? ? dataLeft = leftValueWidth; ? ? ? ? ? ? } ? ? ? ? ? ? Rect dataRect = new Rect(dataLeft, dataTop, dataRight, dataBottom); ? ? ? ? ? ? if (dataRight>leftValueWidth) { ? ? ? ? ? ? ? ? canvas.drawRect(dataRect, paint); ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? /** ? ? ? ? ?* 繪制條形數(shù)據(jù)頂部文字 ? ? ? ? ?*/ ? ? ? ? public void drawDataTopText() { ? ? ? ? ? ? String topTextMessage = data.get(VALUE); ? ? ? ? ? ? int topTextWidth = getTextWidth(paint, topTextMessage, mDataTopTextSize); ? ? ? ? ? ? paint.setColor(mDataTopTextColor); ? ? ? ? ? ? paint.setTextSize(mDataTopTextSize); ? ? ? ? ? ? int bottomLeft = (index + 1) * mSpanBottomText + mChartMovedSize + leftValueWidth + bottomTextPainted; ? ? ? ? ? ? int topTextLeft = bottomLeft + (bottomMessageWidth - topTextWidth) / 2; ? ? ? ? ? ? int dataValue = Float.valueOf(data.get(VALUE)).intValue(); ? ? ? ? ? ? int dataTop = chartDataHeight - (dataValue*(chartDataHeight-dataTopTextHeight - mSpanDataTopText)/piceValue)/10; ? ? ? ? ? ? int topTextTop = dataTop - mSpanDataTopText * 2 / 3; ? ? ? ? ? ? if (topTextLeft >= leftValueWidth && bottomLeft < mWidget) { ? ? ? ? ? ? ? ? canvas.drawText(topTextMessage, topTextLeft, topTextTop, paint); ? ? ? ? ? ? } else if ((topTextLeft+topTextWidth)>leftValueWidth) { ? ? ? ? ? ? ? ? int index = (leftValueWidth-topTextLeft)*topTextMessage.length()/topTextWidth+1; ? ? ? ? ? ? ? ? if (index>=0 && index <topTextMessage.length()) { ? ? ? ? ? ? ? ? ? ? canvas.drawText(topTextMessage.substring(index), leftValueWidth, topTextTop, paint); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } ? ? ? ? } ? ? } }
實(shí)現(xiàn)效果如下圖
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android開發(fā)之使用ExifInterface獲取拍照后的圖片屬性
這篇文章主要介紹了Android開發(fā)之使用ExifInterface獲取拍照后的圖片屬性,較為詳細(xì)的分析了ExifInterface類操作圖片的具體使用技巧,需要的朋友可以參考下2016-01-01Android 給應(yīng)用程序的icon添加未讀消息個(gè)數(shù)提示(紅圈內(nèi)數(shù)字)
本文主要介紹了Android 給應(yīng)用程序的icon添加未讀消息個(gè)數(shù)提示(紅圈內(nèi)數(shù)字)的方法。具有很好的參考價(jià)值。下面跟著小編一起來(lái)看下吧2017-04-04Android編程實(shí)現(xiàn)讀取本地SD卡圖片的方法
這篇文章主要介紹了Android編程實(shí)現(xiàn)讀取本地SD卡圖片的方法,涉及Android針對(duì)文件讀取及判定操作的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-11-11Android使用自定義控件HorizontalScrollView打造史上最簡(jiǎn)單的側(cè)滑菜單
側(cè)滑菜單一般都會(huì)自定義ViewGroup,然后隱藏菜單欄,當(dāng)手指滑動(dòng)時(shí),通過(guò)Scroller或者不斷的改變leftMargin等實(shí)現(xiàn);多少都有點(diǎn)復(fù)雜,完成以后還需要對(duì)滑動(dòng)沖突等進(jìn)行處理,今天給大家?guī)?lái)一個(gè)簡(jiǎn)單的實(shí)現(xiàn),史上最簡(jiǎn)單有點(diǎn)夸張,但是的確是我目前遇到過(guò)的最簡(jiǎn)單的一種實(shí)現(xiàn)2016-02-02Android fragment 轉(zhuǎn)場(chǎng)動(dòng)畫創(chuàng)建步驟
在 Android 中,可以使用 setCustomAnimations() 方法來(lái)繪制自定義的 Fragment 轉(zhuǎn)場(chǎng)動(dòng)畫,本文分步驟給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧2024-03-03Android使用fragment實(shí)現(xiàn)左側(cè)導(dǎo)航
這篇文章主要為大家詳細(xì)介紹了Android使用fragment實(shí)現(xiàn)左側(cè)導(dǎo)航,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-02-02Andoroid實(shí)現(xiàn)底部圖片選擇Dialog效果
這篇文章主要介紹了Andoroid實(shí)現(xiàn)底部圖片選擇Dialog效果,需要的朋友可以參考下2017-10-10