欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android自定義view繪制表格的方法

 更新時間:2022年05月19日 10:02:36   作者:碼仔時光  
這篇文章主要為大家詳細(xì)介紹了Android自定義view繪制表格的方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下

本文實例為大家分享了Android自定義view繪制表格的具體代碼,供大家參考,具體內(nèi)容如下

先上效果圖

平時很少有這樣的表格需求,不過第一想法就是自定義view繪制表格,事實上我確實是用的canvas來繪制的,整個過程看似復(fù)雜,實為簡單,計算好各個點的坐標(biāo)后事情就完成一半了。不廢話show code

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.text.Layout;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;

import androidx.annotation.Nullable;

import com.robot.common.entity.ScenicDetailInfo;
import com.robot.common.utils.PixelUtil;

/**
?* 景區(qū)詳情門票信息表格
?*
?* @author ly
?* date 2019/8/12 10:24
?*/
public class TicketInfoView extends View {

? ? private Paint pLine, pText;
? ? //表格寬高
? ? private int w, h;
? ? //每一行的高度
? ? private int rowH;
? ? //表格線的寬度
? ? private float tableLineW;
? ? //豎線x坐標(biāo)
? ? private float vLine1x, vLine2x, vLine3x, vLine4x;
? ? //橫線y坐標(biāo)
? ? private float hLine1y, hLine2y;
? ? //每一列文字的x坐標(biāo)(單列內(nèi)居中)
? ? private float textX1, textX2, textX3, textX4, textX5, textXEnd;
? ? private static final String text1 = "市場價";
? ? private static final String text2 = "單人出行";
? ? private static final String text3 = "多人出行";
? ? private static final String text4 = "持卡者";
? ? private static final String text5 = "同行者";
? ? private static final String text6 = "出行總?cè)藬?shù)";
? ? private ScenicDetailInfo.TicketInfo ticketInfo;

? ? private int tableLineColor = Color.parseColor("#FFB6B4C8");
? ? private int textColorBlack = Color.parseColor("#FF232627");
? ? private int textColorGray = Color.parseColor("#FF65657e");
? ? private int textColorRed = Color.parseColor("#FFfa496a");
? ? private int blackTextSize = PixelUtil.sp2px(14);
? ? private int grayTextSize = PixelUtil.sp2px(12);
? ? private int redTextSize = PixelUtil.sp2px(13);

? ? //表格上半部分顏色
? ? private int tableBgColorTop = Color.parseColor("#FFF6F5FF");
? ? //表格下半部分顏色
? ? private int tableBgColorBottom = Color.parseColor("#FFE9EAFF");
? ? //表格高亮部分顏色
? ? private int tableBgColorHighLight = Color.parseColor("#FF6066DD");

? ? //三個有顏色的矩形區(qū)域
? ? private RectF topRect, bottomRect, highLightRect;
? ? private static final int radius = PixelUtil.dp2px(10);
? ? //圓角矩形的Path
? ? private Path pathRoundRect;
? ? //頂部矩形的四個圓角
? ? private static final float[] radiusTop = {radius, radius, radius, radius, 0f, 0f, 0f, 0f};
? ? //底部矩形的四個圓角
? ? private static final float[] radiusBottom = {0, 0, 0, 0, radius, radius, radius, radius};
? ? private static final float[] radiusAll = {radius, radius, radius, radius, radius, radius, radius, radius};

? ? //門票信息文字的高度
? ? private int ticketInfoTextH;
? ? //門票信息內(nèi)間距
? ? private final int ticketInfoTextPadding = PixelUtil.dp2px(5);
? ? private StaticLayout ticketTextStaticLayout;
? ? private TextPaint ticketTextPaint;
? ? private int ticketTextH;

? ? public TicketInfoView(Context context) {
? ? ? ? this(context, null);
? ? }

? ? public TicketInfoView(Context context, @Nullable AttributeSet attrs) {
? ? ? ? this(context, attrs, 0);
? ? }

? ? public TicketInfoView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
? ? ? ? super(context, attrs, defStyleAttr);

? ? ? ? tableLineW = PixelUtil.dp2px(1.0f);

? ? ? ? pLine = new Paint();
? ? ? ? pLine.setAntiAlias(true);
? ? ? ? pLine.setStrokeWidth(tableLineW);

? ? ? ? pText = new Paint();
? ? ? ? pText.setAntiAlias(true);
? ? ? ? pText.setTextAlign(Paint.Align.CENTER);

? ? ? ? pathRoundRect = new Path();

? ? ? ? topRect = new RectF();
? ? ? ? bottomRect = new RectF();
? ? ? ? highLightRect = new RectF();
? ? }

