返回顶部
首页 > 资讯 > 移动开发 >Android表格自定义控件使用详解
  • 318
分享到

Android表格自定义控件使用详解

2024-04-02 19:04:59 318人浏览 独家记忆
摘要

近期公司要做报表功能,在网上搜索下表格的样式后便自己写了一个自定义的表格控件,该表格控件能根据设置的数据中数据的最大值自动设置左侧信息栏显示的值,使得条形图能尽量的充满控件,条形图部

近期公司要做报表功能,在网上搜索下表格的样式后便自己写了一个自定义的表格控件,该表格控件能根据设置的数据中数据的最大值自动设置左侧信息栏显示的值,使得条形图能尽量的充满控件,条形图部分支持左右滑动,数据的长度可能超过控件本身所能容纳的长度,所以在绘制的时候做了判断,当需要绘制的部分不再控件范围内则不进行绘制,具体请阅读代码,目前只支持一个名称对应一条数据,如有不足之处,大家提出帮忙修改

使用方法如下:

在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中设置控件要显示的数据、设置显示的样式

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("测试")
                .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);
    }

    
    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 {

    
    public static final String NAME = "name";
    
    public static final String VALUE = "value";

    
    private Context mContext;
    
    private int mHeight;
    
    private int mWidget;
    
    private List<Map<String, String>> mData;
    
    private String mDataCompany = "单位: ";
    
    private String mDataTitle = null;
    
    private int mBottomTextSize;
    
    private int mLeftTextSize;
    
    private int mDataTopTextSize;
    
    private int mTitleTextSize;
    
    private int mSpanLeftText;
    
    int mSpanDataTopText;
    
    int mSpanBottomText;
    
    int mSpanBottom;
    
    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;
    
    private int mTitleColor = Color.BLACK;
    
    private int mChartMovedSize = 0;
    
    private int mDownX = 0;
    
    private int mUpX = 0;
    
    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;
    }

    
    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++) {
            //设置数据,必须在第一行
            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();
        }
    }

    
    private int getTextHeight (Paint paint, int textSize){
        String text = "测试";
        Rect rect = new Rect();
        paint.setTextSize(textSize);
        paint.getTextBounds(text, 0, text.length(), rect);
        return rect.height();
    }

    
    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();
    }

    
    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;
    }

    
    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;
    }

    
    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;
    }

    
    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;
    }

    
    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;
    }

    
    private int dpToPx(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }

    
    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;
    }

    
    public MyChatView setDataBackgroundColor (int dataBackgroundColor){
        try {
            this.mDataBackgroundColor = dataBackgroundColor;
        }catch (Exception e) {
            e.printStackTrace();
        }
        return this;
    }

    
    public MyChatView setLeftTextColor (int leftTextColor){
        try {
            this.mLeftTextColor = leftTextColor;
        }catch (Exception e) {
            e.printStackTrace();
        }
        return this;
    }

    
    public MyChatView setBottomTextColor (int bottomTextColor){
        try {
            this.mBottomTextColor = bottomTextColor;
        }catch (Exception e) {
            e.printStackTrace();
        }
        return this;
    }

    
    public MyChatView setDataColor (int dataColor){
        try {
            this.mDataColor = dataColor;
        }catch (Exception e) {
            e.printStackTrace();
        }
        return this;
    }

    
    public MyChatView setmDataTopTextColor (int dataTopTextColor){
        try {
            this.mDataTopTextColor = dataTopTextColor;
        }catch (Exception e) {
            e.printStackTrace();
        }
        return this;
    }

    
    public MyChatView setTitleColor (int titleColor){
        try {
            this.mTitleColor = titleColor;
        }catch (Exception e){
            e.printStackTrace();
        }
        return this;
    }

    
    public MyChatView setBottomTextSize (int bottomTextSize){
        try {
            this.mBottomTextSize = dpToPx(mContext, bottomTextSize);
        }catch (Exception e) {
            e.printStackTrace();
        }
        return this;
    }

    
    public MyChatView setLeftTextSize (int leftTextSize){
        try {
        this.mLeftTextSize = dpToPx(mContext, leftTextSize);
    }catch (Exception e) {
            e.printStackTrace();
        }
        return this;
    }

    
    public MyChatView setDataTopTextSize (int dataTopTextSize){
        try {
            this.mDataTopTextSize = dpToPx(mContext, dataTopTextSize);
        }catch (Exception e) {
            e.printStackTrace();
        }
        return this;
    }

    
    public MyChatView setTitleTextSize (int titleTextSize){
        try {
            this.mTitleTextSize = dpToPx(mContext,titleTextSize);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return this;
    }

    
    public MyChatView setDataCompany (String dataCompany){
        try {
            this.mDataCompany += dataCompany==null? "空":dataCompany;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return this;
    }

    
    public MyChatView setDataTitle (String dataTitle){
        try {
            mDataTitle = dataTitle;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return this;
    }

    
    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;
        
        private  int bottomTitleHeight;
        
        private  int bottomMessageHeight;
        
        private  String leftValueMaxString;
        
        private  int dataTopTextHeight;
        
        private  int leftValueWidth;
        
        private  int chartDataHeight;
        
        private  int piceValueHeight;
        
        private  int piceValue;
        
        private  int dataBarWidth;
        
        String bottomMessage;
        
        private int bottomMessageWidth;
        
        Map<String, String> data;
        
        int index;

        public InnerDraw (Canvas canvas){
            initData(canvas);
        }

        
        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;
        }

        
        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);
            }
        }

        
        public void drawDataBackground() {
            paint.setColor(mDataBackgroundColor);
            Rect rect = new Rect(leftValueWidth, 0, mWidget, chartDataHeight);
            canvas.drawRect(rect, paint);
        }

        
        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);
            }
        }

        
        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);
        }

        
        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) {//需要绘制的区域在绘制区域的左侧
                bottomTextPainted += bottomMessageWidth;
                return 0;
            }
            if (bottomMsgBegainDrawX>mWidget) {//需要绘制的区域超出了控件的右边,结束绘制
                return -1;
            }
            return 1;
        }

        
        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);
                }
            }
        }

        
        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);
            }
        }

        
        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);
                }
            }
        }

    }
}

实现效果如下图

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程网。

--结束END--

本文标题: Android表格自定义控件使用详解

本文链接: https://lsjlt.com/news/143298.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作