I am trying to dynamically create and place a View which starts below an icon within a custom 'RecordView', and above the same icon of another 'RecordView' which is just below it using a a ConstraintLayout. The id's of the icons I have confirmed are unique but it seems the constraint doesn't work when connecting to a view inside a custom view.
Any ideas for either fixing this approach or using a different layout to achieve the following expected result and draw the same in between other RecordViews similarly: Desired view
Here's the code for creating the line dynamically and attempting to constrain against the icons int the first and second RecordViews. It seems that it can only make the constraint against the entire custom view but not against views within them. If ConstraintLayout's don't cater for this, is there any alternatives as I can't seem to find any.
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val mainLayout: ConstraintLayout = view.findViewById(R.id.fragmentLayout)
val record1View: RecordView = view.findViewById(R.id.record1)
val record2View: RecordView = view.findViewById(R.id.record2)
val lineView = CanvasLineView(context).apply {
id = View.generateViewId()
layoutParams = ConstraintLayout.LayoutParams(20.dpToPx(), ConstraintLayout.LayoutParams.MATCH_CONSTRAINT)
setBackgroundColor(Color.CYAN)
}
mainLayout.addView(lineView)
val constraintSet = ConstraintSet()
constraintSet.clone(mainLayout)
constraintSet.connect(
lineView.id, ConstraintSet.START,
record1View.icon.id, ConstraintSet.START,
0
)
constraintSet.connect(
lineView.id, ConstraintSet.TOP,
record1View.icon.id, ConstraintSet.BOTTOM,
0
)
constraintSet.connect(
lineView.id, ConstraintSet.BOTTOM,
record2View.icon.id, ConstraintSet.BOTTOM,
0
)
constraintSet.applyTo(mainLayout)
}
Here's the layout for the record_view
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:id="@+id/recordlayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:background="@drawable/border">
<LinearLayout
android:id="@+id/recordLinearlayout"
android:orientation="vertical"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="center_vertical"
android:layout_marginStart="8dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/title"
android:textStyle="bold"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Title" />
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1" />
<ImageView
android:id="@+id/icon"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="end"
android:src="@android:drawable/ic_menu_add" />
</LinearLayout>
<TextView
android:id="@+id/content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Content" />
</LinearLayout>
</LinearLayout>
and the code behind
class RecordView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : LinearLayout(context, attrs, defStyleAttr) {
val icon: ImageView
private val title: TextView
private val content: TextView
init {
inflate(context, R.layout.record_view, this)
icon = findViewById(R.id.icon)
title = findViewById(R.id.title)
content = findViewById(R.id.content)
val typedArray = context.obtainStyledAttributes(attrs, R.styleable.Record)
val recordTitle = typedArray.getString(R.styleable.Record_recordTitle)
val recordContent = typedArray.getString(R.styleable.Record_recordContent)
val iconId = typedArray.getResourceId(R.styleable.Record_recordIconId, -1)
if (iconId != -1) {
icon.id = iconId
}
typedArray.recycle()
// Set the title and content from attributes
title.text = recordTitle
content.text = recordContent
}
}
and here's the main 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"
android:id="@+id/fragmentLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.example.constrainviewinsideotherviews.RecordView
android:id="@+id/record1"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:recordTitle="Record 1"
app:recordIconId="@+id/record1_icon"
app:recordContent="This is the first record"
app:layout_constraintStart_toStartOf="parent"
android:paddingBottom="2dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<com.example.constrainviewinsideotherviews.RecordView
android:id="@+id/record2"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:recordTitle="Record 2"
app:recordIconId="@+id/record2_icon"
app:recordContent="This is the second record.\nIt will\ntake up\nquite\a few\nlines"
android:paddingBottom="2dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/record1"/>
<com.example.constrainviewinsideotherviews.RecordView
android:id="@+id/record3"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:recordTitle="Record 3"
app:recordIconId="@+id/record3_icon"
android:paddingBottom="2dp"
app:recordContent="This is the third record"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/record2"/>
<com.example.constrainviewinsideotherviews.RecordView
android:id="@+id/record4"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:recordTitle="Record 3"
app:recordIconId="@+id/record4_icon"
android:paddingBottom="2dp"
app:recordContent="This is the fourth record"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/record3"/>
</androidx.constraintlayout.widget.ConstraintLayout>