I am new in this stuff so i hope its not a ridiculous question...
I have a list view, and all the items including a video, numOfLikes(textview), like and dislike (Buttons).
When I click on the like or dislike button, I try to change the background of the button, but it changes the background of all the like/dislike buttons in the list view.
The same happens when I am trying to enable the dislike button while I am clicking on the like button, it disables all the dislike buttons in the list.
Code :
public class FeedAdapter extends ArrayAdapter<Feed> {
Context context;
ArrayList<Feed> feedsList;
ArrayList<String> listOfItems;
Dialog dialog;
public FeedAdapter(Context context, int resource, ArrayList<Feed> feeds) {
super(context, resource, feeds);
this.context = context;
this.feedsList = feeds;
}
public FeedAdapter(Context context, ArrayList<Feed> feeds){
super(context, R.layout.feed_listitem, feeds);
this.context = context;
this.feedsList = feeds;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
final FeedHolder holder;
if(convertView == null){
convertView = LayoutInflater.from(context).inflate(R.layout.feed_listitem, parent, false);
holder = new FeedHolder();
holder.titleTextView = (TextView) convertView.findViewById(R.id.feed_title_textView);
holder.usernameTextView = (TextView) convertView.findViewById(R.id.feed_name_textview);
holder.likesTextView = (TextView) convertView.findViewById(R.id.feed_likes_textview);
holder.likeButton = (Button) convertView.findViewById(R.id.feed_like_button);
holder.unlikeButton = (Button) convertView.findViewById(R.id.feed_unlike_button);
holder.video = (VideoView) convertView.findViewById(R.id.feed_post_videoView);
holder.frameLayout = (FrameLayout) convertView.findViewById(R.id.feed_placeholder_framelayout);
holder.frameLayout.setTag(holder.video);
holder.likeButton.setTag(holder.unlikeButton);
holder.unlikeButton.setTag(holder.likeButton);
convertView.setTag(holder);
} else{
holder = (FeedHolder) convertView.getTag();
holder.frameLayout.setTag(holder.video);
holder.likeButton.setTag(holder.unlikeButton);
holder.unlikeButton.setTag(holder.likeButton);
}
holder.titleTextView.setText(feedsList.get(position).getTitle());
holder.usernameTextView.setText(feedsList.get(position).getUsername());
holder.likesTextView.setText(TrendliContract.showNumInNumK(feedsList.get(position).getLikesInLong()));
holder.titleTextView.setTypeface(TrendliContract.helvetica);
holder.usernameTextView.setTypeface(TrendliContract.helvetica);
holder.likesTextView.setTypeface(TrendliContract.helvetica);
holder.frameLayout.setBackground(feedsList.get(position).getDrawable());
holder.video.setVisibility(View.INVISIBLE);
holder.video.setMediaController(new MediaController(context));
holder.video.setVideoURI(Uri.parse(feedsList.get(position).getVideoImageGif()));
holder.video.setLayoutParams(new FrameLayout.LayoutParams(TrendliContract.screenW,
TrendliContract.screenW));
postImageViewOnClickListener(holder);
holder.likeButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Feed f = feedsList.get(position);
//Button b = ((Button) v.getTag());
if(f.isLikePressed() == false){
new TrendliContract.Like().execute(f);
f.setLikePressed(true);
int numOfLikes = Integer.parseInt(holder.likesTextView.getText().
toString().replace(" ", ""));
holder.likesTextView.setText(String.valueOf(++numOfLikes));
//v.setBackgroundColor(R.color.black);
//b.setEnabled(false);
} else{
new TrendliContract.UnLike().execute(f);
f.setLikePressed(false);
int numOfLikes = Integer.parseInt(holder.likesTextView.getText().
toString().replace(" ", ""));
holder.likesTextView.setText(String.valueOf(--numOfLikes));
//v.setBackgroundColor(R.color.transparent);
//b.setEnabled(true);
}
}
});
holder.unlikeButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Feed f = feedsList.get(position);
//Button b = ((Button) v.getTag());
if(f.isDislikePressed() == false){
new TrendliContract.DisLike().execute(f);
f.setDislikePressed(true);
int numOfLikes = Integer.parseInt(holder.likesTextView.getText().toString().replace(" ", ""));
holder.likesTextView.setText(String.valueOf(--numOfLikes));
//v.setBackgroundColor(R.color.black);
//b.setEnabled(false);
} else{
new TrendliContract.UnDisLike().execute(f);
f.setDislikePressed(false);
int numOfLikes = Integer.parseInt(holder.likesTextView.getText().toString().replace(" ", ""));
holder.likesTextView.setText(String.valueOf(++numOfLikes));
//v.setBackgroundColor(R.color.transparent);
//b.setEnabled(true);
}
}
});
convertView.setTag(holder);
return convertView;
}
private class FeedHolder{
TextView titleTextView;
TextView usernameTextView;
TextView likesTextView;
Button likeButton;
Button unlikeButton;
VideoView video;
FrameLayout frameLayout;
}
}
You must never change the properties of ListView item's view in the onClick event.
The reason is that the onClick event get called out of getView method in a different time and because of recycling system of ListView those affected properties will be applied to recycled views, so you get irrelevant results.
Instead you must store the properties in an array and then in the getView method use that array to apply properties to views...
In the Adapter class
boolean[] buttonState;
In the constructor:
buttonState = new boolean[feeds.size()];
In the onClick:
buttonState[position] = false; // or true...
In the getView:
holder.yourButton.setEnabled(buttonState[position]);
As a variant you can create custom button class extends Button and implements View.OnClickListener, then override it's onClick method to set background corresponding with the flag like mPressed. After that you can use this class for yours buttons. Here an example of custom button class:
public class CustomButton extends Button implements View.OnClickListener {
private boolean mPressed = false;
private static final int mRegularBackID = R.drawable.button_up;
private static final int mPressedBackID = R.drawable.button_down;
public CustomButton( Context context ) {
super( context );
}
public CustomButton( Context context, AttributeSet attrs ) {
super( context, attrs );
}
public CustomButton( Context context, AttributeSet attrs, int defStyle ) {
super( context, attrs, defStyle );
}
#Override
public void onClick( View view ) {
mPressed = !mPressed;
this.setBackgroundResource( mPressed ? mPressedBackID : mRegularBackID );
}
}
Instead of static drawable IDs with the flag (as in my example) you can also use drawable state list or constructor with corresponding drawables as additional parameters.
You can use this custom class in XML with full package name like
<my.own.project.package.CustomButton... />
View passed in onClick(View v) it's clicked Button object you can use it to change Button property.
public void onClick(View v) {
Button b = ((Button)v);
b.setEnabled(false);
}
You can setup background property of Button inside your xml layout. Even you can define drawable xml slector witch will define different background for different states like: pressed, focused, disabled, etc.
First you have to define selector xml and set it as Button background:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#color/selected" android:state_pressed="true"/>
<item android:drawable="#color/selected" android:state_selected="true"/>
<item android:drawable="#android:color/transparent"/>
</selector>
Instead of colors you can use drawable resources (images or shapes). Also you can define different states in this list. First element in selector witch match current satte will be used.
Try --
likeButton.setBackgroundColor(R.color.transparent);
unlikeButton.setEnabled(false);
Related
I'm using this library for spinner. I want to change the color of already selected items from the list in the spinner. How can I do it? This is how I'm populating the data onclick of the spinner:
spinner1.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
Cursor crs = database.rawQuery("SELECT * FROM "+ ItemsTable.TABLE_ZONE +" WHERE "+ ItemsTable.COLUMN_ZONE_ID +"<>"+ zone_id1
+" AND "+ ItemsTable.COLUMN_ZONE_ID +"<>"+ zone_id2 +" AND "+ ItemsTable.COLUMN_ZONE_ID +"<>"+ zone_id3 +"", null);
Integer[crs.getCount()];
List<Zone> listOfZones = new ArrayList<Zone>();
while(crs.moveToNext())
{
String title = crs.getString(crs.getColumnIndex("title"));
Integer title_id = crs.getInt(crs.getColumnIndex("id"));
listOfZones.add(new Zone(title_id, title));
}
crs.close();
ArrayAdapter<Zone> zoneadapter = new ArrayAdapter<Zone>(getActivity(),
android.R.layout.simple_dropdown_item_1line, listOfZones);
spinner1.setAdapter(zoneadapter);
}
return false;
}
});
In the code above I'm removing the items from the list which are already selected but I want to change the background color of the items already selected.
You can give background color by creating xml file for spinner layout. Follow below steps.
1) You need to create one xml file under layout folder.
2) Create layout which includes one TextView which show item names.
3) Give background color to main rootview layout. For example android:background="#color/anycolor".
And bind this layout in spinner adapter.
Here is custom adapter:
public class CustomAdapter extends BaseAdapter {
Context context;
List<Zone> listOfZones;
LayoutInflater inflter;
public CustomAdapter(Context applicationContext, List<Zone> listOfZones) {
this.context = applicationContext;
this.listOfZones = listOfZones;
inflter = (LayoutInflater.from(applicationContext));
}
#Override
public int getCount() {
return flags.length;
}
#Override
public Object getItem(int i) {
return null;
}
#Override
public long getItemId(int i) {
return 0;
}
#Override
public View getView(int i, View view, ViewGroup viewGroup) {
view = inflter.inflate(R.layout.your_layout_name, null);
TextView names = (TextView) view.findViewById(R.id.textView);
names.setText(listOfZones.get(i).yourObjectName);
return view;
}}
And bind this to spinner like this:
CustomAdapter customAdapter=new CustomAdapter(getApplicationContext(),listOfZones);
your_spinner.setAdapter(customAdapter);
My ListView item consists of the following components - TextView and then under it there are two ImageViews - like and dislike.
So when I click on either like or dislike I want to be able to change the like or dislike ImageView from grey to blue.
At the moment when I click on like the like ImageView does change from grey to blue. But not only for the corresponding ListView item but for every 3rd item in the list - so if I have 10 items in my list and I click on the like of the first item in the list then 4th, 7th and 10th items like ImageView change from grey to blue.
In my post_list_item.xml in the root element of the file I specified the following android:descendantFocusability="blocksDescendants" but it doesn't help either.
My question is - what do I have to do so that when I click on either like or dislike I would be able to change the like or dislike ImageView from grey to blue without affecting other list items?
Here is my code of the CursorAdapter
public class PostCursorAdapter extends CursorAdapter {
public PostCursorAdapter(Context context, Cursor c, int flags) {
super(context, c, flags);
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return LayoutInflater.from(context).inflate(R.layout.post_list_item, parent, false);
}
#Override
public void bindView(View view, final Context context, Cursor cursor) {
String post = cursor.getString(cursor.getColumnIndex(DBOpenHelper.POST));
final String liked = cursor.getString(cursor.getColumnIndex(DBOpenHelper.LIKED));
String disliked = cursor.getString(cursor.getColumnIndex(DBOpenHelper.DISLIKED));
final String post_id = cursor.getString(cursor.getColumnIndex(DBOpenHelper.POST_ID));
String userliked = cursor.getString(cursor.getColumnIndex(DBOpenHelper.USER_LIKED));
TextView tvPost = (TextView) view.findViewById(R.id.tvPost );
tvJoke.setText(post);
TextView tvLikeCount = (TextView) view.findViewById(R.id.tvLikeCount);
tvLikeCount.setText(liked);
TextView tvDislikesCount = (TextView) view.findViewById(R.id.tvDislikeCount);
tvDislikesCount.setText(disliked);
final ImageView ivLike = (ImageView) view.findViewById(R.id.ivLike);
// has the user liked it?
int check = Integer.parseInt(userliked);
if(check == 1){
String uri = "#drawable/like_blue"; // where myresource (without the extension) is the file
int imageResource = context.getResources().getIdentifier(uri, null, context.getPackageName());
Drawable res = context.getResources().getDrawable(imageResource);
ivLike.setImageDrawable(res);
}
ivLike.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String uri = "#drawable/like_blue";
int imageResource = context.getResources().getIdentifier(uri, null, context.getPackageName());
Drawable res = context.getResources().getDrawable(imageResource);
ivLike.setImageDrawable(res);
}
});
}
}
You can use state drawables in your drawables/like.xml like this,
like.xml
<item android:state_activated="true"
android:drawable="#drawable/like_blue"/>
<item android:drawable="#drawable/like_grey"/>
you can add to your imageview's
android:src="#drawable/like"
android:clickable="true"
in your adapter,
ivLike.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(ivLike.isActivated())
ivLike.setActivated(false);
else
ivLike.setActivated(true);
}
});
for dislike image also you can do the same.
You are running into a view recycling issue. To learn more, look at the answer to this question. In your case, the easiest thing to do is to use the view that's passed into your onClick method:
ivLike.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
ImageView icon = (ImageView) view;
String uri = "#drawable/like_blue";
int imageResource = context.getResources().getIdentifier(uri, null, context.getPackageName());
Drawable res = context.getResources().getDrawable(imageResource);
icon.setImageDrawable(res);
}
});
This is a follow on from an earlier question: ImageButton within row of ListView android not working
But after suggestions from SO gurus it has been suggested I post a new question.
The issue is that I have a custom adapter that is not showing any data. I have looked into other questions, but it didn't provide a solution.
In my Main Activity I have a couple of buttons, one of them: ToDo, should create a row that displays data from a SQLite database, and depending on some factors (dates mainly), it shows a type of traffic light that is stored as a drawable.
Part of the Items in this Row is an Image Button that I want the user to be able to click and the image should change. The user should be able also to click on the actual row and a new activity starts.
The issue I have is that NO DATA is being displayed.
So, here is my code:
public class MainActivity extends Activity {
// definitions etc ...
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// definitions etc ...
}
public void ToDo(View v){ // the user has clicked in the ToDo button
IgroDatabaseHelper helper = new IgroDatabaseHelper(getBaseContext()); // create instance of SQLIte database
numRows = helper.NumEntries("ToDo"); // Get the number of rows in table
int i = 1;
ArrayList<RowItem> rowItems = new ArrayList<>();
RowItem myItem1;
while (i <= numRows){
// get items from database
// depending on value select different drawable
// put data into List Array of RowItem
myItem1 = new RowItem(TheWhat, R.drawable.teamworka, R.drawable.redtrafficlight, R.drawable.checkbox, TheWhenBy);
rowItems.add(myItem1);
//
i = i+ 1;
}
ListView yourListView = (ListView) findViewById(R.id.list);
CustomListViewAdapter customAdapter = new CustomListViewAdapter(this, R.layout.todo_row, rowItems);
yourListView.setAdapter(customAdapter);
}
The CustomListViewAdapter looks like this:
public class CustomListViewAdapter extends ArrayAdapter<RowItem> {
Context context;
ArrayList<RowItem> _rowItems;
public CustomListViewAdapter(Context context, int resourceId,
ArrayList<RowItem> rowItems) {
super(context, resourceId);
this.context = context;
_rowItems = rowItems;
System.out.println("I am in the custom Adapter class "+ _rowItems);
}
#Override
public View getView(int position, View convertView, ViewGroup parent){
System.out.println("This is the get view");
View row = convertView;
RowItem item = _rowItems.get(position);
// you can now get your string and drawable from the item
// which you can use however you want in your list
String columnName = item.getColumnName();
int drawable = item.getDrawable();
if (row == null) {
LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = mInflater.inflate(R.layout.todo_row, parent, false);
}
ImageButton chkDone = (ImageButton) row.findViewById(R.id.chkDone);
chkDone.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
View parentRow = (View) v.getParent();
ListView listView = (ListView) parentRow.getParent();
final int position = listView.getPositionForView(parentRow);
System.out.println("I am in position "+ position);
}
});
return row;
}
}
The RowItem Class looks like:
public class RowItem {
private String _heading;
private int _icon;
private int _lights;
private int _chkdone;
private String _date;
public RowItem(String heading, int icon, int lights, int chkDone, String date) {
_heading = heading;
_icon = icon;
_lights = lights;
_chkdone = chkDone;
_date = date;
System.out.println("adding stuff to my rows");
System.out.println("my column Name is " + heading);
System.out.println("My drawable int is "+ icon);
}
public String getColumnName() {
System.out.println("column Names is "+ _heading);
return _heading;
}
public int getDrawable() {
return _icon;
}
public int getLights(){
return _lights;
}
public int getchkDone(){
return _chkdone;
}
public String getDate(){
return _date;
}
}
I am obviously missing something, as I mentioned earlier, no data gets shown. I know that there are 2 row items that get passed to the CustomListViewAdapter. But I also know that the View getView inside the CustomListViewAdapter does not actually get called.
I hope I have put enough information/code, but if you feel I need to explain something further, please say.
Thanking all very much in advance!
I don't see a getCount() method. You should be overriding it like this:
#Override
public int getCount() {
return _rowItems.getCount();
}
Alternatively, calling super(context, resourceId, rowItems); should also fix it.
Your ListView thinks there are no items to display. If you are using your own array, you must override the getCount() method to indicate the number of items you want to display.
I have a custom ListView with two button and I when I click either button on any row I want to get the text label on the Listview and for now just popup a toast with it. So far nothing has worked I keep getting the last item in my array.
Here is a screen shot to give you a better idea of what i mean
Here is my Adapter subclass for my custom ListView
static final String[] Names =
new String[] { "John", "Mike", "Maria", "Miguel"};
class MyArrayAdapter extends ArrayAdapter<String> {
private final Context context;
int which;
public MyArrayAdapter(Context context, String[] pValues) {
super(context, R.layout.main, pValues);
this.context = context;
values = pValues;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
rowView = inflater.inflate(R.layout.main, parent, false);
TextView textView = (TextView) rowView.findViewById(R.id.label);
ImageView imageView = (ImageView) rowView.findViewById(R.id.logo);
Button call = (Button) rowView.findViewById(R.id.button1);
Button chat = (Button) rowView.findViewById(R.id.button2);
textView.setText(values[position]);
// Change icon based on name
s = values[position];
which = position;
call.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
String name = values[which];
Toast.makeText(CustomListView.this, name, Toast.LENGTH_SHORT).show();
}
});
return rowView;
}
}
Edit:
String name = textView.getText().toString();
RelativeLayout ll = (RelativeLayout)v.getParent();
textView = (TextView)ll.findViewById(R.id.label);
Toast.makeText(CustomListView.this, name,
Toast.LENGTH_SHORT).show();
Easy to do:
call.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
RelativeLayout rl = (RelativeLayout)v.getParent();
TextView tv = (TextView)rl.findViewById(R.id.label);
String text = tv.getText().toString();
Toast.makeText(CustomListView.this, text, Toast.LENGTH_SHORT).show();
}
});
use setTag attribute of the View..............
as
Button call = (Button) rowView.findViewById(R.id.button1);
call.setTag(position);
and
call.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
int which = -1;
Obejct obj = v.getTag();
if(obj instaceof Integer){
which = ((Integer)obj).intValue();
}
if(which >-1){
String name = values[which];
Toast.makeText(CustomListView.this, name, Toast.LENGTH_SHORT).show();
}
}
});
If you have a ListActivity, and you're not using your own adapter, you can still get the list item belonging to the tapped button, like so:
In your layout file of the list row:
<ImageButton
android:id="#+id/button_call"
android:layout_height="48dip"
android:layout_width="48dip"
android:contentDescription="Call"
android:onClick="callBuddy"
android:src="#drawable/call_button_image"
/>
In your ListActivity:
public void callBuddy(View view) {
int position = getListView().getPositionForView((View) view.getParent());
Buddy buddyToCall = (Buddy) getListView().getItemAtPosition(position);
Toast.makeText(MyListActivity.this, String.format("Calling your buddy %s.", buddyToCall.name), Toast.LENGTH_SHORT).show();
}
simply use getItem() and pass the position
Ex:getItem(position).getID()
here getID() method is getter method
Set onClick="click" to xml of button/image/etc...
and in your Activity, do:
public void click(View v) {
final int position = getListView().getPositionForView(v);
String text = getListView().getItemAtPosition(position).toString();
Toast.makeText(getApplicationContext, text, Toast.LENGTH_SHORT).show();
}
I have list with items having two textview and one imageview.I inflate the list with ArrayAdapter.Everything is working fine except changing list item color on click.I have 22 items in my listview. Primarily listview displaying 10 items on the screen and get the other items on scroll.Now my problem is when I clicks on a single item between 0-9(initial 10 items) item changes their color properly on click, but when i scroll and clicks on an item having position greater then 9(after the initial 10 items) my activity crashes.I am referring http://www.mail-archive.com/android-developers#googlegroups.com/msg09740.html link to write the code in for loop.Help me to get rid of this problem.Any suggestions or solutions will be highly appreciated.Thanx in advance.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); // to hide the virtual keyboard
setContentView(R.layout.defect_pic_listview);
try{
adapter = new MyArrayAdapter(this,makeList());
setListAdapter(adapter);
adapter.notifyDataSetChanged();
getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
getListView().setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
// Toast.makeText(getApplicationContext(), "Item "+position+" is clicked",
// Toast.LENGTH_SHORT).show();
System.out.println("position"+position);
int first = getListView().getFirstVisiblePosition();
System.out.println("first="+first);
int last = getListView().getLastVisiblePosition();
System.out.println("last="+last);
int total = last - first;
System.out.println("total="+total);
if(getListView().isItemChecked(position)){
for(int i = 0 ; i <= last ; i++){
System.out.println("i="+i);
if(first+i == position){
getListView().getChildAt(i).setBackgroundColor(Color.GREEN);
System.out.println("l1="+getListView());
// l.getItemAtPosition(i);
// System.out.println("l position"+l);
}
else{
getListView().getChildAt(i).setBackgroundColor(Color.TRANSPARENT);
System.out.println("l2="+getListView());
}
}
}
else{
getListView().getChildAt(position - first).setBackgroundColor(Color.TRANSPARENT);
}
}
});
}
catch(Exception e){
Log.d("error",e.getMessage());
}
}
Use this code for the for loop.
if(getListView().isItemChecked(position))
{
for(int i = 0 ; i < total ; i++)
{
System.out.println("i="+i);
if(first+i == position)
{
getListView().getChildAt(i).setBackgroundColor(Color.GREEN);
System.out.println("l1="+getListView());
// l.getItemAtPosition(i);
// System.out.println("l position"+l);
}
else
{
getListView().getChildAt(i).setBackgroundColor(Color.TRANSPARENT);
System.out.println("l2="+getListView
());
}
}
I think your intention to only change the bacground color of clicked item. For that you not need to add for loop. if your intention is same as i said then use this code only at the place of for loop.
getListView().getChildAt(position).setBackgroundColor(Color.GREEN);
There is other way to do.
First you need to add a selector xml e.g. listviewitem_bg.xml
<item android:drawable="#drawable/listview_normal" android:state_enabled="true" android:state_pressed="false"/>
<item android:drawable="#drawable/listview_press" android:state_enabled="true" android:state_pressed="true"/>
and then set it as a background of your list view cell.
You can try like this:
public class CustomAdapter extends ArrayAdapter<String> {
String[] array;
Context mContext;
LayoutInflater mInflater;
int[] itemStates;
public CustomAdapter(Context context, int textViewResourceId,
String[] objects)
{
super(context, textViewResourceId, objects);
array=objects;
mContext=context;
mInflater = LayoutInflater.from(context);
//save all buttons state as 0(not clicked) initially
itemStates=new int[objects.length];
for(int i=0;i<objects.length;i++)
{
itemStates[i]=0;
}
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
final ViewHolder holder;
if(convertView==null)
{
convertView = mInflater.inflate(R.layout.custom_listitem, null);
holder = new ViewHolder();
holder.text=(TextView)convertView.findViewById(R.id.text);
holder.layout=(LinearLayout)convertView.findViewById(R.id.linear_layout); // outer most linear layout iin custom_listitem xml
convertView.setTag(holder);
}
else
holder=(ViewHolder)convertView.getTag();
holder.text.setText(array[position]);
if(itemStates[position]==0)
{
holder.layout.setBackgroundResource(R.drawable.red_gradient); // item is not clicked/selected yet
}
else
{
holder.button.setBackgroundResource(R.drawable.green_gradient); // item is clicked/selected so change its color
}
final int pos=position;
holder.layout.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
itemStates[pos]=1;
holder.button.setBackgroundResource(R.drawable.green_gradient);
}
});
return convertView;
}
static class ViewHolder
{
TextView text;
LinearLayout layout;
}
}
This will give you behavior like:
Initially all items would be red colored.
if you click on 2nd item,then it will turn green(according to my code).
Now when you scroll and click on any other items,they will keep on turning green from red.
But if you click on "green" colored item,it will again turn red like it is unselected!
you can do something like this
# outside of on create
View prevView;
then in oncreate
lv.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View view, int arg2,
long arg3) {
if (prevView != null) {
prevView.setBackgroundColor(Color.TRANSPARENT);
}
view.setBackgroundColor(Color.RED);
prevView = view;
}
});
I am giving the answer to my own question.
Here's the perfect running code:-
getListView().setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
// Toast.makeText(getApplicationContext(), "Item "+position+" is clicked",
// Toast.LENGTH_SHORT).show();
System.out.println("position="+position);
int first = getListView().getFirstVisiblePosition();
System.out.println("first="+first);
int last = getListView().getLastVisiblePosition();
System.out.println("last="+last);
int total = last - first;
System.out.println("total="+total);
if(getListView().isItemChecked(position)){
for(int i = first ; i <= last ; i++){
System.out.println("i="+i);
if(i == position){
Log.w("TAG", "I am in If block");
getListView().getChildAt(i-first).setBackgroundColor(Color.GREEN);
System.out.println("l1="+getListView());
// l.getItemAtPosition(i);
// System.out.println("l position"+l);
}
else{
getListView().getChildAt(i-first).setBackgroundColor(Color.TRANSPARENT);
System.out.println("l2="+getListView());
}
}
}
else{
getListView().getChildAt(position).setBackgroundColor(Color.TRANSPARENT);
}
}
});
A cleaner(?) solution I've successfully used is to create an extension widget of LinearLayout (or whatever root view type you use for your listitem layout) that implements Checkable.
public class CheckableLinearLayout extends LinearLayout implements Checkable {
boolean checked = false;
public CheckableLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CheckableLinearLayout(Context context) {
super(context);
}
#Override
public void setChecked(boolean checked) {
this.checked = checked;
updateView();
}
/* (non-Javadoc)
* #see android.widget.Checkable#isChecked()
*/
#Override
public boolean isChecked() {
return this.checked;
}
/* (non-Javadoc)
* #see android.widget.Checkable#toggle()
*/
#Override
public void toggle() {
this.checked=!this.checked;
updateView();
}
private void updateView() {
if (this.checked) {
//Change to Whatever your checked color should be, maybe expose this as attribute so i't can be changed from xml attribute
setBackgroundResource(R.color.default_background_color);
} else {
setBackgroundDrawable(null);
}
invalidate();
}
}
Then in your item layout xml:
<my.app.widgets.CheckableLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
..any views for your listitem
<my.app.widgets.CheckableLinearLayout/>