Search code examples
androidandroid-custom-view

Custom component not rendering properly anymore


I'm new to creating custom components on android and it was a fun, annoying, and very educational experience. I was able to make my quite complex custom component and I'm very happy with it. But after I moved it to a directory and out of it, it doesn't display anything anymore.

My project consist of a lot of fragments and my custom component is used on one of them. So when I moved all those fragments in a directory, AS told me that someone can't find something on my custom component class. So I included the custom component class inside the fragments directory. Everything worked fine but when I tried to use the custom view on a different layout which is not a fragment's, the custom component doesn't display anything. I made every variable of the custom view class to public then moved it outside the fragments folder. Now, it doesn't display anything anymore. Please point out what I've done wrong.

This is custom component class.

public class CheckOutItem extends ConstraintLayout {
    public Context ctx;
    public Paint mPaint;
    public Rect mRect;
    int mSquareColor;
    public ImageView imgThumbnail;
    public TextView lblAbbrev, lblFullName;
    public ConstraintLayout lytMain;

    public CheckOutItem(Context context) {
        super(context);
        ctx = context;
        init(null);
    }

    public CheckOutItem(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        LayoutInflater.from(context).inflate(R.layout.checkout_item, this);
        ctx = context;

        init(attrs);
    }

    public CheckOutItem(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        ctx = context;
        init(attrs);
    }

    private void init(@Nullable AttributeSet set){
        inflate(ctx, R.layout.checkout_item, this);
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mRect = new Rect();

        if(set == null){
            return;
        }

        TypedArray ta = getContext().obtainStyledAttributes(set, R.styleable.CheckOutItem);

        this.imgThumbnail = findViewById(R.id.imgItemThumbnail);
        this.lblAbbrev = findViewById(R.id.lblItemAbbrevName);
        this.lblFullName = findViewById(R.id.lblItemFullName);
        this.lytMain = findViewById(R.id.lytMain);

        this.lblAbbrev.setText(ta.getText(R.styleable.CheckOutItem_abbrevText));
        this.lblAbbrev.setTextSize(ta.getDimension(R.styleable.CheckOutItem_abbrevTextSize, 1f));
        this.lblAbbrev.setTextColor(ta.getColor(R.styleable.CheckOutItem_abbrevTextColor, Color.BLACK));

        this.lblFullName.setText(ta.getText(R.styleable.CheckOutItem_fullNameText));
        this.lblFullName.setTextSize(ta.getDimension(R.styleable.CheckOutItem_fullNameTextSize, 1f));
        this.lblFullName.setTextColor(ta.getColor(R.styleable.CheckOutItem_fullNameTextColor, Color.BLACK));
        this.lblFullName.setBackgroundColor(ta.getColor(R.styleable.CheckOutItem_fullNameBackgroundColor, Color.WHITE));

        this.lytMain.setBackgroundColor(ta.getColor(R.styleable.CheckOutItem_mainBackgroundColor, Color.LTGRAY));

        ta.recycle();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mRect.left = 0;
        mRect.right = getWidth();
        mRect.top = 0;
        mRect.bottom = getHeight();

        canvas.drawRect(mRect, mPaint);
    }
}

This is my layout.

<?xml version="1.0" encoding="utf-8"?>
<merge 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.support.constraint.ConstraintLayout
        android:id="@+id/lytMain"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/border_bg">

        <ImageView
            android:id="@+id/imgItemThumbnail"
            android:layout_width="match_parent"
            android:layout_height="70dp"
            android:layout_marginEnd="8dp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            tools:srcCompat="@tools:sample/avatars[9]"
            tools:visibility="gone" />

        <TextView
            android:id="@+id/lblItemAbbrevName"
            android:layout_width="0dp"
            android:layout_height="60dp"
            android:gravity="center"
            android:textSize="16sp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <TextView
            android:id="@+id/lblItemFullName"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_marginStart="1dp"
            android:layout_marginEnd="1dp"
            android:gravity="center"
            android:textAlignment="center"
            android:textSize="12sp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="1.0"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/lblItemAbbrevName"
            app:layout_constraintVertical_bias="0.0" />

    </android.support.constraint.ConstraintLayout>

</merge>

This is my attrs.xml.

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="CheckOutItem">
        <attr name="thumbnail" format="string"/>
        <attr name="abbrevText" format="string"/>
        <attr name="abbrevTextSize" format="dimension"/>
        <attr name="abbrevTextColor" format="color|reference"/>
        <attr name="fullNameText" format="string"/>
        <attr name="fullNameTextSize" format="dimension"/>
        <attr name="fullNameTextColor" format="color|reference"/>
        <attr name="textStyle">
            <enum name="normal" value="0"/>
            <enum name="bold" value="1"/>
            <enum name="italic" value="2"/>
        </attr>
        <attr name="fullNameBackgroundColor" format="color|reference"/>
        <attr name="mainBackgroundColor" format="color|reference"/>
    </declare-styleable>
</resources>

This is how I use it.

<com.example.android.projectname.CheckOutItem
        android:id="@+id/coi2"
        android:layout_width="102dp"
        android:layout_height="102dp"
        android:layout_margin="7.8dp"
        app:abbrevText="MP"
        app:abbrevTextColor="@color/black"
        app:abbrevTextSize="12sp"
        app:fullNameBackgroundColor="@color/colorAccent"
        app:fullNameText="Make Payment"
        app:fullNameTextColor="@color/white"
        app:fullNameTextSize="8sp"
        app:mainBackgroundColor="@color/transparent"
        app:thumbnail="" />

Solution

  • You are inflating your layout twice

    public CheckOutItem(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        LayoutInflater.from(context).inflate(R.layout.checkout_item, this);
        ...
    

    Remove the second inflate in init

    private void init(@Nullable AttributeSet set){
        // inflate(ctx, R.layout.checkout_item, this); // remove this line
        ...