GVKun编程网logo

android – 自定义视图不绘制自己(安卓自定义视图)

8

对于想了解android–自定义视图不绘制自己的读者,本文将是一篇不可错过的文章,我们将详细介绍安卓自定义视图,并且为您提供关于AndroidCanvas绘制自定义“线头”问题、android–onD

对于想了解android – 自定义视图不绘制自己的读者,本文将是一篇不可错过的文章,我们将详细介绍安卓自定义视图,并且为您提供关于Android Canvas 绘制自定义 “线头” 问题、android – onDraw Scrollview中的自定义视图、android – 为什么自定义视图不会失效?、android – 以编程方式添加时自定义视图不膨胀布局的有价值信息。

本文目录一览:

android – 自定义视图不绘制自己(安卓自定义视图)

android – 自定义视图不绘制自己(安卓自定义视图)

我在这里读到了关于这个主题的不同问题,但我仍然找不到答案.随时以任何理由关闭此问题.

我有一个简单的Circle类,可以扩展View.

这个类的代码是:

public class ProgressCircle extends View {
    Paint mCirclePaint;
    float exTradius;
    float viewWidth,viewHeight;
    float centerX,centerY;

    public ProgressCircle(Context context,AttributeSet attrs) {
        super(context,attrs);
        setwillNotDraw(false);
        init();
    }

    @Override
    protected void onSizeChanged(int w,int h,int oldw,int oldh) {
        float xpad = (float) getPaddingLeft() + getPaddingRight();
        float ypad = (float) getPaddingTop() + getPaddingBottom();
        float ww = (float)w - xpad; float hh = (float)h - ypad;
        exTradius = Math.min(ww,hh) / 2;

        viewWidth = this.getWidth();
        viewHeight = this.getHeight();
        centerX = viewWidth / 2; centerY = viewHeight / 2;

        super.onSizeChanged(w,h,oldw,oldh);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawCircle(centerX,centerY,exTradius,mCirclePaint);
        canvas.drawText("Ciao",mCirclePaint);    
    }

    private void init() {
        mCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mCirclePaint.setColor(0x666666);
        mCirclePaint.setStyle(Paint.Style.FILL_AND_stroke);
    }

我确认在创建主活动时(通过使用一些Log.d()s)调用此类中的每个方法.我添加了一个< com.mypackage.Circle>我的主要活动的LinearLayout中的元素,然后我添加了一个示例测试按钮.

我所取得的成就是我的圆圈没有显示按钮,但仍然是按钮(在Circle之后的LinearLayout中)不是布局的第一个元素:这让我觉得实际发生了一些事情,但没有得到了.

解决方法

这只是一个愚蠢的问题:mCirclePaint.setColor(0x666666)中的颜色是无效的.它适用于mCirclePaint.setColor(Color.RED)或res文件夹中定义的任何其他颜色.

如果需要指定颜色值,则必须包含透明度字节(否则它不是您指定的32位整数,而是24位).因此0x666666无效,但0xff666666是有效颜色并将绘制.

Android Canvas 绘制自定义 “线头” 问题

Android Canvas 绘制自定义 “线头” 问题

线头介绍:

Android 提供了线头设置的方法线头形状有三种:

BUTT 平头、ROUND 圆头、SQUARE 方头。

默认为 BUTT。

而当线条变粗的时候,它们就会表现出不同的样子:

 

问题:如何自定义文章开始那种线头呢?

 

解决方案:

线条描边,我们给线条添加 border

boder 宽度 * 2 + 中心线条宽度 = 总宽度

由于实现方案需要结合场景,因此不适合封装,但是具体用途我们按照本思路实现即可

下面我们给出一个案例

代码实现

public class SectionPointerMeterView extends View implements ValueAnimator.AnimatorUpdateListener {

    private final String TAG = "MeterView";
    private TextPaint mTextPaint;
    private DisplayMetrics mDisplayMetrics;
    private int mContentHeight = 0;
    private int mContentWidth = 0;

    private final float MIN_ARC_ANGLE = 120f;
    private final float MAX_ARC_ANGLE = 360 - MIN_ARC_ANGLE;
    private int progress = 0;
    private int maxProgress = 100;
    private String tagText = "";
    private final static String UNIT_PERCENT = "%";
    private ValueAnimator animatorProgress = null;
    private volatile boolean isRelease = false;
    private boolean disableComputeColorBlock = false;

