I have created a custom ArrayList which is working as it should barring an issue with the onClick. I orginally had the ArrayList highlight the selected row in red when the user clicked on the row. However, I also required the position of that click outside of the ArrayAdapter class.
The only way I could seem to do this is by adding an onClickListener, however this is were the issues began, although this solved my issue of getting the position the user click on, the row highlighting now seems to get overridden.
So basically my issue is allowing both selected rows to be highlighted and position to be passed to a variable outside of the ArrayAdapter class, please see my code below:
Array Adapter Class:
public class Shop extends ListActivity
{
private static class MyAdapter extends ArrayAdapter<String>
{
private ArrayList<String> data1, data2, data3, data4;
public MyAdapter(Context context, int resource, int textViewResourceId, ArrayList<String> data1, ArrayList<String> data2, ArrayList<String> data3, ArrayList<String> data4)
{
super(context, resource, textViewResourceId, data1);
this.data1 = data1;
this.data2 = data2;
this.data3 = data3;
this.data4 = data4;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent)
{
View v = super.getView(position, convertView, parent);
TextView t1 = (TextView) v.findViewById(R.id.data1);
t1.setText(data1.get(position));
TextView t2 = (TextView) v.findViewById(R.id.data2);
t2.setText(data2.get(position));
TextView t3 = (TextView) v.findViewById(R.id.data3);
t3.setText(data3.get(position));
TextView t4 = (TextView) v.findViewById(R.id.data4);
t4.setText(data4.get(position));
spnCharacters.setVisibility(View.GONE);
Iterator<Integer> iterator = unavailableItem.iterator();
while (iterator.hasNext())
{
int NotAvailable = iterator.next();
if(position == NotAvailable)
{
v.setBackgroundColor(Color.rgb(170, 170, 170));
}
}
if(unavailableItem.size() == 1)
{
if(position == unavailableItem.get(0))
{
v.setBackgroundColor(Color.rgb(170, 170, 170));
}
}
if (position == 0)
{
v.setBackgroundResource(android.R.drawable.title_bar);
}
v.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
currentPositon = position;
if(data2.get(currentPositon).equals("0"))
{
btnSell.setEnabled(false);
}
else
{
btnSell.setEnabled(true);
}
}
});
return v;
}
}
private void NeedPosition()
{
int position = // need ArrayAdapter exact position here
}
}
ArrayAdapter XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<TextView
android:id="#+id/data1"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_margin="5dp"
android:layout_weight="1.5"
android:gravity="center_horizontal"
android:textColor="#FFFFFF" />
<TextView
android:id="#+id/data2"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_margin="5dp"
android:layout_weight="0.5"
android:gravity="center_horizontal"
android:textColor="#FFFFFF" />
<TextView
android:id="#+id/data3"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_margin="5dp"
android:layout_weight="0.5"
android:gravity="center_horizontal"
android:textColor="#FFFFFF" />
<TextView
android:id="#+id/data4"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_margin="5dp"
android:layout_weight="0.5"
android:gravity="center_horizontal"
android:textColor="#FFFFFF" />
</LinearLayout>
List View XML:
<ListView
android:id="#android:id/list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/linearButtons"
android:layout_above="#+id/linerBuyBtns"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:listSelector="#drawable/list_selector">
</ListView>
ListActvity has its own way to manage cell click.
protected void onListItemClick (ListView l, View v, int position, long id)
This method will be called when you click on an row of the ListView. As you can see the second paramter is the position you need
try this...
#Override
public View getView(final int position, View convertView, ViewGroup parent)
{
onClick(...)
{
convertView.parent().setSelection(position); <---
}
}
I had a similar problem with custom listViews and Array adapters..
for me the android:listSelector did not work properly so i used android:Background instead
where i defined states selected, highlighted etc....At the end to achieve certain visual effects i had to use a combination of both, probably not the best solution but works perfectly.
Related
I currently have a listview that contains a button and EditText view. How do I properly implement an OnClickListener in my list adapter so when each button is clicked, the associated EditText within the view is hidden via the setVisibility method.
Based on my current implementation of the OnClickListener in my list adapter, when I click a button to hide the corresponding EditText within the view it hides the very last EditText within the viewport and does not hide the corresponding EditText that it's in the same view as the button. Below is my listview xml file (inspection_single_row.xml), my list adapter (InspectionAdapter.java) and main activity (MainActivity).
inspection_single_row.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Was the sink cleaned floors mopped"
android:id="#+id/text_id"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/check_boxes"
android:layout_marginBottom="20dp"
android:gravity="center_horizontal">
<RadioGroup
android:id="#+id/groupRadio"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:orientation="horizontal">
<RadioButton
android:id="#+id/radioComplete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Complete"
android:checked="false"
android:textColor="#color/grey_mid"/>
<RadioButton
android:id="#+id/radioIncomplete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Incomplete"
android:checked="false"
android:textColor="#color/grey_mid"
android:layout_marginLeft="25dp"/>
</RadioGroup>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="click"
android:onClick="clickMe"
android:id="#+id/btn"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:id="#+id/master_linlayout"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp">
<EditText
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_marginBottom="20dp"
android:gravity="top"
android:padding="10dp"
android:textSize="14sp"
android:background="#drawable/border2"
android:inputType="textMultiLine"
android:textColor="#color/grey_mid"
android:id="#+id/edit_text"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
InspectionAdapter.java
public class InspectionAdapter extends ArrayAdapter<InspectionObject> {
ArrayList<InspectionObject> arrayList;
Context context;
int Resource;
LayoutInflater layoutInflater;
ProgressHolder holder;
public InspectionAdapter(Context context, int resource, ArrayList<InspectionObject> objects) {
super(context, resource, objects);
this.context = context;
arrayList = objects;
Resource = resource;
layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
private static class ProgressHolder {
public RadioGroup radio_group;
public EditText deficiency_notes;
public TextView inspection_task;
public RadioButton radio_yes;
public RadioButton radio_no;
public LinearLayout master_layout;
public Button my_button;
}
#Override
public View getView(final int position, View convertView, final ViewGroup parent) {
View v = convertView;
holder = new ProgressHolder();
if(v == null)
{
v = layoutInflater.inflate(Resource, null);
holder.radio_group = (RadioGroup)v.findViewById(R.id.groupRadio);
holder.deficiency_notes = (EditText)v.findViewById(R.id.edit_text);
holder.inspection_task = (TextView)v.findViewById(R.id.text_id);
holder.radio_yes = (RadioButton)v.findViewById(R.id.radioComplete);
holder.radio_no = (RadioButton)v.findViewById(R.id.radioIncomplete);
holder.master_layout = (LinearLayout)v.findViewById(R.id.master_linlayout);
holder.my_button = (Button)v.findViewById(R.id.btn);
v.setTag(holder);
}else{
holder = (ProgressHolder)v.getTag();
}
final InspectionObject inspectionObject = arrayList.get(position);
holder.my_button.setTag(position);
holder.deficiency_notes.setTag(position);
holder.my_button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int pos = (Integer) v.getTag(); //the real and updated position
Log.i("ConfirmAdapter","Button # position : " + pos);
Log.i("ConfirmAdapter","EditText # position : " + holder.deficiency_notes.getTag());
}
});
return v;
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
ListView lv;
InspectionAdapter inspection_adapter;
ArrayList<InspectionObject> inspectionList;
Boolean eval;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lv = findViewById(R.id.listView2);
inspectionList = new ArrayList<InspectionObject>();
inspectionList = new ArrayList<InspectionObject>();
inspectionList.add(new InspectionObject(true, "", "Were the floor mopped?"));
inspectionList.add(new InspectionObject(true, "", "Were the mirrors cleaned?"));
inspectionList.add(new InspectionObject(false, "", "Were the toilets cleaned?"));
inspectionList.add(new InspectionObject(true, "", "Was high/low dusting performed?"));
inspection_adapter = new InspectionAdapter(getApplicationContext(), R.layout.inspection_single_row, inspectionList);
lv.setAdapter(inspection_adapter);
}
}
Edit:
In this part
Log.i("ConfirmAdapter","EditText # position : " + holder.deficiency_notes.getTag())
you are still referencing the holder variable that is created last. As i said before: In getView, for every view, you create a new ProgressHolder assigning it to holder variable. So holder is overwritten everytime getView is called. That's why, Log.i gives your last item.
Try the following:
Put the new ProgressHolder inside if clause.
if(v == null)
{
holder = new ProgressHolder();
This way it only creates a new instance, when the view is null.
Instead of setting the tag for the button to position you can set it to holder like this
holder.my_button.setTag(holder);
you don't need to set tag for EditText.
Then in the onClick you get the corresponding instance of ProgressHolder via getTag() and change the visibilty like this:
holder.my_button.setTag(holder);
holder.my_button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
ProgressHolder clickedHolder = (ProgressHolder)view.getTag();
clickedHolder.deficiency_notes.setVisibility(View.GONE);
}
});
I have an custom array adaptor which is handling a list view.
Each row has two checkboxes. There are five rows in total.
I want to be able to count the number of checkboxes ticked and then display this number in Stand1
So basically the project Layout is like this
Inside stand1 there is a list view and a text view.
The stand1.java calls an array adapter Called CustomArrayAdaptor.
I want to be able to count the number of checkboxes clicked and send that data back to the stand1
I am quite new to android development so if somebody can be able to push me in the right direction, it would be great.
Here is my code
Stand1.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent">
<ListView
android:layout_width="fill_parent"
android:layout_height="446dp"
android:id="#+id/Stand1list"
android:scrollIndicators="right"
android:smoothScrollbar="true">
</ListView>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Send Score To Databse"
android:id="#+id/sendtodb"
android:textSize="12dp"
android:clickable="true"
android:layout_below="#+id/Stand1list"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="8/10"
android:id="#+id/Score"
android:layout_marginLeft="33dp"
android:layout_marginStart="33dp"
android:layout_alignBottom="#+id/sendtodb"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginBottom="10dp" />
Row_Layout1.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="20dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/textelement"
xmlns:android="http://schemas.android.com/apk/res/android"
android:textSize="30dp"
android:textStyle="bold"
android:longClickable="false" />
<CheckBox
android:layout_width="50dp"
android:layout_height="50dp"
android:id="#+id/Checkbox1"
android:button="#drawable/checkboxcustom"
android:layout_marginLeft="50dp" />
<CheckBox
android:button="#drawable/checkboxcustom"
android:id="#+id/Checkbox2"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginLeft="50dp" />
</LinearLayout>
Stand1.java
public class Stand1 extends Fragment {
ListView mList;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.stand1,container,false);
mList = (ListView) root.findViewById(R.id.Stand1list);
return root;
}
public void onActivityCreated(Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState);
populateListView();
}
private void populateListView() {
String[] pair = {"Pair 1","Pair 2","Pair 3","Pair 4","Pair 5"};
//build adapter
ArrayAdapter<String> adapter = new CustomArrayAdaptor(getActivity(),pair);
mList.setAdapter(adapter);
}
}
CustomArrayAdaptor.java
public class CustomArrayAdaptor extends ArrayAdapter<String>{
public CustomArrayAdaptor(Context context, String [] Pairs) {
super(context, R.layout.row_layout1, Pairs);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = LayoutInflater.from(getContext());
View CustomView = inflater.inflate(R.layout.row_layout1, parent, false);
String stringelement = getItem(position);
TextView Text= (TextView)CustomView.findViewById(R.id.textelement);
Text.setText(stringelement);
return CustomView;
}
}
Thanks Folks
I added a few things to your CustomArrayAdaptor and tested it, see below:
public class CustomArrayAdapter extends ArrayAdapter<String> {
int checkAccumulator;
public CustomArrayAdapter(Context context, String [] Pairs) {
super(context, R.layout.row_layout1, Pairs);
checkAccumulator = 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = LayoutInflater.from(getContext());
View customView = inflater.inflate(R.layout.row_layout1, parent, false);
String stringelement = getItem(position);
TextView Text = (TextView) customView.findViewById(R.id.textelement);
CheckBox checkBox1 = (CheckBox) customView.findViewById(R.id.Checkbox1);
CheckBox checkBox2 = (CheckBox) customView.findViewById(R.id.Checkbox2);
CompoundButton.OnCheckedChangeListener checkListener = new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
countCheck(isChecked);
Log.i("MAIN", checkAccumulator + "");
}
};
checkBox1.setOnCheckedChangeListener(checkListener);
checkBox2.setOnCheckedChangeListener(checkListener);
Text.setText(stringelement);
return customView;
}
private void countCheck(boolean isChecked) {
checkAccumulator += isChecked ? 1 : -1 ;
}
}
Added int checkAccumulator to keep track of how many items have been clicked.
Added two CheckBox Views for the purpose of tracking checks.
Added CompoundButton.OnCheckedChangeListener that calls a new countCheck method everytime any checkBox is checked / unchecked. We pass the isChecked boolean to track whether we need to add or subtract from our checkAccumulator.
Added countCheck function that adds or subtracts 1 dependent on the boolean. Sorry for the obfuscated code, for all those who aren't used to the ? conditional it is basically saying if true add 1, else add -1.
Not sure what you wanted to do with the check count, so I added a Log.i("MAIN", checkAccumulator + ""); just so you can watch the Android Monitor to ensure that it is actually working.
Should work for you.
First of all, you should recycle your views in the adapter:
LayoutInflater inflater = LayoutInflater.from(getContext());
if (convertView == null) {
convertView = inflater.inflate(R.layout.row_layout1, parent, false);
}
After that, I think you should save the state of each checkbox in your data source or just keep a list, the same size of your pair array, and save it there using the position you get from getView.
I have a conversation page with bubble and thumbnail user image, I have problem with thumbnail position: when I send text thumbnail must show on the right and when my friend sent text his thumbnail must show on the left
My XML item is :
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:padding="5dp" >
<LinearLayout
android:id="#+id/wrapper"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="0.5dp" >
<ImageView
android:id="#+id/icon"
android:layout_width="35dp"
android:layout_height="35dp"
android:background="#drawable/user_four"
android:padding="0dp" />
<TextView
android:id="#+id/comment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="5dip"
android:textColor="#2e2e2e"
android:paddingLeft="10dp" />
</LinearLayout>
</RelativeLayout>
and my Java code is :
public class ChatArrayAdapter extends ArrayAdapter<Comment> {
private TextView countryName;
private List<Comment> countries = new ArrayList<Comment>();
private LinearLayout wrapper;
#Override
public void add(Comment object) {
countries.add(object);
super.add(object);
}
public ChatArrayAdapter(Context context, int textViewResourceId) {
super(context, textViewResourceId);
}
public int getCount() {
return this.countries.size();
}
public Comment getItem(int index) {
return this.countries.get(index);
}
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
if (row == null) {
LayoutInflater inflater = (LayoutInflater) this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.listitem_chat, parent, false);
}
wrapper = (LinearLayout) row.findViewById(R.id.wrapper);
Comment coment = getItem(position);
countryName = (TextView) row.findViewById(R.id.comment);
countryName.setText(coment.comment);
countryName.setBackgroundResource(coment.left ? R.drawable.other_bubble : R.drawable.own_bubble);
wrapper.setGravity(coment.left ? Gravity.LEFT : Gravity.RIGHT);
return row;
}
public Bitmap decodeToBitmap(byte[] decodedByte) {
return BitmapFactory.decodeByteArray(decodedByte, 0, decodedByte.length);
}
}
If you know in getView() method that the text is your's or your friend's you can change gravity attribute to left or right, depending on the condition, of the linear layout.
Use seperate layout for left and right then inflate it with the correct layout in your get view
Problem
I'm trying to create a ListView with selectable items. I want to be able to click on an item in the ListView and have the item change color in the list, and then go on and do something else with the data from the row.
I'm using a SimpleAdapter.
How do I make it so that when I tap on a row, it turns a different color, and then when I tap on a different row, the new row is selected and changed to a new color, and the old row changes back to normal?
Code
Here is my code so far. The DBTools class is has all of the data that I want to be displayed in my ListView organized and taken care of. The getAllReceivers() method returns an ArrayList of HashMap<String, String>s that have all of my data.
MainActivity.java:
public class MainActivity extends ListActivity {
DBTools dbTools = new DBTools(this);
ArrayList<HashMap<String, String>> receiverList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getActionBar().hide();
setContentView(R.layout.activity_main);
receiverList = dbTools.getAllReceivers();
dbTools.close();
ListView listView = getListView();
if(receiverList.size() != 0) {
SimpleAdapter adapter = new SimpleAdapter(MainActivity.this,receiverList, R.layout.receiver_entry, new String[] {"receiverId","receiverName", "fullPath"}, new int[] {R.id.receiverId, R.id.receiverName, R.id.fullPath});
setListAdapter(adapter);
}
}
}
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TableRow
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/black" >
<TextView
android:id="#+id/titleTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="My List" />
</TableRow>
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/black"
android:id="#android:id/list" />
</TableLayout>
receiver_entry.xml
<?xml version="1.0" encoding="utf-8"?>
<TableRow xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/tableRow" >
<TextView
android:id="#+id/receiverId"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:visibility="gone" />
<TextView
android:id="#+id/receiverName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Robotronics" />
<TextView
android:id="#+id/fullPath"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="123.45.678.910:8088/robtrox/find" />
</TableRow>
Solution
The solution to this problem is very simple. We need to add an OnItemClickListener to our ListView to listen for clicks and respond accordingly.
So, in the onCreate() method, once you've made sure that you set of data isn't empty, you're going to want to Override the onItemClick() method to listen for the click and change the color. You're also going to want to keep track of which item you selected for the later steps, so add public int selectionId = -1; at the top of your class. Furthermore, you'll need to let the ListAdapter know that you changed something by calling ((SimpleAdapter) getListAdapter()).notifyDataSetChanged().
if(receiverList.size() != 0) {
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int index, long id) {
view.setBackgroundColor(Color.RED);
TextView receiverIdTextView = (TextView) view.findViewById(R.id.receiverId);
selectionId = Integer.valueOf(receiverIdTextView.getText().toString());
((SimpleAdapter) getListAdapter()).notifyDataSetChanged();
}
});
SimpleAdapter adapter = getNewAdapter();
setListAdapter(adapter);
}
Great! Now we have a working system that will change the color of the row that you tap. But we're not done yet. We need to make sure that the previous selection changes back to the normal color.
For this, we are going to use override the SimpleAdapter's getView() method, which is called everytime the ListView goes to draw the items being displayed in it.
It only actually displays the items it needs to - the ones that you can see. It does not render the ones above or below your screen. So if you have 200 items in a ListView, only 5 or 6, depending on the size of your screen and the size of the items, are being rendered at a time.
To override the getView() method, go up to where you initialize the adapter and change the code to this:
SimpleAdapter adapter = new SimpleAdapter(MainActivity.this,receiverList, R.layout.receiver_entry, new String[] { "receiverId","receiverName", "fullPath"}, new int[] {R.id.receiverId, R.id.receiverName, R.id.fullPath}) {
#Override
public View getView (int position, View convertView, ViewGroup parent) {
View view = super.getView(position, convertView, parent);
TextView receiverIdTextView = (TextView) view.findViewById(R.id.receiverId);
if(receiverIdTextView.getText().toString().equals(String.valueOf(selectionId))) {
view.setBackgroundColor(Color.RED);
} else {
view.setBackgroundColor(Color.WHITE);
}
return view;
}
};
Every time one of the rows is drawn, since the getView() will get called, the ListView will check if the current view has the id of row you selected. If it doesn't, it'll change the background color to white. If it does, it'll change the background color to red.
And voila! That's it! Now you are setting the background color to red when you click on an item in the ListView.
Final Code
MainActivity.java:
public class MainActivity extends ListActivity {
DBTools dbTools = new DBTools(this);
ArrayList<HashMap<String, String>> receiverList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getActionBar().hide();
setContentView(R.layout.activity_main);
receiverList = dbTools.getAllReceivers();
dbTools.close();
ListView listView = getListView();
if(receiverList.size() != 0) {
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int index, long id) {
view.setBackgroundColor(Color.RED);
TextView receiverIdTextView = (TextView) view.findViewById(R.id.receiverId);
selectionId = Integer.valueOf(receiverIdTextView.getText().toString());
((SimpleAdapter) getListAdapter()).notifyDataSetChanged();
}
});
SimpleAdapter adapter = new SimpleAdapter(MainActivity.this,receiverList, R.layout.receiver_entry, new String[] { "receiverId","receiverName", "fullPath"}, new int[] {R.id.receiverId, R.id.receiverName, R.id.fullPath}) {
#Override
public View getView (int position, View convertView, ViewGroup parent) {
View view = super.getView(position, convertView, parent);
TextView receiverIdTextView = (TextView) view.findViewById(R.id.receiverId);
if(receiverIdTextView.getText().toString().equals(String.valueOf(selectionId))) {
view.setBackgroundColor(Color.RED);
} else {
view.setBackgroundColor(Color.WHITE);
}
return view;
}
};
setListAdapter(adapter);
}
}
}
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TableRow
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/black" >
<TextView
android:id="#+id/titleTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="My List" />
</TableRow>
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/black"
android:id="#android:id/list" />
</TableLayout>
receiver_entry.xml
<?xml version="1.0" encoding="utf-8"?>
<TableRow xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/tableRow" >
<TextView
android:id="#+id/receiverId"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:visibility="gone" />
<TextView
android:id="#+id/receiverName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Robotronics" />
<TextView
android:id="#+id/fullPath"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="123.45.678.910:8088/robtrox/find" />
</TableRow>
I've been dealing with this for a few weeks now. I've already seen all other related questions and it does not help. I'm trying to populate a custom ListView and can't for the life of me get it to work. I'll post all the relevant information hoping someone will notice my mistake.
Activity Layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
tools:context=".MainActivity"
android:background="#000000">
<ListView
android:id="#+id/deviceListView"
android:layout_width="400px"
android:layout_height="fill_parent"
android:textColor="#ffffff"
android:layout_centerVertical="true"
android:layout_alignParentLeft="true"/>
</LinearLayout>
Custom Row layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="#000000">
<TextView android:id="#+id/textId"
android:textSize="50sp"
android:text="ID"
android:textColor="#FFFFFF"
android:textStyle="bold"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:orientation="vertical">
<TextView android:id="#+id/textTimestamp"
android:textSize="16sp"
android:text="Timestamp"
android:textColor="#FFFFFF"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
android:layout_height="wrap_content"/>
<TextView android:id="#+id/textCoordinates"
android:textSize="16sp"
android:text="Coordinates"
android:textColor="#FFFFFF"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView android:id="#+id/textDistance"
android:textSize="16sp"
android:text="Distance"
android:textColor="#FFFFFF"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
</LinearLayout>
Adapter model:
public class DeviceList {
public static ArrayList<Device> list;
public static void loadModel(int quantity) {
ArrayList<Device> listTmp = new ArrayList<Device>();
for (int i = 0; i < quantity; i++) {
listTmp.add(new Device(System.currentTimeMillis(), i, new float[]{0, 0}, System.currentTimeMillis() / (i + 1)));
}
list = listTmp;
}
public static Device GetById(int id){
Device tmp = null;
for(Device device : list){
if (device.getID() == id){
tmp = device;
}
}
return tmp;
}
}
Adapter:
public class DeviceArrayAdapter extends ArrayAdapter<Device> {
private Context context;
private int rowResourceId;
private String[] ids;
public DeviceArrayAdapter(Context context, int rowResourceId, String[] devices) {
super(context, rowResourceId);
this.context = context;
this.ids = devices;
this.rowResourceId = rowResourceId;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.device_row, parent, false);
TextView idTextview = (TextView) rowView.findViewById(R.id.textId);
TextView timeStampTextview = (TextView) rowView.findViewById(R.id.textTimestamp);
TextView coordinatesTextview = (TextView) rowView.findViewById(R.id.textCoordinates);
TextView distanceTextview = (TextView) rowView.findViewById(R.id.textDistance);
int id = Integer.parseInt(ids[position]);
timeStampTextview.setText(Long.toString(DeviceList.GetById(id).getTimestamp()));
idTextview.setText(DeviceList.GetById(id).getID());
coordinatesTextview.setText(DeviceList.GetById(id).getCoordinates()[0] + "," + DeviceList.GetById(id).getCoordinates()[1]);
distanceTextview.setText(DeviceList.GetById(id).getDistance() + "");
return rowView;
}
}
And finally the Activity's onCreate method:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// setContentView(R.layout.activity_main);
// ArrayList<Device> list = createDummyDeviceList(5);
DeviceList.loadModel(5);
String[] ids = new String[DeviceList.list.size()];
for (int i= 0; i < ids.length; i++){
ids[i] = Integer.toString(i+1);
}
ListView listView = (ListView) findViewById(R.id.deviceListView);
DeviceArrayAdapter adapter = new DeviceArrayAdapter(this, R.layout.device_row, ids);
listView.setAdapter(adapter);
}
Note: I'm sorry to post like this but I'm desperate. I've already debugged it up to the last line and everything is loaded and there are no Exceptions. But it just won't populate.
[EDIT]
Together with the selected answer I also had different numbered arrays and ids. The ids I generated started from 1 and not 0.
You never pass the dataset to the super class. Change
super(context, rowResourceId);
with
super(context, rowResourceId, devices);
this way the getCount of the ArrayAdapter, returns the devices length and the getView would be invoked. Also to avoid waste of memory and better performance, you should inflate the convertView only once.
Edit. The super is expecting an Array or ArrayList of Device objects. Instead your devices in a String array. Your choice should be consistent. You can either change
extends ArrayAdapter<Device>
with
extends ArrayAdapter<String>
or pass as paramter a Device[] as parameter to your custom Adapter. For instance
public DeviceArrayAdapter(Context context, int rowResourceId, Device[] devices) {
Check sources of ArrayAdapter http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.3_r2.1/android/widget/ArrayAdapter.java#ArrayAdapter.getCount%28%29
In your case you should override method getCount().