【Android自定义View】- 表格控件

作者: 拔萝卜占坑 | 来源:发表于2018-12-09 20:24 被阅读18次

    简介

    记得第一次写文章是自己刚开始自学Android的时候,当时不知道怎么地,从一个学习硬件,控制转向学习java,毕业找了一份机顶盒上的Android应用开发,两年多跳了两家公司,每次简历都不知道写些啥,时隔两年多,重新开始写文章,只希望逼迫自己不断学习,分享也是快乐。

    效果

    屏幕快照 2018-12-10 上午10.01.11.png jjj.gif

    功能

    1. 绘制类似excel第一个单元格分类样式
    2. 设定水平和垂直标题
    3. 通过编码控制单元格显示图片
    4. 单元格点击事件和自动更新编码数据 
        5. 常规的表格数据展示
    

    实现

    • 绘制表格水平分割线(垂直同理)
      /**
      * 从右至左,分别表示有无left,top,right,bottom边框线(0 - 无,1 - 有)
      */
      private int mFrameLine = 0x0101;

        private void drawHorizontalFrameLine(Canvas canvas){
        //记录水平横线路径
        if ((0x0010 & mFrameLine) != 0 ){
          mHorizontalFrameLinePath.moveTo(0,0);
          mHorizontalFrameLinePath.lineTo(width,0);
        }
        if ((mContentLine & 0x01) != 0){
          for(int i = 1 ; i < mVerticalGap; i++){
            int y = cellHeight * i;
            mHorizontalFrameLinePath.moveTo(0,y);
            mHorizontalFrameLinePath.lineTo(width,y);
          }
        }
        if ((0x1000 & mFrameLine) != 0 ){
          mHorizontalFrameLinePath.moveTo(0,height);
          mHorizontalFrameLinePath.lineTo(width,height);
        }
        canvas.drawPath(mHorizontalFrameLinePath,mFrameLinePaint);
        }
      

      创建水平和垂直Path路径变量,记录分割线路径,通过变量mFrameLine来控制表格四条边框的绘制路径。

    • 绘制表格第一个分类单元格
      如果设置了分类数据,第一个单元格绘制分类标题,如果没有者是空白

          private void drawOneCell(Canvas canvas) {
            //绘制第一个单元格分类
            drawTableTitleLine(canvas);
        
            String topTitle = mHorizontalTitle[0];
            String leftTitle = mVerticalTitle[0];
        
            int t = 0;
            int b = mTableHeadTextHeight + 8;
            int l = cellWidth / cellHeight * b;
            int r = cellWidth;
        
        
            int hX = l + (r - l) / 2;
            int hY = b;
            canvas.drawText(topTitle,hX,hY,mTableHeadPaint);
        
            int vX = (cellWidth - l) / 2;
            int vY = (int) (1.5*hY + mTableHeadTextHeight);
            canvas.drawText(leftTitle,vX,vY,mTableHeadPaint);
          }
      
    • 绘制表格类容
      类容绘制支持两种模式,

      1. 普通的数据填充模式:设置一个String数组数据给控件,控件会安装顺序填充。

      2. 编码模式:水平方向,分别表示4,2,1,单元格状态分别有1,0两种,通过&来确定单元格目前状态,然后给单元格绘制不同的图片数据。比如传入传入编码数据,比如“7654321”,7表示水平第一行三个单元格状态都是1,这样就在单元格里绘制相应的图片,比如打勾。

         private void drawContentText(Canvas canvas) {
         int startIndex = mStartRowIndex * mHorizontalGap + mStartColumnIndex -1;
         startIndex = startIndex < 0 ? 0 : startIndex;
         int num = mHorizontalGap * mVerticalGap;
        
         for (int i = startIndex ; i < num; i++){
           int hIndex = i % mHorizontalGap;
           int vIndex = i / mHorizontalGap;
        
           if (mStartRowIndex -1 >= hIndex){
             continue;
           }
        
           if (hIndex >= mHorizontalGap || vIndex >= mVerticalGap){
             return;
           }
        
           if (mMode == MODE_STRING_DATA){
             int index = (vIndex - mStartRowIndex)*(mHorizontalGap - mStartColumnIndex) + hIndex - mStartColumnIndex;
             if(index < 0 || index >= mContentStrData.length){
               continue;
             }
             String str = mContentStrData[index];
             drawCell(canvas,i,str);
        
           }else if (mMode == MODE_ENCODER_DATA){
        
             int encoderStart = hIndex - mStartColumnIndex;
             encoderStart = encoderStart < 0 ? 0 : encoderStart;
        
             if (encoderStart >= ENCODER.length){
               return;
             }
             int encoder = ENCODER[encoderStart];
        
             int vIndexStart = vIndex - mStartRowIndex;
             vIndexStart = vIndexStart < 0 ? 0 : vIndexStart;
             if(vIndexStart >= mContentIntData.length ){
               return;
             }
             if ((encoder & mContentIntData[vIndexStart]) != 0){
               if (null != oneBitmap){
                 drawCell(canvas,i,oneBitmap);
               }else {
                 drawCell(canvas,i,oneStr);
               }
             }else {
               if (null != zeroBitmap){
                 drawCell(canvas,i,zeroBitmap);
               }else {
                 drawCell(canvas,i,zeroStr);
               }
             }
           }
         }
        
      }
      
    • 单元格点击事件和数据更新(在编码模式下)
      通过重写onTouchEvent事件,通过坐标,算出当前触摸点所在的单元格,然后做区域判断,通过&更新数据,
      完整思路请查看源码
      源码

    相关文章

      网友评论

        本文标题:【Android自定义View】- 表格控件

        本文链接:https://www.haomeiwen.com/subject/qpikhqtx.html