Ejemplo n.º 1
0
 // 递归计算出对应的index
 private int getLoopMappingIndex(int index) {
   if (index < 0) {
     index = index + adapter.getItemsCount();
     index = getLoopMappingIndex(index);
   } else if (index > adapter.getItemsCount() - 1) {
     index = index - adapter.getItemsCount();
     index = getLoopMappingIndex(index);
   }
   return index;
 }
Ejemplo n.º 2
0
  private void remeasure() {
    if (adapter == null) {
      return;
    }

    measureTextWidthHeight();

    // 最大Text的高度乘间距倍数得到 可见文字实际的总高度,半圆的周长
    halfCircumference = (int) (itemHeight * (itemsVisible - 1));
    // 整个圆的周长除以PI得到直径,这个直径用作控件的总高度
    measuredHeight = (int) ((halfCircumference * 2) / Math.PI);
    // 求出半径
    radius = (int) (halfCircumference / Math.PI);
    // 控件宽度,这里支持weight
    measuredWidth = MeasureSpec.getSize(widthMeasureSpec);
    // 计算两条横线和控件中间点的Y位置
    firstLineY = (measuredHeight - itemHeight) / 2.0F;
    secondLineY = (measuredHeight + itemHeight) / 2.0F;
    centerY = (measuredHeight + maxTextHeight) / 2.0F - CENTERCONTENTOFFSET;
    // 初始化显示的item的position,根据是否loop
    if (initPosition == -1) {
      if (isLoop) {
        initPosition = (adapter.getItemsCount() + 1) / 2;
      } else {
        initPosition = 0;
      }
    }

    preCurrentIndex = initPosition;
  }
Ejemplo n.º 3
0
 /** 计算最大len的Text的宽高度 */
 private void measureTextWidthHeight() {
   Rect rect = new Rect();
   for (int i = 0; i < adapter.getItemsCount(); i++) {
     String s1 = getContentText(adapter.getItem(i));
     paintCenterText.getTextBounds(s1, 0, s1.length(), rect);
     int textWidth = rect.width();
     if (textWidth > maxTextWidth) {
       maxTextWidth = textWidth;
     }
     paintCenterText.getTextBounds("\u661F\u671F", 0, 2, rect); // 星期
     int textHeight = rect.height();
     if (textHeight > maxTextHeight) {
       maxTextHeight = textHeight;
     }
   }
   itemHeight = lineSpacingMultiplier * maxTextHeight;
 }
Ejemplo n.º 4
0
  @Override
  public boolean onTouchEvent(MotionEvent event) {
    boolean eventConsumed = gestureDetector.onTouchEvent(event);
    switch (event.getAction()) {
      case MotionEvent.ACTION_DOWN:
        startTime = System.currentTimeMillis();
        cancelFuture();
        previousY = event.getRawY();
        break;

      case MotionEvent.ACTION_MOVE:
        float dy = previousY - event.getRawY();
        previousY = event.getRawY();
        totalScrollY = (int) (totalScrollY + dy);

        // 边界处理。
        if (!isLoop) {
          float top = -initPosition * itemHeight;
          float bottom = (adapter.getItemsCount() - 1 - initPosition) * itemHeight;
          if (totalScrollY - itemHeight * 0.3 < top) {
            top = totalScrollY - dy;
          } else if (totalScrollY + itemHeight * 0.3 > bottom) {
            bottom = totalScrollY - dy;
          }

          if (totalScrollY < top) {
            totalScrollY = (int) top;
          } else if (totalScrollY > bottom) {
            totalScrollY = (int) bottom;
          }
        }
        break;

      case MotionEvent.ACTION_UP:
      default:
        if (!eventConsumed) {
          float y = event.getY();
          double l = Math.acos((radius - y) / radius) * radius;
          int circlePosition = (int) ((l + itemHeight / 2) / itemHeight);

          float extraOffset = (totalScrollY % itemHeight + itemHeight) % itemHeight;
          mOffset = (int) ((circlePosition - itemsVisible / 2) * itemHeight - extraOffset);

          if ((System.currentTimeMillis() - startTime) > 120) {
            // 处理拖拽事件
            smoothScroll(ACTION.DAGGLE);
          } else {
            // 处理条目点击事件
            smoothScroll(ACTION.CLICK);
          }
        }
        break;
    }
    invalidate();

    return true;
  }
Ejemplo n.º 5
0
 /**
  * 获取Item个数
  *
  * @return
  */
 public int getItemsCount() {
   return adapter != null ? adapter.getItemsCount() : 0;
 }