    private float MIN_PADDING = 0.0f;
    private float lineRadius = 0;

    public static class ColorBlock {
        int color;
        float ratio;

        public ColorBlock(float ratio, int color) {
            this.color = color;
            this.ratio = ratio;
        }

        static ColorBlock build(float ratio, int color) {
            ColorBlock cb = new ColorBlock(ratio, color);
            return cb;
        }
    }

    public final ColorBlock[] colorBlocks = {
            ColorBlock.build(0f, 0xffFF1D1D),
            ColorBlock.build(0.1f, 0xffFF1D1D),
            ColorBlock.build(0.2f, 0xffF04D11),
            ColorBlock.build(0.3f, 0xffF04D11),
            ColorBlock.build(0.4f, 0xffFEA315),
            ColorBlock.build(0.5f, 0xffFEA315),
            ColorBlock.build(0.6f, 0xffFEA315),
            ColorBlock.build(0.7f, 0xffF8DF38),
            ColorBlock.build(0.8f, 0xffF8DF38),
            ColorBlock.build(0.9f, 0xff10D659),
            ColorBlock.build(1.0f, 0xff10D659),

    };

    public SectionPointerMeterView(Context context) {
        this(context, null);
    }

    public SectionPointerMeterView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public SectionPointerMeterView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initPaint();
        if (isInEditMode() || BuildConfig.DEBUG) {
            setMaxProgress(100);
            setProgress(25);
            setTagText("功效");
        }
    }

    public void setMaxProgress(int maxProgress) {
        if (maxProgress <= 0) {
            throw new IllegalArgumentException(" max progress must be postive num");
        }
        this.maxProgress = maxProgress;
        invalidate();
    }

    public void setProgress(int progress) {

        if (progress < 0) {
            throw new IllegalArgumentException("  progress must be no-nagtive num");
        }
        this.progress = progress;
        invalidate();
    }

    public void setProgress(int progress, boolean isAnimate) {
        if (progress < 0) {
            throw new IllegalArgumentException("  progress must be no-nagtive num");
        }
        if (!isAnimate) {
            setProgress(progress);
            return;
        }

        int current = this.progress;
        int target = progress;

        if (animatorProgress != null) {
            animatorProgress.cancel();
            animatorProgress = null;
        }
        if (target == current) {
            return;
        }
        startProgressAnimation(current, target);

    }