? ? @Override
? ? protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
? ? ? ? super.onMeasure(widthMeasureSpec, heightMeasureSpec);
? ? ? ? w = MeasureSpec.getSize(widthMeasureSpec);
? ? ? ? rowH = (int) (w * 0.134f);

? ? ? ? computeH();
? ? ? ? setMeasuredDimension(w, h);
? ? }

? ? @Override
? ? protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
? ? ? ? super.onLayout(changed, left, top, right, bottom);
? ? ? ? vLine1x = 1 / 5f * w;
? ? ? ? vLine2x = 2 / 5f * w;
? ? ? ? vLine3x = 3 / 5f * w;
? ? ? ? vLine4x = 4 / 5f * w;
? ? ? ? hLine1y = rowH;
? ? ? ? hLine2y = rowH * 2;

? ? ? ? textX1 = vLine1x / 2;
? ? ? ? textX2 = vLine1x + (vLine2x - vLine1x) / 2;
? ? ? ? textX3 = vLine2x + (vLine3x - vLine2x) / 2;
? ? ? ? textX4 = vLine3x + (vLine4x - vLine3x) / 2;
? ? ? ? textX5 = vLine4x + (w - vLine4x) / 2;
? ? ? ? textXEnd = w / 2f;

? ? ? ? topRect.right = w;
? ? ? ? topRect.bottom = rowH * 3;

? ? ? ? bottomRect.top = topRect.bottom;
? ? ? ? bottomRect.right = w;
? ? ? ? bottomRect.bottom = topRect.bottom + ticketTextH;

? ? ? ? highLightRect.left = vLine2x;
? ? ? ? highLightRect.top = hLine1y;
? ? ? ? highLightRect.right = vLine3x;
? ? ? ? highLightRect.bottom = topRect.bottom;
? ? }

