I am using the following list layout for items that have associated comments. The number of comments are indicated by the box on the right side.
You hadn't posted any code relating to the adapter itself, but I found your previous question and you are most of the way there.
In bindView()
, let's modify your comments_count
TextView to save the index of the current row in the tag (for your itemUri
) and add a simple OnClickListener:
public void bindView(View view, Context context, Cursor cursor) {
ViewHolder holder = (ViewHolder)view.getTag();
if (holder == null) {
...
holder.comments_count.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// Get the position from the ViewHolder
long id = (Long) v.getTag();
Toast.makeText(v.getContext(), "Comment Click: " + id, Toast.LENGTH_SHORT).show();
}
});
}
...
holder.comments_count.setTag(cursor.getLong(0));
}
When the user clicks on the row it will still call onListItemClick()
, except if they click on the comments box. The comments box fires the OnClickListener above where you can direct the user to your CommentsActivity
. You didn't mention where you fetch the different values for itemUri
but I assumed you need the row's id to get it.
In your previous question, I noticed that you are making some repetitive calls and that Thiago Moreira Rocha's layout was extremely complex to be used repeatedly (for every ListView row.) So I propose a different approach. I've divided my answer into parts relating to the adapter, row layout, and colors for comments_count
:
The Adapter
I'll post the code in full and then explain at the bottom:
public class CustomCursorAdapter extends CursorAdapter {
private LayoutInflater mInflater;
private int[] mFrom;
private OnClickListener commentClick = new OnClickListener() {
@Override
public void onClick(View v) {
// Get the position saved in bindView()
long id = (Long) v.getTag();
Toast.makeText(v.getContext(), "Comment Click: " + id, Toast.LENGTH_SHORT).show();
}
};
public CustomCursorAdapter(Context context, Cursor cursor, int flags) {
super(context, cursor, flags);
mInflater = LayoutInflater.from(context);
}
private void applyColorFilter(Drawable drawable, int count) {
drawable.clearColorFilter();
if (count > 0) {
float saturation = (count * 15) / 100f;
// The value gets pinned if out of range.
int color = Color.HSVToColor(new float[] {110f, saturation, 1f});
drawable.setColorFilter(color, Mode.SRC);
}
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
ViewHolder holder = (ViewHolder) view.getTag();
holder.title.setText(cursor.getString(mFrom[0]));
holder.description.setText(cursor.getString(mFrom[1]));
// Get comments_count and set it as text
int count = cursor.getInt(mFrom[2]);
holder.comments_count.setText(count + "");
holder.comments_count.setTag(cursor.getLong(0));
// Adjust the color by saturation
applyColorFilter(holder.comments_color, count);
// Alternate method, that I explain in the answer
// Note: set the solid color in color.xml to #2aff00
//holder.comments_color.setAlpha(count * 45);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
View view = mInflater.inflate(R.layout.list_item, parent, false);
ViewHolder holder = new ViewHolder();
holder.title = (TextView)view.findViewById(R.id.title);
holder.description = (TextView)view.findViewById(R.id.description);
holder.comments_count = (TextView)view.findViewById(R.id.comments_count);
holder.comments_count.setOnClickListener(commentClick);
holder.comments_color = ((LayerDrawable) holder.comments_count.getBackground()).findDrawableByLayerId(R.id.color);
view.setTag(holder);
return view;
}
@Override
public Cursor swapCursor(Cursor newCursor) {
if(mFrom == null && newCursor != null) {
mFrom = new int[] {newCursor.getColumnIndex(TITLE), newCursor.getColumnIndex(DESCRIPTION), newCursor.getColumnIndex(COMMENTS_COUNT)};
}
return super.swapCursor(newCursor);
}
private class ViewHolder {
TextView title;
TextView description;
TextView comments_count;
Drawable comments_color;
}
}
I made a few changes:
mFrom
holds the indices of the columns that you are using. You only need to get the column index once, it won't change unless you change the CursorcommentsClick
is one generic OnClickListener that I use for every row and I set it while creating a ViewHolder
applyColorFilter()
ViewHolder
into newView()
rather than checking for a null
one in bindView()
The Row Layout
You probably noticed that I change the comments' color a little differently, that is because I use a simpler row layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="10dp" >
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_toLeftOf="@+id/comments_count"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="@+id/description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@+id/title"
android:layout_toLeftOf="@+id/comments_count"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:id="@+id/comments_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="15dp"
android:background="@drawable/comments_layers"
android:textAppearance="?android:attr/textAppearanceLarge" />
</RelativeLayout>
(While Thiago Moreira Rocha's layout works, the nested ViewGroups seem like overkill. Anytime you have a ViewGroup with only one child, their is usually an alternative.)
I use a LayerDrawable to replace the two LinearLayouts, that I will explain in in steps. First, the border (border.xml
), very similar to the previous one:
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<corners android:radius="10dp" />
<padding android:bottom="2dp" android:left="2dp" android:right="2dp" android:top="2dp" />
<solid android:color="#ffffff" />
<stroke android:width="2dp"
android:color="#000000" />
</shape>
(Notice the padding is the width of the stroke.)
Second, the adjustable background color (color.xml
):
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<corners android:radius="10dp" />
<padding android:bottom="10dp" android:left="10dp" android:right="10dp" android:top="10dp" />
<solid android:color="#ffffff" />
</shape>
Last, I created a LayerDrawable to combine the two images (comments_layers.xml
):
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+id/border"
android:drawable="@drawable/border" />
<item
android:id="@+id/color"
android:drawable="@drawable/color" />
</layer-list>
(Optional)
You adjust the saturation of your HSV value in applyColorFilter()
, but it seems that this is the equivalent to adjusting the alpha of a green background. If this is true, the changing the alpha value is a much simpler task. Find my comments in bindView()
:
applyColorFilter(holder.comments_color, count);
holder.comments_color.setAlpha(count * 45);
color.xml
file and change the color
attribute of the solid
element from #ffffff
to #2aff00
In all truth I had never used LayerDrawables like this before, there may be a faster way, but I think this is pretty slick.