    private void startProgressAnimation(int current, int target) {
        ValueAnimator animator = ValueAnimator.ofInt(current, target);
        animator.setDuration(1100);
        animator.setInterpolator(new BounceInterpolator());
        animatorProgress = animator;
        animatorProgress.addUpdateListener(this);
        animator.start();
    }

    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        this.progress = (int) animation.getAnimatedValue();
        invalidate();
    }

    public void setTagText(String tagText) {
        this.tagText = tagText;
    }

    private void initPaint() {
        mDisplayMetrics = getResources().getDisplayMetrics();
        mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
        mTextPaint.setAntiAlias(true);
        MIN_PADDING = dp2px(1);
        lineRadius = dp2px(5);

    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);

        if (widthMode != MeasureSpec.EXACTLY) {
            widthSize = mDisplayMetrics.widthPixels / 2;
        }

        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);

        if (heightMode != MeasureSpec.EXACTLY) {
            heightSize = widthSize / 2;
        }
        setMeasuredDimension(widthSize, heightSize);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {

        super.onSizeChanged(w, h, oldw, oldh);

        mContentHeight = (int) (h - MIN_PADDING*2);
        mContentWidth = (int) (w - MIN_PADDING*2);

    }


    private float minLength = 0f;
    private float outArcR = 0f;
    private float  centerX = 0f;
    private float  centerY = 0f;
    private float  startAngle = 0f;
    private float offsetDegree = 5f;

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (isRelease) {
            return;
        }

        mTextPaint.setStyle(Paint.Style.STROKE);

        mTextPaint.setStrokeWidth(dp2px(20));
        float arcStrokeWidth = mTextPaint.getStrokeWidth();
        if (mContentWidth <= arcStrokeWidth || mContentHeight <= arcStrokeWidth) {
            return;
        }

        minLength = Math.min(mContentWidth, mContentHeight) - arcStrokeWidth;
        outArcR  = (float) (minLength/(1f+Math.cos(Math.toRadians(MIN_ARC_ANGLE/2))));
        centerX = getWidth()/2f;
        centerY = outArcR + MIN_PADDING + arcStrokeWidth/2;
        startAngle = (180f - MIN_ARC_ANGLE)/2f +  MIN_ARC_ANGLE;

        Bitmap targetBitmap =  Bitmap.createBitmap(getWidth(),getHeight(),Bitmap.Config.ARGB_8888);
        drawArcSection(new Canvas(targetBitmap), arcStrokeWidth);
        RectF rectF = new RectF();
        rectF.left = 0;
        rectF.right = getWidth();
        rectF.top = 0;
        rectF.bottom = getHeight();
        canvas.drawBitmap(targetBitmap,null,rectF,null);
        targetBitmap.recycle();

        int saveCount = canvas.save();
        canvas.translate(centerX,centerY);

        float totalDegree = 360f - (MIN_ARC_ANGLE+ offsetDegree *2);
        float perDegree = totalDegree/10f;
        mTextPaint.setStrokeWidth(dp2px(1));
        mTextPaint.setColor(Color.WHITE);
        mTextPaint.setStrokeCap(Paint.Cap.BUTT);
        for (int i=0;i<11;i++){
            float angle = (float) Math.toRadians(startAngle+ offsetDegree + i* perDegree);
            float sx = (float) (Math.cos(angle)*(outArcR - arcStrokeWidth/2));
            float sy = (float) (Math.sin(angle)*(outArcR - arcStrokeWidth/2));

            float ex = (float) (Math.cos(angle)*(outArcR - arcStrokeWidth/2-dp2px(5)));
            float ey = (float) (Math.sin(angle)*(outArcR - arcStrokeWidth/2-dp2px(5)));

            canvas.drawLine(sx,sy,ex,ey,mTextPaint);
        }


        drawPointer(canvas,outArcR);

        float  innerArcR = outArcR/2f;
        SweepGradient colorShader = new SweepGradient(0, 0, new int[]{
                0x33ffffff,
                Color.TRANSPARENT,
                0x33ffffff,
                Color.WHITE,
                0x33ffffff
        },new float[]{
                0,
                (90)/360f,
                180f/360f,
                270/360f,
                1.0f
        });
        mTextPaint.setStyle(Paint.Style.STROKE);
        mTextPaint.setShader(colorShader);


        RectF innerArcRect = new RectF();
        innerArcRect.left   =  -innerArcR;
        innerArcRect.right  =   innerArcR;
        innerArcRect.top    =  -innerArcR;
        innerArcRect.bottom  =   innerArcR;
        canvas.drawArc(innerArcRect,startAngle+ offsetDegree,MAX_ARC_ANGLE-2* offsetDegree,false,mTextPaint);

        mTextPaint.setShader( null);

        canvas.restoreToCount(saveCount);

        mTextPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        drawTextBlock(canvas,centerX,centerY);
        drawTextScale(canvas,centerX,centerY,outArcR-arcStrokeWidth-dp2px(8));

    }

    private void drawPointer(Canvas canvas, float compassRadius) {
        int count = canvas.save();
        float ratio = (progress * 1f / maxProgress * 1f);
        float CONTENT_MAX_ARC_ANGEL = (MAX_ARC_ANGLE - offsetDegree*2);
        float progressAngle = ratio * (MAX_ARC_ANGLE - offsetDegree*2);

        canvas.rotate(-(CONTENT_MAX_ARC_ANGEL) / 2f + progressAngle);
        RectF pointerRectF  = new RectF();
        pointerRectF.left   = - dp2px(1);
        pointerRectF.right  =  dp2px(1);
        pointerRectF.top    = - compassRadius * 2 / 3f;
        pointerRectF.bottom = 0;

        mTextPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        mTextPaint.setColor(0xee5191FF);

        canvas.drawRoundRect(pointerRectF, 0,0, mTextPaint);

        canvas.restoreToCount(count);
    }


    private void drawArcSection(Canvas canvas, float strokeWidth) {


        float  centerLineWidth = strokeWidth - lineRadius * 2;
        float  degree = MAX_ARC_ANGLE* 2f/(11f);

        int saveCount = canvas.save();
        canvas.translate(centerX,centerY);

        mTextPaint.setColor(0xffFF1D1D);  //最左侧边缘
        drawArcRoundLine(canvas, outArcR, startAngle,degree, centerLineWidth);

        mTextPaint.setColor(0xff10D659);//最右侧边缘
        drawArcRoundLine(canvas, outArcR, startAngle+MAX_ARC_ANGLE - degree,degree, centerLineWidth);

        mTextPaint.setStrokeWidth(strokeWidth);
        mTextPaint.setColor(0xffF04D11);
        drawArcLine(canvas,outArcR,startAngle+degree,degree);


        mTextPaint.setColor(0xffF8DF38);  //最右侧第二半圆
        drawArcLine(canvas,outArcR,startAngle+MAX_ARC_ANGLE - degree*2,degree);

        //顶部半圆
        mTextPaint.setColor(0xffFEA315);
        drawArcLine(canvas,outArcR,startAngle+degree*2,degree+degree/2);

        mTextPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
        drawSplitLines(canvas, outArcR, startAngle, degree,strokeWidth);
        mTextPaint.setXfermode(null);

        canvas.restoreToCount(saveCount);
    }

    private void drawSplitLines(Canvas canvas, float outArcR, float startAngle, float degree,float strokeWith) {
        float degreePadding = 5f;

        int color = mTextPaint.getColor();
        mTextPaint.setColor(Color.MAGENTA);
        mTextPaint.setStrokeWidth(strokeWith+dp2px(1));

        drawSplitLine(canvas,outArcR,startAngle+degree-degreePadding/2,degreePadding/2);

        drawSplitLine(canvas,outArcR,startAngle+degree*2-degreePadding/2,degreePadding/2);

        drawSplitLine(canvas,outArcR,(startAngle+degree*2 + degree+degree/2),degreePadding/2);

        drawSplitLine(canvas,outArcR,startAngle+MAX_ARC_ANGLE-degree,degreePadding/2);

        mTextPaint.setColor(color);
    }


    private void drawArcLine(Canvas canvas, float outArcR, float startAngle,float swipeAngle) {
        RectF arcRect = new RectF();

        arcRect.left = - outArcR;
        arcRect.right = outArcR;
        arcRect.top = - outArcR;
        arcRect.bottom = outArcR;

        mTextPaint.setStrokeCap(Paint.Cap.BUTT);
        canvas.drawArc(arcRect, startAngle, swipeAngle, false, mTextPaint);

    }
    private void drawSplitLine(Canvas canvas, float outArcR, float startAngle,float swipeAngle) {
        RectF arcRect = new RectF();
        arcRect.left = - outArcR;
        arcRect.right = outArcR;
        arcRect.top = - outArcR;
        arcRect.bottom = outArcR;

        mTextPaint.setStrokeCap(Paint.Cap.BUTT);
        canvas.drawArc(arcRect, startAngle, swipeAngle, false, mTextPaint);

    }


    private void drawArcRoundLine(Canvas canvas, float outArcR, float startAngle,float swipeAngle, float centerLineWidth) {
        RectF arcRect = new RectF();
        arcRect.left = - outArcR;
        arcRect.right = outArcR;
        arcRect.top = - outArcR;
        arcRect.bottom = outArcR;
        if(centerLineWidth<=0) {
            mTextPaint.setStrokeCap(Paint.Cap.ROUND);
            canvas.drawArc(arcRect, startAngle, swipeAngle, false, mTextPaint);
        }else{
            mTextPaint.setStrokeCap(Paint.Cap.SQUARE);

            mTextPaint.setStrokeWidth(centerLineWidth);
            canvas.drawArc(arcRect, startAngle, swipeAngle, false, mTextPaint);

            mTextPaint.setStrokeCap(Paint.Cap.ROUND);
            mTextPaint.setStrokeWidth(lineRadius*2);

            RectF oArcRect = new RectF();
            oArcRect.left = - outArcR - centerLineWidth/2;
            oArcRect.right = outArcR + centerLineWidth/2;
            oArcRect.top = - outArcR - centerLineWidth /2;
            oArcRect.bottom = outArcR + centerLineWidth/2;

            canvas.drawArc(oArcRect, startAngle, swipeAngle, false, mTextPaint);

            RectF iArcRect = new RectF();
            iArcRect.left = - outArcR + centerLineWidth/2;
            iArcRect.right = outArcR - centerLineWidth/2;
            iArcRect.top = - outArcR + centerLineWidth /2;
            iArcRect.bottom = outArcR - centerLineWidth/2;
            canvas.drawArc(iArcRect, startAngle, swipeAngle, false, mTextPaint);
        }
    }

    private void drawTextScale(Canvas canvas, float centerX, float centerY, float pointerLength) {
        int id = canvas.save();
        canvas.translate(centerX, centerY);
        final String startText = "0%";
        final String endText = maxProgress + "%";

        mTextPaint.setTextSize(dp2px(12));

        float offsetAngle = (180 - MIN_ARC_ANGLE  ) / 2f; //计算从X轴方向逆时针的角度
        float sx = (float) (Math.cos(Math.toRadians((MIN_ARC_ANGLE + offsetAngle + offsetDegree))) * pointerLength);
        float sy = (float) (Math.sin(Math.toRadians((MIN_ARC_ANGLE + offsetAngle + offsetDegree))) * pointerLength);

        canvas.drawText(startText, sx - mTextPaint.measureText(startText) / 2, sy + getTextPaintBaseline(mTextPaint), mTextPaint);

        float x = (float) (Math.cos(Math.toRadians((offsetAngle - offsetDegree))) * pointerLength);
        float y = (float) (Math.sin(Math.toRadians((offsetAngle - offsetDegree))) * pointerLength);
        canvas.drawText(endText, x - mTextPaint.measureText(endText) / 2, y + getTextPaintBaseline(mTextPaint), mTextPaint);


        canvas.restoreToCount(id);
    }

    private void drawTextBlock(Canvas canvas, float centerX, float centerY) {

        float ratio = (progress * 1f / maxProgress * 1f);


        int id = canvas.save();
        canvas.translate(centerX, centerY);

        final String text = "+" + progress;
        ColorBlock colorBlock = computeColorBlock(ratio);

        if (colorBlock != null) {
            mTextPaint.setColor(colorBlock.color);
        }
        final float textSize = dp2px(40);
        final float textUnitSize = dp2px(20);
        final float textPadding = dp2px(2);
        final float topOffset = dp2px(5) * -1f;

        mTextPaint.setTextSize(textSize);
        mTextPaint.setFakeBoldText(true);
        final float textBaseline = getTextPaintBaseline(mTextPaint);
        float textWidth = mTextPaint.measureText(text);

        mTextPaint.setTextSize(textUnitSize);
        mTextPaint.setFakeBoldText(false);

        float textUnitWidth = mTextPaint.measureText(UNIT_PERCENT);
        float topTextWidth = textWidth + textUnitWidth + textPadding;


        mTextPaint.setTextSize(textSize);
        mTextPaint.setFakeBoldText(true);

        canvas.drawText(text, -topTextWidth / 2, textBaseline + topOffset, mTextPaint);

        mTextPaint.setTextSize(textUnitSize);
        mTextPaint.setFakeBoldText(false);
        canvas.drawText(UNIT_PERCENT, -topTextWidth / 2 + textWidth + textPadding, textBaseline + topOffset, mTextPaint);


        mTextPaint.setTextSize(dp2px(15));
        mTextPaint.setFakeBoldText(false);
        mTextPaint.setColor(0xddffffff);
        float bottomTextWidth = mTextPaint.measureText(tagText);

        canvas.drawText(tagText, -bottomTextWidth / 2, topOffset + textBaseline + getTextHeight(mTextPaint) + getTextPaintBaseline(mTextPaint), mTextPaint);
        canvas.restoreToCount(id);
    }

    private ColorBlock computeColorBlock(float ratio) {
        if (disableComputeColorBlock) {
            return ColorBlock.build(ratio, Color.WHITE);
        }
        if (ratio <= 0) {
            return colorBlocks[0];
        }
        if (ratio >= 1f) {
            return colorBlocks[colorBlocks.length - 1];
        }
        for (int i = 0; i < colorBlocks.length; i++) {
            if (ratio > colorBlocks[i].ratio) {
                continue;
            }
            if (colorBlocks[i].ratio == ratio) {
                return colorBlocks[i];
            }
            int preIndex = i - 1;
            float dx = Math.abs(colorBlocks[i].ratio - ratio) - Math.abs(colorBlocks[preIndex].ratio - ratio);
            if (dx > 0) {
                return colorBlocks[preIndex];
            }
            return colorBlocks[i];
        }

        return ColorBlock.build(ratio, Color.WHITE);
    }

    public float dp2px(float dp) {
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, mDisplayMetrics);
    }

    public float sp2px(float dp) {
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, dp, mDisplayMetrics);
    }

    public static int argb(
            int alpha,
            int red,
            int green,
            int blue) {
        return (alpha << 24) | (red << 16) | (green << 8) | blue;
    }

    //真实宽度 + 笔画上下两侧间隙(符合文本绘制基线)
    private static int getTextHeight(Paint paint) {
        Paint.FontMetricsInt fm = paint.getFontMetricsInt();
        int textHeight = ~fm.top - (~fm.top - ~fm.ascent) - (fm.bottom - fm.descent);
        return textHeight;
    }

    /**
     * 基线到中线的距离=(Descent+Ascent)/2-Descent
     * 注意,实际获取到的Ascent是负数。公式推导过程如下:
     * 中线到BOTTOM的距离是(Descent+Ascent)/2,这个距离又等于Descent+中线到基线的距离,即(Descent+Ascent)/2=基线到中线的距离+Descent。
     */
    public static float getTextPaintBaseline(Paint p) {
        Paint.FontMetrics fontMetrics = p.getFontMetrics();
        return (fontMetrics.descent - fontMetrics.ascent) / 2 - fontMetrics.descent;
    }



    public void setDisableComputeColorBlock(boolean disableComputeColorBlock) {
        this.disableComputeColorBlock = disableComputeColorBlock;
        invalidate();
    }
}

 

 

 

 

