美文网首页
Android学习笔记1

Android学习笔记1

作者: 依然淳熙 | 来源:发表于2018-12-13 09:44 被阅读0次

    1 关于关于TextView的baseline计算。

    baseline如图所示 image

    英文显示baseline比中文的更明显一些。可以通过FontMetrics来top等获取属性值,FontMetrics类介绍如下

     /**
         * Class that describes the various metrics for a font at a given text size.
         * Remember, Y values increase going down, so those values will be positive,
         * and values that measure distances going up will be negative. This class
         * is returned by getFontMetrics().
         */
        public static class FontMetrics {
            /**
             * The maximum distance above the baseline for the tallest glyph in
             * the font at a given text size.
             */
            public float   top;
            /**
             * The recommended distance above the baseline for singled spaced text.
             */
            public float   ascent;
            /**
             * The recommended distance below the baseline for singled spaced text.
             */
            public float   descent;
            /**
             * The maximum distance below the baseline for the lowest glyph in
             * the font at a given text size.
             */
            public float   bottom;
            /**
             * The recommended additional space to add between lines of text.
             */
            public float   leading;
        }
    

    通过Paint画笔获取FontMetrics或FontMetricsInt。FontMetrics是float类型,FontMetricsInt是int类型的返回值

        Paint.FontMetrics fontMetrics=mPaint.getFontMetrics();
        Paint.FontMetricsInt fontMetricsInt= mPaint.getFontMetricsInt();
    

    然后就可以计算baseline了,可以通过top和bottom计算,也可以通过ascent和descent来计算。

    int dy=(fontMetricsInt.bottom-fontMetricsInt.top)/2-fontMetricsInt.bottom;
    int dy=(fontMetricsInt.descent -fontMetricsInt.ascent) / 2 - fontMetricsInt.descent;
    

    canvas的drawText方法如下:

    /**
         * Draw the text, with origin at (x,y), using the specified paint. The origin is interpreted
         * based on the Align setting in the paint.
         *
         * @param text The text to be drawn
         * @param x The x-coordinate of the origin of the text being drawn
         * @param y The y-coordinate of the baseline of the text being drawn
         * @param paint The paint used for the text (e.g. color, size, style)
         */
        public void drawText(@NonNull String text, float x, float y, @NonNull Paint paint) {
            super.drawText(text, x, y, paint);
        }
    

    我们要注意第三个参数y与画布的原点位置有关系,比如如果原点在画布左上角,文字要画在画布Y轴中心那么

    y=容器高度/2+dy
    

    多试验试验就好了。

    2自定义View继承ViewGroup 默认不会调用onDraw方法 为什么?

    通过查看了一些资料,知道了是通过ViewRootImpl的performTraversals()方法依次调用performMeasure(),performLayout(),performDraw()方法,进而实现了View的measure、layout、draw三大流程。View中调用顺序为measure(),layout(),draw();
    ViewGroup继承自View ,View的draw方法如下

      @CallSuper
        public void draw(Canvas canvas) {
            final int privateFlags = mPrivateFlags;
            final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
                    (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
            mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
    
            /*
             * Draw traversal performs several drawing steps which must be executed
             * in the appropriate order:
             *
             *      1. Draw the background
             *      2. If necessary, save the canvas' layers to prepare for fading
             *      3. Draw view's content
             *      4. Draw children
             *      5. If necessary, draw the fading edges and restore layers
             *      6. Draw decorations (scrollbars for instance)
             */
             // Step 1, draw the background, if needed
            int saveCount;
    
            if (!dirtyOpaque) {
                drawBackground(canvas);
            }
            // skip step 2 & 5 if possible (common case)
            ..........................
            // Step 3, draw the content
            if (!dirtyOpaque) onDraw(canvas);
    
            // Step 4, draw the children
            dispatchDraw(canvas);
            // Step 5, draw the fade effect and restore layers
            ..........................
             // Step 6, draw decorations (foreground, scrollbars)
            onDrawForeground(canvas);
    
    }
    

    主要有6个过程。发现了只有dirtyOpaque是false 才会调用onDraw()方法。而dirtyOpaque这个变量是由 mPrivateFlags控制的。mPrivateFlags 到底是怎么赋值的 通过查找代码, 发现在View的构造函数中调用 computeOpaqueFlags()来设置这个变量

    protected void computeOpaqueFlags() {
            // Opaque if:
            //   - Has a background
            //   - Background is opaque
            //   - Doesn't have scrollbars or scrollbars overlay
    
            if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
                mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
            } else {
                mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
            }
    
            final int flags = mViewFlags;
            if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
                    (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
                    (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
                mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
            } else {
                mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
            }
        }
    

    ViewGroup 为什么出不来 initViewGroup

     private void initViewGroup() {
            // ViewGroup doesn't draw by default
            if (!debugDraw()) {
                setFlags(WILL_NOT_DRAW, DRAW_MASK);
            }
            导致 mPrivateFlags 会重新赋值
            mGroupFlags |= FLAG_CLIP_CHILDREN;
            mGroupFlags |= FLAG_CLIP_TO_PADDING;
            mGroupFlags |= FLAG_ANIMATION_DONE;
            mGroupFlags |= FLAG_ANIMATION_CACHE;
            mGroupFlags |= FLAG_ALWAYS_DRAWN_WITH_CACHE;
    
            if (mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB) {
                mGroupFlags |= FLAG_SPLIT_MOTION_EVENTS;
            }
    
            setDescendantFocusability(FOCUS_BEFORE_DESCENDANTS);
    
            mChildren = new View[ARRAY_INITIAL_CAPACITY];
            mChildrenCount = 0;
    
            mPersistentDrawingCache = PERSISTENT_SCROLLING_CACHE;
        }
    

    相关文章

      网友评论

          本文标题:Android学习笔记1

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