Home > Software engineering >  How to add XML layout to custom view?
How to add XML layout to custom view?

Time:02-20

I have a custom view like this:

enter image description here

class SquareView : View {

    private lateinit var mRectanglePaint: Paint


    constructor(context: Context?) : super(context) {
        init(null)
    }

    constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) {
        init(attrs)
    }

    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
        context,
        attrs,
        defStyleAttr
    ) {
        init(attrs)
    }

    constructor(
        context: Context?,
        attrs: AttributeSet?,
        defStyleAttr: Int,
        defStyleRes: Int
    ) : super(context, attrs, defStyleAttr, defStyleRes) {
        init(attrs)
    }

    private fun init(attrs: AttributeSet?) {

        mRectanglePaint = Paint().apply {
            isAntiAlias = true
            color = Color.RED
        }

    }


    override fun onDraw(canvas: Canvas) {
        canvas.apply {
            drawRectangle(this)
        }
    }

    private fun drawRectangle(canvas: Canvas) {
        val rect = Rect()
        rect.left = 100
        rect.right = rect.left   100
        rect.top = 100
        rect.bottom = rect.top   100

        canvas.drawRect(rect, mRectanglePaint)
    }

}

And, this is my blue_square.xml file:

enter image description here

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:orientation="vertical"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_height="wrap_content">

    <View
        android:id="@ id/blue_square"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="#0000FF" />

</LinearLayout>

I want to add this XML layout to my view and set position to bottom of the red square.

I added this code but this time only the blue square appears.

val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
val view = inflater.inflate(R.layout.blue_square, this, true)

I want to include the blue square in my custom view and change its position.

How can I do that? Thank you for your help.

CodePudding user response:

When I said 2 different approaches, so the first is in a bit more detail but I'll also outline the others.

1)The first is to inflate and layout the xml to a Bitmap and then draw that Bitmap to you Canvas in the right place.

Inflate your xml BUT don't attach it or parent it to your custom view (as that really replaces you custom view (second and third parameters of inflate)

e.g.

val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
val xmlView = inflater.inflate(R.layout.blue_square, null, false)

Draw this new view to Bitmap

Sorry this is Java but you can convert it to Kotlin as you seem to be using that.

Canvas bitmapCanvas = new Canvas();
Bitmap bitmap = Bitmap.createBitmap(xmlView.getWidth(), xmlView.getHeight(), Bitmap.Config.ARGB_8888);

bitmapCanvas.setBitmap(bitmap);
xmlView.draw(bitmapCanvas);

Then in your onDraw draw this Bitmap to your canvas in the right position (setting top and left location to be below your red square)

Something like

plainPaint = Paint().apply { isAntiAlias = true }
canvas.drawBitmap (bitmap, left, top, plainPaint)

Note this is not exactly tested but it is similar to something I do a lot.

2)Don't invert the normal hierarchy of Views and ViewGroups, don't make your SquareView custom View be the single view your an App draws. Your SquareView custom view should just draw a view big enough to be the square (You should implement onMeasure for your custom view).

Then an App could do in it's xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:orientation="vertical"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_height="wrap_content">

    <SquareView
        android:id="@ id/custom_square"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <View
        android:id="@ id/blue_square"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="#0000FF" />

</LinearLayout>

  • Related