android – onDraw Scrollview中的自定义视图

android – onDraw Scrollview中的自定义视图

我在水平Scrollview(宽度= 480)内有一个自定义视图(宽度= 2000).所以有一个可滚动的区域.

调用onDraw()时,脏矩形(由getClipBounds()返回)返回整个视图的尺寸,因此我绘制整个视图,包括不可见的区域.因此,当我滚动时,onDraw()不再被调用,因为已经绘制了可见的区域并以某种方式记住了.

public void onDraw(Canvas canvas)
{
    canvas.getClipBounds(r); // returns 2000 x 400
}

这很好用!
但是我的自定义视图可能会超过20,000或更多,并且事情开始变慢.我担心的是缓存的绘图会占用大量内存.我不认为图形被保存为位图,因为它已经崩溃了,所以这些绘图命令(大多数是行和文本)是如何保存的?
有没有办法指定onDraw()应该只请求视图的可见部分,并在滚动时继续调用onDraw()?或者还有其他方法吗?

谢谢!

解决方法

从Android 3.0开始,Android使用 hardware accelerated “display lists”进行绘制.这会导致整个视图的显示列表被缓存.

如果ScrollView中的视图非常大,则视图可以为disable hardware acceleration.

我们通过继承ScrollView并使用以下方法覆盖onAttachedToWindow()方法来完成此操作:

