I have a custom view like this:
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:
<?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>