Search code examples
androidandroid-layoutandroid-linearlayoutandroid-relativelayout

How to draw custom view decorations other way than with XML layouts?


Below is a drawing that I created using the code beneath that. However I intend to use it multiple times with a layout file. Does anyone know what the best way would be in order to remove the linear layouts whilst retaining the same appearance of this drawing and keeping the number of views used to a minimum?

The main benefit of using the linear layout was the fact that layout weights could be used to space the rectangles out evenly but unfortunately when the linear layouts are removed and one has to reply on the relative layout, equal spacing doesn't appear to be possible without using the dp unit of measurement (with is NOT what I want especially considering the fact that Android screens come in all different sizes).

enter image description here

    <RelativeLayout
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:background="#808080" >
        <include
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:layout_gravity="center"
            layout="@layout/textview_carriage2"/>
        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="10dp"
            android:layout_alignParentTop="true"
            android:orientation="horizontal"
            android:weightSum="100"
            android:baselineAligned="false" >

            <include
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="20"
                layout="@layout/view_emptyrect_red"/>

            <include
                android:layout_width="1dp"
                android:layout_height="match_parent"
                android:layout_weight="7"
                layout="@layout/view_spacebetweenwindows"/>

            <include
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="20"
                layout="@layout/view_emptyrect_red"/>

            <include
                android:layout_width="1dp"
                android:layout_height="match_parent"
                android:layout_weight="6"
                layout="@layout/view_spacebetweenwindows"/>

            <include
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="20"
                layout="@layout/view_emptyrect_red"/>

            <include
                android:layout_width="1dp"
                android:layout_height="match_parent"
                android:layout_weight="7"
                layout="@layout/view_spacebetweenwindows"/>

            <include
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="20"
                layout="@layout/view_emptyrect_red"/>
        </LinearLayout>

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="10dp"
            android:layout_alignParentBottom="true"
            android:orientation="horizontal"
            android:weightSum="100"
            android:baselineAligned="false" >

            <include
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="20"
                layout="@layout/view_emptyrect_red"/>

            <include
                android:layout_width="1dp"
                android:layout_height="match_parent"
                android:layout_weight="7"
                layout="@layout/view_spacebetweenwindows"/>

            <include
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="20"
                layout="@layout/view_emptyrect_red"/>

            <include
                android:layout_width="1dp"
                android:layout_height="match_parent"
                android:layout_weight="6"
                layout="@layout/view_spacebetweenwindows"/>

            <include
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="20"
                layout="@layout/view_emptyrect_red"/>

            <include
                android:layout_width="1dp"
                android:layout_height="match_parent"
                android:layout_weight="7"
                layout="@layout/view_spacebetweenwindows"/>

            <include
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="20"
                layout="@layout/view_emptyrect_red"/>
        </LinearLayout>
    </RelativeLayout>

Solution

  • Using XML layouts is overkill solution for simple decoration like this. Instead extend TextView (or other View if you like) and override onDraw() method.

    Create field paint and initialize it in init() method that you call from all constructors:

    Paint paint;
    
    private void init() {
        paint = new Paint();
        paint.setColor(Color.RED);
        paint.setStrokeWidth(4); // convert to dp?
        paint.setStyle(Paint.Style.STROKE); // delete line for filled rect
    }
    

    The onDraw() method should look like this: (customize!)

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
    
        int w = canvas.getWidth();
        int h = canvas.getHeight();
    
        int rectWidth = w/5;
        int space = w/15;
        int topRectHeight = getPaddingTop();
        int bottomRectHeight = getPaddingBottom();
    
        for (int i = 0; i < 4; i++) {
            int left = i * (rectWidth + space);
            int right = left + rectWidth;
    
            Rect rect = new Rect(left, 0, right, topRectHeight);
            canvas.drawRect(rect, paint);
    
            Rect rect2 = new Rect(left, h - bottomRectHeight, right, h);
            canvas.drawRect(rect2, paint);
        }
    }
    

    This will draw rectangles in the padding areas. Note that width should be specified either by match_parent, weight or fixed value in dp.

    Then just place the view in XML

    <your.package.RectangleTextView 
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingTop="10dp"
        android:paddingBottom="10dp"
        android:text="2"
        android:gravity="center" />