@Override
protected void onAttachedToWindow()
{
    setLayerType(LAYER_TYPE_SOFTWARE,null);
}

android – 为什么自定义视图不会失效?

android – 为什么自定义视图不会失效?

我是 Android开发的菜鸟,我遇到了使视图无效的问题.我正在使用 this教程并没有实现它的问题.但是,当我更改视图的背景时,它仍然会响应,就像之前的背景仍然设置一样.换句话说,我更改了蒙版,但我的“touchview”类没有看到新的蒙版.我没有运气使用invalidate更新视图,我已经验证掩码实际上被重置为背景.任何帮助将不胜感激.

我的代码

@Override
public boolean onMenuItemClick(com.actionbarsherlock.view.MenuItem item) {
    // Todo Auto-generated method stub
    switch (item.getItemId())
    {
        case 1:   // id from the xml file
            if(isMale){
                isMale=false;
                item.setIcon(R.drawable.male_icon);
                imageViewOriginal.setimageResource(R.drawable.woman_front);
                imageViewFlip.setimageResource(R.drawable.woman_back);
                if(isFrontView){
                    myMask.setBackgroundResource(R.drawable.woman_front_mask); //Mask changed here
                }else{
                    myMask.setBackgroundResource(R.drawable.woman_back_mask);  //Mask changed here
                }
            }else{
                isMale=true;
                item.setIcon(R.drawable.female_icon);
                imageViewOriginal.setimageResource(R.drawable.man_front);                   
                imageViewFlip.setimageResource(R.drawable.man_back);
                if(isFrontView){
                    myMask.setBackgroundResource(R.drawable.man_front_mask); //Mask changed here
                }else{
                    myMask.setBackgroundResource(R.drawable.man_back_mask);  //Mask changed here
                }

            }

            touchView.invalidate();
            infoView.invalidate();
            myMask.invalidate(); //Mask View Invalidated here

            return true;   // we handled the click,dont pass it up the chain

        case 2:   // id from the xml file
            if(isFrontView){
                isFrontView=false;
                if(isMale){
                    myMask.setBackgroundResource(R.drawable.man_back_mask); //Mask changed here
                }else{
                    myMask.setBackgroundResource(R.drawable.woman_back_mask); //Mask changed here
                }
            }else{
                isFrontView=true;
                if(isMale){
                    myMask.setBackgroundResource(R.drawable.man_front_mask); //Mask changed here
                }else{
                    myMask.setBackgroundResource(R.drawable.woman_front_mask); //Mask changed here
                }
            }
            FlipAnimator animator = new FlipAnimator(imageViewOriginal,imageViewFlip,imageViewFlip.getWidth() / 2,imageViewFlip.getHeight() / 2);
            if (imageViewOriginal.getVisibility() == View.GONE) {
                animator.reverse();
            }
            flipLayout.startAnimation(animator);

            touchView.invalidate();
            infoView.invalidate();
            myMask.invalidate();  //Mask View Invalidated here

            return true;
    }
    return false;
}

