如何通过invalidate更新Canvas?自定义View曲线绘制遇阻求助
Hey there! Since you're new to Android custom View development, let's walk through why calling invalidate() might not be fixing your curve-drawing problem, and how to get it working right.
Common Reasons invalidate() Isn't Working & Fixes
You're calling
invalidate()from a non-UI thread
Android requires all View updates to happen on the main UI thread. If you're calculating curve data in a background thread, you can't callinvalidate()directly there. Instead, use one of these approaches:// Option 1: Switch to UI thread with runOnUiThread runOnUiThread(() -> { yourCustomCurveView.invalidate(); }); // Option 2: Use postInvalidate() (works from any thread) yourCustomCurveView.postInvalidate();Your
onDraw()implementation has gaps
Make sure you're not missing critical steps in your drawing logic:- Always call
super.onDraw(canvas)first (it handles essential View drawing tasks) - Use
Pathfor smooth curves and ensure your coordinate calculations are correct - Save and restore the Canvas state to avoid messing up subsequent draws
Example of a solidonDraw()for curves:
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // Save Canvas state before modifying canvas.save(); // Set up paint for your curve Paint curvePaint = new Paint(); curvePaint.setColor(Color.parseColor("#2196F3")); curvePaint.setStrokeWidth(4f); curvePaint.setStyle(Paint.Style.STROKE); curvePaint.setAntiAlias(true); // Makes curves smoother // Define your curve path Path curvePath = new Path(); // Example: Quad curve (adjust coordinates to match your data) curvePath.moveTo(30f, getHeight() / 2); curvePath.quadTo(getWidth() / 2, getHeight() - 50f, getWidth() - 30f, getHeight() / 2); // Draw the curve canvas.drawPath(curvePath, curvePaint); // Restore Canvas state canvas.restore(); }- Always call
Your View has zero size (forgot
onMeasure())
If your custom View useswrap_content, you need to overrideonMeasure()to define its default size—otherwise, it might collapse to 0x0 pixels, so your curve is drawn but invisible. Here's a simple implementation:@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // Set default size (adjust these values to fit your needs) int defaultWidth = dpToPx(400); int defaultHeight = dpToPx(250); // Calculate final dimensions based on parent constraints int measuredWidth = measureDimension(defaultWidth, widthMeasureSpec); int measuredHeight = measureDimension(defaultHeight, heightMeasureSpec); setMeasuredDimension(measuredWidth, measuredHeight); } // Helper to convert dp to pixels private int dpToPx(int dp) { return (int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics() ); } // Helper to resolve measure specs private int measureDimension(int defaultSize, int measureSpec) { int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); if (specMode == MeasureSpec.EXACTLY) { return specSize; // Parent gave exact size, use it } else if (specMode == MeasureSpec.AT_MOST) { return Math.min(defaultSize, specSize); // Don't exceed parent's max size } else { return defaultSize; // Use default size for UNSPECIFIED mode } }Your curve is being covered by another View
Double-check your layout hierarchy—if another View is placed on top of your custom View, it'll block the curve. Test this by setting a temporary background color on your custom View:yourCustomCurveView.setBackgroundColor(Color.LTGRAY);If you can see the gray background but not the curve, the issue is in your
onDraw()logic. If you can't see the background at all, your View is either hidden or positioned incorrectly.You're calling
invalidate()before updating your curve data
Make sure you first update the data that defines your curve, then callinvalidate(). For example:// Public method to update curve data public void setCurvePoints(List<PointF> newPoints) { this.curvePoints = new ArrayList<>(newPoints); invalidate(); // Refresh after data is updated }
Give these fixes a try—start with checking the UI thread and View size first, since those are the most common gotchas for new custom View developers.
内容的提问来源于stack exchange,提问作者Marc Karam