Ejemplo n.º 6
0
  @Override
  protected void onDraw(Canvas canvas) {
    if (adapter == null) {
      return;
    }
    // 可见的item数组
    Object visibles[] = new Object[itemsVisible];
    // 滚动的Y值高度除去每行Item的高度,得到滚动了多少个item,即change数
    change = (int) (totalScrollY / itemHeight);
    try {
      // 滚动中实际的预选中的item(即经过了中间位置的item) = 滑动前的位置 + 滑动相对位置
      preCurrentIndex = initPosition + change % adapter.getItemsCount();
    } catch (ArithmeticException e) {
      System.out.println("出错了!adapter.getItemsCount() == 0,联动数据不匹配");
    }
    if (!isLoop) { // 不循环的情况
      if (preCurrentIndex < 0) {
        preCurrentIndex = 0;
      }
      if (preCurrentIndex > adapter.getItemsCount() - 1) {
        preCurrentIndex = adapter.getItemsCount() - 1;
      }
    } else { // 循环
      if (preCurrentIndex
          < 0) { // 举个例子:如果总数是5,preCurrentIndex = -1,那么preCurrentIndex按循环来说,其实是0的上面,也就是4的位置
        preCurrentIndex = adapter.getItemsCount() + preCurrentIndex;
      }
      if (preCurrentIndex > adapter.getItemsCount() - 1) { // 同理上面,自己脑补一下
        preCurrentIndex = preCurrentIndex - adapter.getItemsCount();
      }
    }

    // 跟滚动流畅度有关,总滑动距离与每个item高度取余,即并不是一格格的滚动,每个item不一定滚到对应Rect里的,这个item对应格子的偏移值
    int itemHeightOffset = (int) (totalScrollY % itemHeight);
    // 设置数组中每个元素的值
    int counter = 0;
    while (counter < itemsVisible) {
      int index =
          preCurrentIndex
              - (itemsVisible / 2 - counter); // 索引值,即当前在控件中间的item看作数据源的中间,计算出相对源数据源的index值

      // 判断是否循环,如果是循环数据源也使用相对循环的position获取对应的item值,如果不是循环则超出数据源范围使用""空白字符串填充,在界面上形成空白无数据的item项
      if (isLoop) {
        index = getLoopMappingIndex(index);
        visibles[counter] = adapter.getItem(index);
      } else if (index < 0) {
        visibles[counter] = "";
      } else if (index > adapter.getItemsCount() - 1) {
        visibles[counter] = "";
      } else {
        visibles[counter] = adapter.getItem(index);
      }

      counter++;
    }

    // 中间两条横线
    canvas.drawLine(0.0F, firstLineY, measuredWidth, firstLineY, paintIndicator);
    canvas.drawLine(0.0F, secondLineY, measuredWidth, secondLineY, paintIndicator);
    // 单位的Label
    if (label != null) {
      int drawRightContentStart = measuredWidth - getTextWidth(paintCenterText, label);
      // 靠右并留出空隙
      canvas.drawText(label, drawRightContentStart - CENTERCONTENTOFFSET, centerY, paintCenterText);
    }
    counter = 0;
    while (counter < itemsVisible) {
      canvas.save();
      // L(弧长)=α(弧度)* r(半径) (弧度制)
      // 求弧度--> (L * π ) / (π * r)   (弧长X派/半圆周长)
      float itemHeight = maxTextHeight * lineSpacingMultiplier;
      double radian = ((itemHeight * counter - itemHeightOffset) * Math.PI) / halfCircumference;
      // 弧度转换成角度(把半圆以Y轴为轴心向右转90度,使其处于第一象限及第四象限
      float angle = (float) (90D - (radian / Math.PI) * 180D);
      // 九十度以上的不绘制
      if (angle >= 90F || angle <= -90F) {
        canvas.restore();
      } else {
        String contentText = getContentText(visibles[counter]);

        // 计算开始绘制的位置
        measuredCenterContentStart(contentText);
        measuredOutContentStart(contentText);
        float translateY =
            (float) (radius - Math.cos(radian) * radius - (Math.sin(radian) * maxTextHeight) / 2D);
        // 根据Math.sin(radian)来更改canvas坐标系原点,然后缩放画布,使得文字高度进行缩放,形成弧形3d视觉差
        canvas.translate(0.0F, translateY);
        canvas.scale(1.0F, (float) Math.sin(radian));
        if (translateY <= firstLineY && maxTextHeight + translateY >= firstLineY) {
          // 条目经过第一条线
          canvas.save();
          canvas.clipRect(0, 0, measuredWidth, firstLineY - translateY);
          canvas.scale(1.0F, (float) Math.sin(radian) * SCALECONTENT);
          canvas.drawText(contentText, drawOutContentStart, maxTextHeight, paintOuterText);
          canvas.restore();
          canvas.save();
          canvas.clipRect(0, firstLineY - translateY, measuredWidth, (int) (itemHeight));
          canvas.scale(1.0F, (float) Math.sin(radian) * 1F);
          canvas.drawText(
              contentText,
              drawCenterContentStart,
              maxTextHeight - CENTERCONTENTOFFSET,
              paintCenterText);
          canvas.restore();
        } else if (translateY <= secondLineY && maxTextHeight + translateY >= secondLineY) {
          // 条目经过第二条线
          canvas.save();
          canvas.clipRect(0, 0, measuredWidth, secondLineY - translateY);
          canvas.scale(1.0F, (float) Math.sin(radian) * 1.0F);
          canvas.drawText(
              contentText,
              drawCenterContentStart,
              maxTextHeight - CENTERCONTENTOFFSET,
              paintCenterText);
          canvas.restore();
          canvas.save();
          canvas.clipRect(0, secondLineY - translateY, measuredWidth, (int) (itemHeight));
          canvas.scale(1.0F, (float) Math.sin(radian) * SCALECONTENT);
          canvas.drawText(contentText, drawOutContentStart, maxTextHeight, paintOuterText);
          canvas.restore();
        } else if (translateY >= firstLineY && maxTextHeight + translateY <= secondLineY) {
          // 中间条目
          canvas.clipRect(0, 0, measuredWidth, (int) (itemHeight));
          canvas.drawText(
              contentText,
              drawCenterContentStart,
              maxTextHeight - CENTERCONTENTOFFSET,
              paintCenterText);
          int preSelectedItem = adapter.indexOf(visibles[counter]);
          if (preSelectedItem != -1) {
            selectedItem = preSelectedItem;
          }
        } else {
          // 其他条目
          canvas.save();
          canvas.clipRect(0, 0, measuredWidth, (int) (itemHeight));
          canvas.scale(1.0F, (float) Math.sin(radian) * SCALECONTENT);
          canvas.drawText(contentText, drawOutContentStart, maxTextHeight, paintOuterText);
          canvas.restore();
        }
        canvas.restore();
      }
      counter++;
    }
  }