解决方法

我可以想到两种可能性:

选项1:您正在从非UI线程运行代码.在这种情况下,使用postInvalidate()而不是invalidate()

postInvalidate(): Cause an invalidate to happen on a subsequent cycle
through the event loop. Use this to invalidate the View from a non-UI
thread.

选项2:您正在从UI线程运行代码.在这种情况下,我需要您发布更多代码.请记住,invalidate()是异步的,因为它只调度主线程事件队列中的重绘.这意味着仅当当前代码全部执行时才会执行重绘.

在这种情况下,如果某些内容阻止了您的UI-Thread,您可以使用AsyncTask或Runnable来执行您的任务.

android – 以编程方式添加时自定义视图不膨胀布局

android – 以编程方式添加时自定义视图不膨胀布局

我正在尝试以编程方式将自定义视图添加到线性布局.我希望自定义视图膨胀我已经创建的布局.当我创建自定义视图的实例并添加它时,一个点显示视图的位置,但布局似乎没有膨胀(将我的自定义布局的背景颜色设置为绿色,但我看不到空间中的绿色,也不是布局中的图像).

我的自定义视图:

public class AddressView extends View {

  public AddressView(Context context) {
    super(context);
    View.inflate(context, R.layout.place_address, null);
  }

  public AddressView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    View.inflate(context, R.layout.place_address, null);
  }

  public AddressView(Context context, AttributeSet attrs) {
    super(context, attrs);
    View.inflate(context, R.layout.place_address, null);
  }
}

