一起Talk Android吧(第一百五十一回:Android自定义View之Draw三)

各位看官们大家好,上一回中咱们说的是Android中自定义View之Draw的例子,这一回咱们继续说该例子。闲话休提,言归正转。让我们一起Talk Android吧!

看官们,我们在前面章回中介绍了View的draw()函数,并且介绍了两个重载的draw()函数,以及它们的不同点。这一回中我们将介绍View的onDraw()函数,不过遗憾的是该函数是一个空函数,接下来,我们以View的直接子类TextView为例来介绍onDraw()函数的过程。下面是它的源代码:

  @Override
  protected void onDraw(Canvas canvas) {
      restartMarqueeIfNeeded();

      // Draw the background for this view
      super.onDraw(canvas);

      final int compoundPaddingLeft = getCompoundPaddingLeft();
      final int compoundPaddingTop = getCompoundPaddingTop();
      final int compoundPaddingRight = getCompoundPaddingRight();
      final int compoundPaddingBottom = getCompoundPaddingBottom();
      final int scrollX = mScrollX;
      final int scrollY = mScrollY;
      final int right = mRight;
      final int left = mLeft;
      final int bottom = mBottom;
      final int top = mTop;
      final boolean isLayoutRtl = isLayoutRtl();
      final int offset = getHorizontalOffsetForDrawables();
      final int leftOffset = isLayoutRtl ? 0 : offset;
      final int rightOffset = isLayoutRtl ? offset : 0;

      final Drawables dr = mDrawables;
      if (dr != null) {
          /*
           * Compound, not extended, because the icon is not clipped
           * if the text height is smaller.
           */

          int vspace = bottom - top - compoundPaddingBottom - compoundPaddingTop;
          int hspace = right - left - compoundPaddingRight - compoundPaddingLeft;

          // IMPORTANT: The coordinates computed are also used in invalidateDrawable()
          // Make sure to update invalidateDrawable() when changing this code.
          if (dr.mShowing[Drawables.LEFT] != null) {
              canvas.save();
              canvas.translate(scrollX + mPaddingLeft + leftOffset,
                      scrollY + compoundPaddingTop + (vspace - dr.mDrawableHeightLeft) / 2);
              dr.mShowing[Drawables.LEFT].draw(canvas);
              canvas.restore();
          }

          // IMPORTANT: The coordinates computed are also used in invalidateDrawable()
          // Make sure to update invalidateDrawable() when changing this code.
          if (dr.mShowing[Drawables.RIGHT] != null) {
              canvas.save();
              canvas.translate(scrollX + right - left - mPaddingRight
                      - dr.mDrawableSizeRight - rightOffset,
                       scrollY + compoundPaddingTop + (vspace - dr.mDrawableHeightRight) / 2);
              dr.mShowing[Drawables.RIGHT].draw(canvas);
              canvas.restore();
          }

          // IMPORTANT: The coordinates computed are also used in invalidateDrawable()
          // Make sure to update invalidateDrawable() when changing this code.
          if (dr.mShowing[Drawables.TOP] != null) {
              canvas.save();
              canvas.translate(scrollX + compoundPaddingLeft
                      + (hspace - dr.mDrawableWidthTop) / 2, scrollY + mPaddingTop);
              dr.mShowing[Drawables.TOP].draw(canvas);
              canvas.restore();
          }

          // IMPORTANT: The coordinates computed are also used in invalidateDrawable()
          // Make sure to update invalidateDrawable() when changing this code.
          if (dr.mShowing[Drawables.BOTTOM] != null) {
              canvas.save();
              canvas.translate(scrollX + compoundPaddingLeft
                      + (hspace - dr.mDrawableWidthBottom) / 2,
                       scrollY + bottom - top - mPaddingBottom - dr.mDrawableSizeBottom);
              dr.mShowing[Drawables.BOTTOM].draw(canvas);
              canvas.restore();
          }
      }

      int color = mCurTextColor;

      if (mLayout == null) {
          assumeLayout();
      }

      Layout layout = mLayout;

      if (mHint != null && mText.length() == 0) {
          if (mHintTextColor != null) {
              color = mCurHintTextColor;
          }

          layout = mHintLayout;
      }

      mTextPaint.setColor(color);
      mTextPaint.drawableState = getDrawableState();

      canvas.save();
      /*  Would be faster if we didn't have to do this. Can we chop the
          (displayable) text so that we don't need to do this ever?
      */

      int extendedPaddingTop = getExtendedPaddingTop();
      int extendedPaddingBottom = getExtendedPaddingBottom();

      final int vspace = mBottom - mTop - compoundPaddingBottom - compoundPaddingTop;
      final int maxScrollY = mLayout.getHeight() - vspace;

      float clipLeft = compoundPaddingLeft + scrollX;
      float clipTop = (scrollY == 0) ? 0 : extendedPaddingTop + scrollY;
      float clipRight = right - left - getCompoundPaddingRight() + scrollX;
      float clipBottom = bottom - top + scrollY
              - ((scrollY == maxScrollY) ? 0 : extendedPaddingBottom);

      if (mShadowRadius != 0) {
          clipLeft += Math.min(0, mShadowDx - mShadowRadius);
          clipRight += Math.max(0, mShadowDx + mShadowRadius);

          clipTop += Math.min(0, mShadowDy - mShadowRadius);
          clipBottom += Math.max(0, mShadowDy + mShadowRadius);
      }

      canvas.clipRect(clipLeft, clipTop, clipRight, clipBottom);

      int voffsetText = 0;
      int voffsetCursor = 0;

      // translate in by our padding
      /* shortcircuit calling getVerticaOffset() */
      if ((mGravity & Gravity.VERTICAL_GRAVITY_MASK) != Gravity.TOP) {
          voffsetText = getVerticalOffset(false);
          voffsetCursor = getVerticalOffset(true);
      }
      canvas.translate(compoundPaddingLeft, extendedPaddingTop + voffsetText);

      final int layoutDirection = getLayoutDirection();
      final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
      if (isMarqueeFadeEnabled()) {
          if (!mSingleLine && getLineCount() == 1 && canMarquee()
                  && (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) != Gravity.LEFT) {
              final int width = mRight - mLeft;
              final int padding = getCompoundPaddingLeft() + getCompoundPaddingRight();
              final float dx = mLayout.getLineRight(0) - (width - padding);
              canvas.translate(layout.getParagraphDirection(0) * dx, 0.0f);
          }

          if (mMarquee != null && mMarquee.isRunning()) {
              final float dx = -mMarquee.getScroll();
              canvas.translate(layout.getParagraphDirection(0) * dx, 0.0f);
          }
      }

      final int cursorOffsetVertical = voffsetCursor - voffsetText;

      Path highlight = getUpdatedHighlightPath();
      if (mEditor != null) {
          mEditor.onDraw(canvas, layout, highlight, mHighlightPaint, cursorOffsetVertical);
      } else {
          layout.draw(canvas, highlight, mHighlightPaint, cursorOffsetVertical);
      }

      if (mMarquee != null && mMarquee.shouldDrawGhost()) {
          final float dx = mMarquee.getGhostOffset();
          canvas.translate(layout.getParagraphDirection(0) * dx, 0.0f);
          layout.draw(canvas, highlight, mHighlightPaint, cursorOffsetVertical);
      }

      canvas.restore();
  }

从源代码中可以看出,它会调用父类的draw()函数去绘制背景,然后依据坐标分别绘制左,右,上,下的边距,最后是绘制文字。

各位看官,关于Androd中自定义View之Draw的例子咱们就介绍到这里,欲知后面还有什么例子,且听下回分解!

发布了520 篇原创文章 · 获赞 131 · 访问量 62万+

猜你喜欢

转载自blog.csdn.net/talk_8/article/details/102827040