? ? @Override
? ? protected void onDraw(Canvas canvas) {
? ? ? ? super.onDraw(canvas);

? ? ? ? pathRoundRect.reset();
? ? ? ? pLine.setStyle(Paint.Style.FILL);
? ? ? ? pLine.setColor(tableBgColorTop);
? ? ? ? if (hasTicketInfo()) {
? ? ? ? ? ? //畫頂部矩形
? ? ? ? ? ? pathRoundRect.addRoundRect(topRect, radiusTop, Path.Direction.CW);
? ? ? ? ? ? canvas.drawPath(pathRoundRect, pLine);

? ? ? ? ? ? //畫底部矩形
? ? ? ? ? ? pathRoundRect.reset();
? ? ? ? ? ? pathRoundRect.addRoundRect(bottomRect, radiusBottom, Path.Direction.CW);
? ? ? ? ? ? pLine.setColor(tableBgColorBottom);
? ? ? ? } else {//無門票說明則只畫上部分表格
? ? ? ? ? ? pathRoundRect.addRoundRect(topRect, radiusAll, Path.Direction.CW);
? ? ? ? }
? ? ? ? canvas.drawPath(pathRoundRect, pLine);

? ? ? ? //畫高亮部分矩形
? ? ? ? pLine.setColor(tableBgColorHighLight);
? ? ? ? canvas.drawRect(highLightRect, pLine);

? ? ? ? //四根豎線
? ? ? ? pLine.setColor(tableLineColor);
? ? ? ? pLine.setStrokeWidth(tableLineW / 2);
? ? ? ? canvas.drawLine(vLine1x, 0, vLine1x, topRect.bottom, pLine);
? ? ? ? canvas.drawLine(vLine2x, 0, vLine2x, topRect.bottom, pLine);
? ? ? ? canvas.drawLine(vLine3x, hLine1y, vLine3x, topRect.bottom, pLine);
? ? ? ? canvas.drawLine(vLine4x, hLine1y, vLine4x, topRect.bottom, pLine);
? ? ? ? //兩根橫線
? ? ? ? canvas.drawLine(vLine1x, hLine1y, w, hLine1y, pLine);
? ? ? ? canvas.drawLine(0, hLine2y, w, hLine2y, pLine);

? ? ? ? pText.setColor(textColorBlack);
? ? ? ? pText.setTextSize(blackTextSize);
? ? ? ? pText.setTypeface(getTypeface());
? ? ? ? //計算baseline
? ? ? ? float baseline = hLine2y / 2 + getTextDis();

? ? ? ? //市場價 黑色大字
? ? ? ? canvas.drawText(text1, textX1, baseline, pText);
? ? ? ? //第一行黑色大字
? ? ? ? baseline = hLine1y / 2 + getTextDis();
? ? ? ? canvas.drawText(text2, textX2, baseline, pText);
? ? ? ? canvas.drawText(text3, vLine2x + (w - vLine2x) / 2, baseline, pText);

? ? ? ? //第二行小字
? ? ? ? baseline = hLine1y + (hLine2y - hLine1y) / 2 + getTextDis();
? ? ? ? pText.setTextSize(grayTextSize);
? ? ? ? canvas.drawText(text4, textX2, baseline, pText);
? ? ? ? canvas.drawText(text5, textX4, baseline, pText);
? ? ? ? canvas.drawText(text6, textX5, baseline, pText);
? ? ? ? pText.setColor(Color.WHITE);
? ? ? ? canvas.drawText(text4, textX3, baseline, pText);

? ? ? ? //第三行 畫價格、隨行人數(shù)
? ? ? ? if (ticketInfo != null) {
? ? ? ? ? ? pText.setTextSize(redTextSize);
? ? ? ? ? ? pText.setColor(textColorBlack);

? ? ? ? ? ? baseline = hLine2y + (topRect.bottom - hLine2y) / 2 + getTextDis();

? ? ? ? ? ? //市場價
? ? ? ? ? ? canvas.drawText(limitTextLength(ticketInfo.price), textX1, baseline, pText);
? ? ? ? ? ? //出行總?cè)藬?shù)
? ? ? ? ? ? canvas.drawText(limitTextLength(ticketInfo.discounts_num), textX5, baseline, pText);

? ? ? ? ? ? //持卡者、同行者價格
? ? ? ? ? ? pText.setColor(Color.WHITE);
? ? ? ? ? ? canvas.drawText(limitTextLength(ticketInfo.discounts_member), textX3, baseline, pText);
? ? ? ? ? ? pText.setColor(textColorRed);
? ? ? ? ? ? canvas.drawText(limitTextLength(ticketInfo.single), textX2, baseline, pText);
? ? ? ? ? ? canvas.drawText(limitTextLength(ticketInfo.discounts), textX4, baseline, pText);

? ? ? ? ? ? //底部門票說明
? ? ? ? ? ? if (hasTicketInfo() && ticketTextStaticLayout != null) {
? ? ? ? ? ? ? ? canvas.save();
? ? ? ? ? ? ? ? //設(shè)定文字開始繪制的坐標(biāo),該坐標(biāo)對應(yīng)文字的left,top
? ? ? ? ? ? ? ? canvas.translate(ticketInfoTextPadding, topRect.bottom + ticketInfoTextPadding + (bottomRect.bottom - bottomRect.top - ticketInfoTextH - 2 * ticketInfoTextPadding) / 2);
? ? ? ? ? ? ? ? ticketTextStaticLayout.draw(canvas);
? ? ? ? ? ? ? ? canvas.restore();
? ? ? ? ? ? }
? ? ? ? }
? ? }