我的自定义视图布局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/address_view"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="#00ff00" >

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/house_1" />

</RelativeLayout>

我在活动中的实例化:

LinearLayout content = (LinearLayout) findViewById(R.id.content);

AddressView addressView = new AddressView(this);
LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, 400);
content.addView(addressView, 0, lp);

我的R.id.content(线性布局是scrollview的唯一子项):

    <LinearLayout
        android:id="@+id/content"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical" >

        <FrameLayout
            android:id="@+id/thumbnail_container"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" >

            <ImageView
                android:id="@+id/thumbnail"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:adjustViewBounds="true"
                android:scaleType="fitXY"
                android:src="@drawable/test_house" />

        </FrameLayout>

    </LinearLayout>

解决方法:

我最终通过扩展FrameLayout而不是View来解决这个问题,并将其传递给inflate调用.我认为该视图正在被添加和膨胀,但它不知道如何正确布置子项,如果您最初将父项传递给inflate调用,则会解决该问题:

public class AddressView extends FrameLayout {

  public AddressView(Context context) {
    super(context);
    LayoutInflater.from(context).inflate(R.layout.place_address, this);
  }

  public AddressView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    LayoutInflater.from(context).inflate(R.layout.place_address, this);
  }

  public AddressView(Context context, AttributeSet attrs) {
    super(context, attrs);
    LayoutInflater.from(context).inflate(R.layout.place_address, this);
  }
}

关于android – 自定义视图不绘制自己安卓自定义视图的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于Android Canvas 绘制自定义 “线头” 问题、android – onDraw Scrollview中的自定义视图、android – 为什么自定义视图不会失效?、android – 以编程方式添加时自定义视图不膨胀布局等相关知识的信息别忘了在本站进行查找喔。

本文标签: