计算器应用绘制矩形问题求助:输入值关联尺寸及布局颜色消失
Hey there! Let's dig into why your light blue LinearLayout loses its color when you tap the "Draw NOW" button. The main issue here is almost certainly how you're handling the drawing process—if you're directly drawing on the LinearLayout without preserving its background, the default drawing pipeline wipes out the background color when you trigger a redraw.
Let's walk through two solutions, starting with the most recommended approach:
方案1:使用自定义View(更规范可控)
LinearLayout is a container designed to hold other views, not for custom drawing. A better practice is to create a dedicated custom View that handles both the background and your rectangle rendering. Here's how to implement it:
Step 1: Create the CustomDrawView class
public class CustomDrawView extends View { private Paint rectPaint; private float sideLength = 0; private final int lightBlueBg = Color.parseColor("#ADD8E6"); public CustomDrawView(Context context) { super(context); init(); } public CustomDrawView(Context context, AttributeSet attrs) { super(context, attrs); init(); } private void init() { // Set up paint for the rectangle rectPaint = new Paint(); rectPaint.setColor(Color.BLACK); rectPaint.setStyle(Paint.Style.STROKE); // Switch to FILL if you want a solid rectangle rectPaint.setStrokeWidth(2); // Set the light blue background setBackgroundColor(lightBlueBg); } public void updateRectSide(float inputNumber) { this.sideLength = inputNumber * 10; // Multiply by 10 as required invalidate(); // Trigger a redraw to show the new rectangle } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // This ensures the background color is drawn first if (sideLength > 0) { // Draw rectangle starting at (50,50) — adjust position as needed canvas.drawRect(50, 50, 50 + sideLength, 50 + sideLength, rectPaint); } } }
Step 2: Update your layout XML
Replace your existing LinearLayout with this custom view:
<com.yourpackage.name.CustomDrawView android:id="@+id/draw_area" android:layout_width="match_parent" android:layout_height="300dp" android:layout_below="@id/calculator_container"/>
Step 3: Hook up the button in MainActivity
public class MainActivity extends AppCompatActivity { private CustomDrawView drawArea; private EditText firstInputField; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); drawArea = findViewById(R.id.draw_area); firstInputField = findViewById(R.id.first_input); Button drawButton = findViewById(R.id.draw_now_button); drawButton.setOnClickListener(v -> { String inputText = firstInputField.getText().toString(); if (!inputText.isEmpty()) { try { float firstNumber = Float.parseFloat(inputText); drawArea.updateRectSide(firstNumber); } catch (NumberFormatException e) { Toast.makeText(this, "Please enter a valid number!", Toast.LENGTH_SHORT).show(); } } }); } }
方案2:修复原LinearLayout的绘制(不推荐,但如果必须用)
If you really want to stick with LinearLayout, you need to force it to draw its background before your rectangle. Here's how:
Step 1: Create a custom LinearLayout subclass
public class DrawableLinearLayout extends LinearLayout { private Paint rectPaint; private float sideLength = 0; public DrawableLinearLayout(Context context) { super(context); init(); } public DrawableLinearLayout(Context context, AttributeSet attrs) { super(context, attrs); init(); } private void init() { rectPaint = new Paint(); rectPaint.setColor(Color.BLACK); rectPaint.setStrokeWidth(2); rectPaint.setStyle(Paint.Style.STROKE); setWillNotDraw(false); // Tell the ViewGroup to trigger onDraw() setBackgroundColor(Color.parseColor("#ADD8E6")); } public void setRectSide(float inputNumber) { this.sideLength = inputNumber * 10; invalidate(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // Draw the background first if (sideLength > 0) { canvas.drawRect(50, 50, 50 + sideLength, 50 + sideLength, rectPaint); } } }
Then update your layout to use DrawableLinearLayout instead of the standard LinearLayout, and adjust your MainActivity code to reference this class (similar to方案1).
Why your original code broke the background
Chances are you were either:
- Overriding
onDraw()without callingsuper.onDraw(canvas), which skips rendering the background color. - Or not setting
setWillNotDraw(false)on the LinearLayout—ViewGroup subclasses don't callonDraw()by default, so your custom drawing code wasn't even running, and some other logic was clearing the background.
Either way, using a dedicated custom View is the cleaner, more maintainable approach for custom shape drawing.
内容的提问来源于stack exchange,提问作者Huntix

