Search code examples
javaandroidviewandroid-custom-view

Method to swap colors of custom rectangle view does not work


I'm following a tutorial about custom views and I'm coding along with the instructor, but my method to swap colors of my custom view doesn't work.

Here's my xml layout:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="20dp"
    tools:context=".MainActivity">


    <com.laila.android.customviews.views.CustomRectangle
        android:id="@+id/my_custom_rectangle"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

    </com.laila.android.customviews.views.CustomRectangle>

    <Button
        android:id="@+id/btn_swap"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="Swap color"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

Here's my custom view class:

public class CustomRectangle extends View {

    private static final int SQUARE_SIZE = 200;
    private Rect myRect;
    private Paint rectPaint;

    public CustomRectangle(Context context) {
        super(context);

        init(null);
    }

    public CustomRectangle(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);

        init(attrs);
    }

    public CustomRectangle(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        init(attrs);
    }

    public CustomRectangle(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);

        init(attrs);
    }

    // Initialization method
    private void init(AttributeSet attrs) {

        myRect = new Rect();
        rectPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    }

    public void swapColor() {

        // Reminder: ternary conditional operator -> ?
        // boolean statement ? true result : false result;

        rectPaint.setColor(rectPaint.getColor() == Color.GREEN ? Color.RED : Color.GREEN);

        postInvalidate();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        myRect.left = 50;
        myRect.top = 50;
        myRect.right = myRect.left + SQUARE_SIZE;
        myRect.bottom = myRect.top + SQUARE_SIZE;

        rectPaint.setColor(Color.GREEN);

        canvas.drawRect(myRect, rectPaint);

    }
}

Here's my main activity:

public class MainActivity extends AppCompatActivity {

    private CustomRectangle customRectangle;
    private Button buttonSwap;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        customRectangle = findViewById(R.id.my_custom_rectangle);
        buttonSwap = findViewById(R.id.btn_swap);

        buttonSwap.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                customRectangle.swapColor();
            }
        });
    }
}

Here's what the application looks like:

enter image description here

But when I click the swap button, nothing happens. Why? What did I forget or what am I doing wrong?

Thank you.


Solution

  • I figured it out. I was calling rectPaint.setColor(Color.GREEN) inside the onDraw method, so every time the canvas was redrawn, the color was set to green.

    All I had to do was put rectPaint.setColor(Color.GREEN) inside my init method instead, like so:

        private void init(AttributeSet attrs) {
    
            myRect = new Rect();
            rectPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    
            rectPaint.setColor(Color.GREEN);
        }
    

    Now the swap colors method works.