? ? private void computeH() {
? ? ? ? if (hasTicketInfo() && w > 2 * ticketInfoTextPadding) {
? ? ? ? ? ? if (ticketTextPaint == null) {
? ? ? ? ? ? ? ? ticketTextPaint = new TextPaint();
? ? ? ? ? ? ? ? ticketTextPaint.setColor(textColorGray);
? ? ? ? ? ? ? ? ticketTextPaint.setTextSize(redTextSize);
? ? ? ? ? ? ? ? ticketTextPaint.setAntiAlias(true);
? ? ? ? ? ? }
? ? ? ? ? ? //此處每次都創(chuàng)建新對象來獲取ticket_info最新值
? ? ? ? ? ? ticketTextStaticLayout = new StaticLayout(ticketInfo.ticket_info, ticketTextPaint, w - 2 * ticketInfoTextPadding, Layout.Alignment.ALIGN_CENTER, 1.1F, 1.1F, true);
? ? ? ? ? ? ticketInfoTextH = ticketTextStaticLayout.getHeight();

? ? ? ? ? ? h = (int) (0.4 * w) + ticketTextH;
? ? ? ? } else {
? ? ? ? ? ? h = (int) (0.4 * w);
? ? ? ? }

? ? ? ? ticketTextH = Math.max((ticketInfoTextH + ticketInfoTextPadding * 2), rowH);
? ? ? ? h = hasTicketInfo() ? (int) (0.4 * w) + ticketTextH : (int) (0.4 * w);
? ? }

? ? private Typeface getTypeface() {
? ? ? ? Typeface roboto = Typeface.create("sans-serif-medium", Typeface.NORMAL);
? ? ? ? if (roboto == null || roboto.getStyle() == Typeface.NORMAL)
? ? ? ? ? ? roboto = Typeface.DEFAULT_BOLD;

? ? ? ? return roboto;
? ? }

? ? /**
? ? ?* 設(shè)置pText的字體大小等屬性時,更新文字居中距離
? ? ?*
? ? ?* @return 文字居中的y坐標(biāo)
? ? ?*/
? ? private float getTextDis() {
? ? ? ? Paint.FontMetrics fontMetrics = pText.getFontMetrics();
? ? ? ? return (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom;
? ? }

? ? /**
? ? * ticketInfo為后臺返回的數(shù)據(jù)模型,此處不再貼出
? ? */
? ? public void setTicketInfo(ScenicDetailInfo.TicketInfo ticketInfo) {
? ? ? ? this.ticketInfo = ticketInfo;
? ? ? ? if (ticketInfo != null) {
? ? ? ? ? ? computeH();
? ? ? ? ? ? //重新layout,確定view的繪制區(qū)域
? ? ? ? ? ? requestLayout();
? ? ? ? } else {
? ? ? ? ? ? invalidate();
? ? ? ? }
? ? }

? ? private String limitTextLength(String src) {
? ? ? ? if (!TextUtils.isEmpty(src) && src.length() > 5)
? ? ? ? ? ? src = src.substring(0, 5) + "...";
? ? ? ? return src;
? ? }

? ? private boolean hasTicketInfo() {
? ? ? ? return ticketInfo != null && !TextUtils.isEmpty(ticketInfo.ticket_info);
? ? }
}

可以看到無非就是定義一些顏色啊、坐標(biāo)啊這些,在onLayout的時候計算出對應(yīng)的值,然后draw即可,主要是思路要清晰,我這里是從上而下,從左到右的思路繪制。

這個view也有個弊端,就是大小及樣式固定,里面的文字均為單行展示沒處理自動換行,不過滿足需求就好了啊,不要那么折騰,不然頭發(fā)又要變少了。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評論