Reputation: 2051
I would like to inset a RecyclerView ItemDecorator divider to left align with a TextView (the item title) inside the list element that is constrained to be 72dp from the parent left side. Something like we see here in the Google Material Design Docs. I assume that I need to somehow reference the layout params on the titleTextView, but am not sure how to do that from my ItemDecorator code, as I seem to be able to only get the params which is the ConstraintLayout, and not the textview itself. Any help or pointers in the right direction would be greatly appreciated! The relevant ItemDecorator code, where I try to get the textView param looks something like this:
for (int i = 0; i < recyclerView.getChildCount() - 1; ++i) {
View child = recyclerView.getChildAt(i);
RecyclerView.LayoutParams params =(RecyclerView.LayoutParams) child.getLayoutParams();
//this just gives me the constraint layout, not the TextView params, how to reference the textViewParams!?
The RecyclerView looks like this:
<android.support.v7.widget.RecyclerView
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/myList"
android:name="com.example.Something"
android:layout_width="0dp"
android:layout_height="0dp"
app:layoutManager="LinearLayoutManager"
tools:context=".controllers.fragments.ExampleFragment"
tools:listitem="@layout/fragment_something"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
The list item xml is a constraint layout with some TextViews, and the relevant portion looks like this:
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="72dp">
<ImageView
android:id="@+id/myImageView"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_marginLeft="16dp"
app:layout_constraintLeft_toLeftOf="parent"
tools:src="@drawable/ic_menu_manage"
android:src="@drawable/ic_menu_manage"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="16dp"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginBottom="16dp" />
<TextView
android:id="@+id/titleTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="4dp"
android:layout_marginLeft="72dp"
android:layout_marginTop="20dp"
android:text="MyTitle"
android:textAppearance="@style/TextAppearance.AppCompat.Subhead"
android:textStyle="bold"
app:layout_constraintBottom_toTopOf="@+id/textView5"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="SampleTitle" />
...
</android.support.constraint.ConstraintLayout>
Upvotes: 0
Views: 1323
Reputation: 1242
Since you already know by how much you have to inset the divider from the left side (calculate it from your layout if you don't know), all you need to do is convert that dp value to px as shown here and set it as the left bound in your custom ItemDecoration
.
public class InsetDividerDecoration extends RecyclerView.ItemDecoration {
private final int insetValueInDp = 72; // in your case
@Override
public void onDraw(Canvas canvas, RecyclerView parent, RecyclerView.State state) {
int dividerLeft = (int) (insetValueInDp * Resources.getSystem().getDisplayMetrics().density);
...
}
}
And use it in your recycler view -
recyclerView.addItemDecoration(new InsetDividerDecoration());
Upvotes: 0
Reputation: 2051
Since the ConstraintLayout is a ViewGroup, it is possible to access the child of the ConstraintLayout from inside of the ItemDecorator by simply doing something like:
public class MyItemDivider extends RecyclerView.ItemDecoration {
....some code here
@Override
public void onDrawOver(Canvas canvas, RecyclerView recyclerView,
RecyclerView.State state) {
super.onDrawOver(canvas, recyclerView, state);
for (int i = 0; i < recyclerView.getChildCount() - 1; ++i) {
ViewGroup item = (ViewGroup) recyclerView.getChildAt(i);
//for now the titleText is at index 1 of constraint layout
TextView titleChild = (TextView) item.getChildAt(1);
int titleTextLeftMargin = titleChild.getLeft();
//this would probably be less brittle
//but I would need to somehow change the context for this to be doable?
//View titleChild = item.findViewById(R.id.contractListProductNameTextView);
...some more code here
divider.setBounds(titleTextLeftMargin, top, right, bottom);
divider.draw(canvas);
}
}
}
Upvotes: 0
Reputation: 21
use a custom item decorator.
class CustomItemDecoration(context: Context) : RecyclerView.ItemDecoration()
{
private val mDivider: Drawable = context.resources.getDrawable(R.drawable.custom_item_divider) // this is a shape that i want to use
override fun onDrawOver(c: Canvas,
parent: RecyclerView,
state: RecyclerView.State)
{
val left = parent.paddingLeft // change to how much padding u want to add here .
val right = parent.width - parent.paddingRight
val childCount = parent.childCount
for (i in 0 until childCount)
{
val child = parent.getChildAt(i)
val params = child.layoutParams as RecyclerView.LayoutParams
val top = child.bottom + params.bottomMargin
val bottom = top + mDivider.intrinsicHeight
mDivider.setBounds(left, top, right, bottom)
mDivider.draw(c)
}
}
}
you set it like that
recyclerView.addItemDecoration(CustomItemDecoration(context))
Upvotes: 2