Add items from arraylist to listview on button click - java

I have an arraylist List<Cars> myCars = new ArrayList<Cars>(); My MainActivity layout has a listview and a button. There is one more layout ("each_car.xml") and its content is as below:-
<?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="horizontal" >
<TextView
android:id="#+id/tv_carName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView" />
<TextView
android:id="#+id/tv_carMaker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView" />
</LinearLayout>
</LinearLayout>
My Cars class has two fields,"name" and "manufacturer".
public class Cars{
String name;
String manufacturer;
}
I am populating this list(myCars) through an async-task. After the task is complete i.e. inside onPostExecute(), I am calling a method in my MainActivity which will populate a listview with the items in the list. Below is the method :-
public void populateListView(List<Cars> data){
ArrayAdapter<Cars> carAdapter = new CarAdapter(MainActivity.this, data);
ListView dataList = (ListView) findViewById(R.id.car_listView);
dataList.setAdapter(carAdapter);
}
Below is my CarAdapter class :-
public class CarAdapter extends ArrayAdapter<Cars>{
private LayoutInflater inflater;
List<Cars> dummyData = new ArrayList<Cars>();
MainActivity host;
public CarAdapter(MainActivity host, List<Cars> data)
{
super(host,R.layout.each_car,data);
inflater = host.getWindow().getLayoutInflater();
dummyData = data;
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
View itemView = convertView;
if(itemView == null)
{
itemView = inflater.inflate(R.layout.each_car,parent,false);
}
Cars currentData = dummyData.get(position);
Log.d("Testing Position","Position :- "+position);
TextView carName = (TextView) itemView.findViewById(R.id.tv_carName);
carName.setText(currentData.getName());
TextView carMaker = (TextView) itemView.findViewById(R.id.tv_carMaker);
carMaker.setText(currentData.getManufacturer());
return itemView;
}
}
This is filling out the listview with the entire List (myCars) at once.
Problem :- I want to populate the listView with one item at a time when I click the button.I am not sure how should I modify my code.

add one item in the list at a time when you click the button and call carAdapter.notifyDataSetChanged() .

create a button on main layout. Implement onclicklistener for the button and call populateListView() inside the onlick method.
Creat a new list. When you click a button add an item to a new list. call notifydatasetchanged(). When you click a button check whether the item is already added in the new list or not. Use newly created list in your adapter so that every time new item will be added.

Related

How can I change the info below a RecyclerView depending of the item selected?

I'm making a recycler view with a linear layout horizontal, it looks like this:
HorizontalRecyclerView
As you can see under it there are two text view that I want to fill with the item info when the user press an item. I've do two Adapters to show a menu before, this way when you make a long click the item change its layout, but it doesn´t change the information below. The way of manage a selected item usually is using the adapter like this:
if (holder instanceof AdaptadorProyectosViewHolder) {
((AdaptadorProyectosViewHolder) holder).tv_nombreProyecto.setText(nombreProyecto.toString());
((AdaptadorProyectosViewHolder) holder).tv_nombreClienteProyecto.setText("UN CLIENTE");
//When it's a long click the menu is shown in the place of the item
((AdaptadorProyectosViewHolder) holder).itemView.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
mostrarMenu(position); //showMenu(position)
return true;
}
});
What this do is that the layout of an item change (displaying more information, options,etc), but i want the info to be below the Recycler View, not inside it into an item. There's any way to do it?
Here's the xml of the fragment that contains the Recycler View:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Vistas.Proyectos">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rv_proyectos"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="#+id/textView3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextView" />
<TextView
android:id="#+id/textView2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextView" />
</LinearLayout>
</LinearLayout>
Relying on little details from your question, here's a quick solution.
Add an onClickListener to your adapter:
public interface OnItemClickListener {
void onItemClick(int position);
}
Declare the listener's variable and add it to the adapter's constructor:
private final OnItemClickListener listener;
public MyAdapter ( List<Item> items , Context context , OnItemClickListener listener ) {
mItems = items;
mContext = context;
this.listener = listener;
}
Inside ViewHolder, add OnClickListener:
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener
{
private TextView txt;
public ViewHolder(#NonNull View itemView) {
super(itemView);
itemView.setOnClickListener(this);
txt = itemView.findViewById(R.id.tvItemTitle);
}
#Override
public void onClick(View v)
{
listener.onItemClick(getAdapterPosition());
}
}
After adding these to the adapter, now move to the activity or fragment hosting the recyclerview and implement the onClickListener you just created. Here, I used a fragment:
public class LibraryFragment extends MainActivityFragment implements MyAdapter.OnItemClickListener
Add the following to the newly implemented method:
#Override
public void onItemClick(int position)
{
mtext.setText(mItems.get(position).getName());
}
All done.
Notice that mItems is your list of items, and mtext is the TextView hosting the results!
Also, note the getName() method is a method I created. Replace mItems, mtext and getName with your own codes!
Extra note: you need to add the listener to the adapter in the fragment:
adapter = new MyAdapter( mItems , getActivity() , this );

How to select item from ImageView in ScrollView?

Please bear with me as I am new to android studio. I want to make a ScrollView containing images with corresponding name (TextView). I want to be able to select an image by touching it in the ScrollView, but I don't know how. I have implemented the ScrollView like this, I also want to be able to add pictures with a name attached to them.
Main_activity.xml
<HorizontalScrollView
android:id="#+id/scrollFilterView"
android:layout_width="fill_parent"
android:layout_height="130dp"
android:scrollbars="none"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.57"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="1.0">
<LinearLayout
android:id="#+id/gallery"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal" />
</HorizontalScrollView>
scrollview.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:id="#+id/filterView"
android:layout_width="90dp"
android:layout_height="90dp"
app:srcCompat="#android:drawable/sym_def_app_icon"
android:contentDescription="filterView" />
<TextView
android:id="#+id/textFilter"
android:layout_width="90dp"
android:gravity="center"
android:layout_height="wrap_content"
android:text="textFilter" />
MainActivity.java
LayoutInflater inflater = LayoutInflater.from(this);
for (int i = 0; i < NUMBER_OF_FILTERS_GRID; i++ ) {
View scrollView = inflater.inflate(R.layout.scrollview, gallery, false);
TextView textview = scrollView.findViewById(R.id.textFilter);
textview.setText("Filter "+ i);
ImageView filterView = scrollView.findViewById(R.id.filterView);
filterView.setImageResource(R.mipmap.ic_launcher);
gallery.addView(scrollView);
}
}
Some input to if this is the right path to take and what functions i should use is very appreciated :)
Use a RecyclerView instead of a ListView, and used with and adapter, this will grant you more control over each item displayed on the list (in this case in the RecyclerView),
you will need to create and Adapter class, a simple class for your Items and a new XML layout that will serve as the model of each item in the list.
Simple class for your items:
public class dataSetItem {
private Integer image;
private String listItemText;
public Integer getImage() {
return image;
}
public void setImage(Integer image) {
this.image = image;
}
public String getListItemText() {
return listItemText;
}
public void setListItemText(String listItemText) {
this.listItemText = listItemText;
}
}
In your mainActivity remove the listView and for loop, use this instead:
public class MyActivity extends Activity {
private RecyclerView recyclerView;
private RecyclerView.Adapter mAdapter;
private RecyclerView.LayoutManager layoutManager;
private ArrayList mAdapter = new ArrayList();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_activity);
recyclerView = (RecyclerView) findViewById(R.id.your_recycler_view);
mDataset.add(dataSetItem("item 1", R.mipmap.ic_launcher))
mDataset.add(dataSetItem("item 2", R.mipmap.ic_launcher))
// You can add more items to the mDataset list and call the adapter again to update the RecyclerView
// use a linear layout manager
layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
// specify an adapter (see also next example)
mAdapter = new MyAdapter(myDataset);
recyclerView.setAdapter(mAdapter);
}
// ...
}
Create this XML layout which will serve as the model for each item, called my_item_list_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:orientation="vertical"
android:layout_height="wrap_content"
android:layout_width="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:gravity="center">
<ImageView
android:id="#+id/the_image_i_want_to_click"
android:layout_width="80dp"
android:layout_margin="10dp"
android:layout_height="80dp"
android:layout_gravity="center"
android:layout_marginLeft="10dp"
android:background="#color/ADRBlack"
/>
<TextView
android:id="#+id/item_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxWidth="220dp"
android:textColor="#color/Black"
android:textSize="16sp"
tools:text="Example Restaurant" />
</LinearLayout>
</LinearLayout>
Now the adapter class, in this case called MyAdapter:
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private customItem[] mDataset;
// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
public static class MyViewHolder extends RecyclerView.ViewHolder {
// each data item is just a string in this case
public TextView textView;
public MyViewHolder(TextView v) {
super(v);
textView = v;
}
}
// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter(customItem[] myDataset) {
mDataset = myDataset;
}
// Create new views (invoked by the layout manager)
#Override
public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
TextView v = (TextView) LayoutInflater.from(parent.getContext())
.inflate(R.my_item_list_layout, parent, false);
MyViewHolder vh = new MyViewHolder(v);
return vh;
}
// Replace the contents of a view (invoked by the layout manager)
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
holder.textView.setText(mDataset[position].getListItemText);
holder.textView.setBackground(mDataset[position].getImage);
//Now to do something when you clic the image use this
holder.textView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(final View v) {
//Your action here
}
});
}
// Return the size of your dataset (invoked by the layout manager)
#Override
public int getItemCount() {
return mDataset.length;
}
}

How can I attach a delete button (x) to each member of a dynamically created ListView?

I have a dynamically created list. It's fragment-layout is as follows:
<ListView
android:id="#+id/colorsList"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
When I add a row to the listview, I want an "X" mark to appear at the end of the row so that when the user clicks on the "X", the row gets deleted.
Not sure, if its relevant but, the way I am adding and removing rows to the listview is as follows.
Logic to add a row tot he listView:
#BindView(R.id.understood_languages_list)
View mColorsList;
*********
*********
ListView listFavoriteColors;
listFavoriteColors = (ListView) mColorsList;
ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(context, android.R.layout.simple_list_item_1, getColorsList());
listFavoriteColors.setAdapter(arrayAdapter);
Logic to remove a row from the ListView.
listFavoriteColors.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
initializeView();
arrayAdapter.remove(((TextView)view).getText().toString());
}
});
Any helpful suggestions on how this can be achieved is much appreciated.
User Custom Adapter with custom Layout to attach delete button to each item in listview
try this code :
CustomAdapter
public class ListAdapter extends ArrayAdapter<String> {
private int resourceLayout;
private Context mContext;
ListInterFace interface;
public ListAdapter(Context context, int resource, List<String>
items,ListInterFace interface) {
super(context, resource, items);
this.resourceLayout = resource;
this.mContext = context;
this.interface=interface;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi;
vi = LayoutInflater.from(mContext);
v = vi.inflate(resourceLayout, null);
}
String value= getItem(position);
if (value!= null) {
TextView tt1 = (TextView) v.findViewById(R.id.dummytext);
Button cancel_click=v.findViewById(R.id.cancel_click);
if (tt1 != null) {
tt1.setText(value);
}
//remove item on button click
cancel_click.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view){
interface.removeItem(position);
}
})
}
return v;
}
}
R.layout.itemlistrow defines the row of the ListView.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:context=".MainActivity">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/dummytext"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Dummy"
android:textColor="#android:color/black"
android:textSize="18sp"
android:padding="5dp"/>
<ImageView
android:id="#+id/cancel_click"
android:layout_width="20dp"
android:layout_height="20dp"
android:src="#mipmap/cancel"
android:layout_alignParentRight="true"
android:layout_margin="5dp"/>
</RelativeLayout>
</LinearLayout>
In the MainActivity define ListViewlike this,
ListView yourListView = (ListView) findViewById(R.id.itemListView);
// get data from the table by the ListAdapter
ListAdapter customAdapter = new ListAdapter(this, R.layout.itemlistrow, myList, new ListInterFace () {
#Override
public void removeItem( int position) {
myList.remove(position);
customAdapter .notifyDataSetChanged();
});
yourListView .setAdapter(customAdapter);
InterFace
public interface ListInterFace {
void removeItem(int position);
}
try this link to remove item from list view on button click
Remove Item From List View On Button Click

I need to display a spinner on each row of custom ArrayAdapter

The idea is I want to display list of mp3 files from SDCARD in listview, each line is also contain a spinner with three items (share, rename and delete), I used custom arrayadapter for this purpose and I am stuck on how to add the spinner on the custom arrayadapter class
this is the activity_main.xml
<?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="match_parent"
android:orientation="vertical"
android:theme="#style/AppTheme"
tools:context=".MainActivity"
>
<ListView
android:id="#+id/list"
android:layout_width="match_parent"
android:layout_height="416dp"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginStart="0dp"
android:layout_marginTop="0dp"
android:layout_alignParentLeft="true"
android:layout_marginLeft="0dp" />
<Button
android:id="#+id/stopBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginLeft="12dp"
android:layout_marginBottom="28dp"
android:text="Stop" />
</LinearLayout>
this is where i create the spinner
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:paddingLeft="14dp"
>
<TextView
android:id="#+id/text1"
android:layout_width="0dp"
android:layout_height="33dp"
android:layout_weight="1"
android:gravity="center|start"
/>
<Spinner
android:id="#+id/spinner"
android:layout_width="31dp"
android:layout_height="33dp"
android:layout_gravity="right"
android:background="#drawable/download"
>
</Spinner>
</LinearLayout>
here I create the datatype
public class MyDataType {
// Name of the song
private String mSongName;
// Drawable Menu resource ID
private int mSpinner;
/** Audio resource ID for the word */
//private int mAudioResourceId;
//public MyDataType(String vName, int imageResourceId, int audioResourceId){
public MyDataType(String vName, int spinner){
mSongName = vName;
mSpinner = spinner;
//mAudioResourceId = audioResourceId;
}
public String getSongName() {
return mSongName;
}
public int getSpinner() {
return mSpinner;
}
}
here i create the custom adapter
public class SongAdapter extends ArrayAdapter<MyDataType> {
public SongAdapter(Context context, ArrayList<MyDataType> words) {
super(context, 0, words);
}
Spinner mSpinner;
ArrayAdapter<CharSequence> mAdapter;
#Override
public View getView(int position, View convertView, ViewGroup parent) {
MyDataType currentSong = getItem(position);
View listItemView = convertView;
if (listItemView == null) {
listItemView = LayoutInflater.from(getContext()).inflate(R.layout.song_list, parent, false);
}
TextView songTextView = (TextView)
listItemView.findViewById(R.id.text1);
songTextView.setText(currentSong.getSongName());
mSpinner = (Spinner) listItemView.findViewById(R.id.spinner);
return listItemView;
}
}
this is the main activity
public class MainActivity extends AppCompatActivity {
private static final String SD_PATH = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Xylophone/";
ArrayList<MyDataType> file_list = new ArrayList<MyDataType>();
private final ArrayList<String> songs = new ArrayList<String>();
private MediaPlayer mp = new MediaPlayer();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final MediaPlayer mp = new MediaPlayer();
//updatePlayList();
if (ActivityCompat.checkSelfPermission(this,
android.Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
fillList();
} else {
ActivityCompat.requestPermissions(this, new String[] {android.Manifest.permission.READ_EXTERNAL_STORAGE}, 100);
}
final SongAdapter adapter = new SongAdapter(this, file_list);
ListView listView = (ListView) findViewById(R.id.list);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
try{
mp.reset();
mp.setDataSource(SD_PATH + songs.get(position));
mp.prepare();
mp.start();
}catch (IOException e){
Log.v(getString(R.string.app_name),e.getMessage() );
}
}
});
Button stopPlay = (Button) findViewById(R.id.stopBtn);
stopPlay.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mp.stop();
}
});
}
private void fillList() {
File file = new File(SD_PATH );
File list[] = file.listFiles();
for (int i = 0; i < list.length; i++) {
//file_list.add(list[i].getName(),);
songs.add(list[i].getName());
MyDataType myList = new MyDataType(list[i].getName(), R.id.spinner);
file_list.add(myList);
}
}
}
the string value that cotain menu items
<resources>
<string name="app_name">PlayMp3List</string>
<string-array name="spinner_data">
<item>Rename</item>
<item>Delete</item>
<item>Share</item>
</string-array>
</resources>
OK, it seems that you have almost every thing in place that you need. However, there are a few minor changes you will need to make before this is working. First, in the code where you check the permissions if permission is granted, you call fillList(). But in the Else condition, you request the permission. In the code above, you are not showing how you are handling the result of the request for permission. If the permission is granted after the request, then in that case, you must also call fillList() there as well. And, after calling fillList() there, you will also need to recreate the SongAdapter, and also redo the setAdapter on your list view.
In fillList(), you are initializing your myList item with the song title, and the ID of a spinner. You shouldn't be doing that. What you should be doing is populating the myList item with the 'value' of the spinner... and the default should probably be 0.
In your getView() method in the custom Adapter, you are getting the current item based on the position parameter and putting the song title into the textView. Then, you are getting a reference to the Spinner, but you are not doing anything with it. After getting the reference you should be doing something like mSpinner.value = currentSong.getSpinner();
What you want to do in your MyDataType class is to store the value of the spinner, not any reference to the spinner itself. You also need some sort of click event so that if the user changes the value of the spinner in the row, you can update your ArrayList with the new value. That assumes the user can change that selected spinner item, if not, then when you are creating the list, you have to figure out what value to set each song's spinner value with, which you are not doing.
Your Adapter code should look like this. Note the removal of getContext().
public class SongAdapter extends ArrayAdapter<MyDataType> {
Context mContext = null;
public SongAdapter(Context context, ArrayList<MyDataType> words) {
super(context, 0, words);
mContext = context;
}
Spinner mSpinner;
ArrayAdapter<CharSequence> mAdapter;
#Override
public View getView(int position, View convertView, ViewGroup parent) {
MyDataType currentSong = getItem(position);
View listItemView = convertView;
if (listItemView == null) {
listItemView = LayoutInflater.from(mContext.inflate(R.layout.song_list, parent, false);
}
TextView songTextView = (TextView)
listItemView.findViewById(R.id.text1);
songTextView.setText(currentSong.getSongName());
mSpinner = (Spinner) listItemView.findViewById(R.id.spinner);
mSpinner.value = currentSong.getSpinner();
return listItemView;
}
}
In your list item click method you will need to set a breakpoint to see that the path you are passing in mp.setDataSource is a valid path. It is possible that your SD_PATH needs a '/' at the end or something.
In your layout.xml file you would define your spinner like this:
<Spinner
android:id="#+id/spinner1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:entries="#array/country_arrays"
android:prompt="#string/country_prompt" />
Where the entries #array/country_arrays points to the list that you defined in Strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">MyAndroidApp</string>
<string name="country_prompt">Choose a country</string>
<string-array name="country_arrays">
<item>Malaysia</item>
<item>United States</item>
<item>Indonesia</item>
<item>France</item>
<item>Italy</item>
<item>Singapore</item>
<item>New Zealand</item>
<item>India</item>
</string-array>
</resources>
You are missing the value in your spinner xml definition:
<Spinner
android:id="#+id/spinner"
android:layout_width="31dp"
android:layout_height="33dp"
android:layout_gravity="right"
android:background="#drawable/download"
android:entries="#array/spinner_data"
>
</Spinner>

Can't select ListView items

I have a ListView that uses a custom adapter. Each element in the ListView contains a RadioButton and a TextView.
Here is my adapter, it takes an ArrayList of Employees (An object that currently only contains a name):
public class EmployeeAdapter extends ArrayAdapter<Employee> {
private ArrayList<Employee> listEmployees;
// Give the adapter the context and layout we are operating it, as well as a list of employees to put in the list.
public EmployeeAdapter(Context context, int layout, ArrayList<Employee> listEmployees) {
super(context, layout, listEmployees);
this.listEmployees = listEmployees;
}
// We override the basic getView function since our list is custom.
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
// If there is nothing left to put in the view, inflate the view in the rowemployee layout.
if (v == null){
LayoutInflater vi;
vi = LayoutInflater.from(getContext());
v = vi.inflate(R.layout.rowemployees, null);
}
Employee i = listEmployees.get(position);
// Check if there's still an employee in the list.
if (i != null){
TextView name = (TextView) v.findViewById(R.id.text_employeename);
name.setText(i.getName());
}
// Alternate row colors.
if (position % 2 == 0) {
v.setBackgroundColor(Color.parseColor("#FFFFFF"));
} else {
v.setBackgroundColor(Color.parseColor("#e5fff4"));
}
return v;
}
}
Here is the listview declaration in my XML layout:
<ListView android:id="#+id/employees_list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:paddingLeft="2dp"
android:paddingRight="1dp"
android:background="#drawable/borderlist"
android:choiceMode="singleChoice"
android:listSelector="#48ad82"
android:layout_below="#id/employees_header">
</ListView>
And here is the layout of every item of the ListView:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/row_employee"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:paddingTop="13dp"
android:paddingBottom="13dp"
android:descendantFocusability="blocksDescendants">
<RadioButton android:id="#+id/radio_employee"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:focusable="false"/>
<TextView
android:id="#+id/text_employeename"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp"
android:layout_toRightOf="#id/radio_employee"
android:layout_marginTop="3dp"
android:layout_marginLeft="5dp"
android:focusable="false" />
</RelativeLayout>
I input a bunch of Employee objects into an ArrayList, which I push to the adapter, and then I set a setOnItemClickListener on the list. The listener contains this code:
OnItemClickListener onItemClickListener_employee
= new OnItemClickListener(){
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id){
Toast.makeText(getApplicationContext(), String.valueOf(view.isSelected()) , Toast.LENGTH_SHORT).show();
}
};
view.isSelected() always returns false. Why? I've been trying to figure out how to select an element on a list containing something else than just a TextView for a couple of hours, and the SDK documentation isn't very helpful, this is getting old.
When I press on the list's items, it seems like the TextView or the RadioButton get pressed instead. Shouldn't focusable="false" prevent this ( Android custom ListView unable to click on items )?
To get the item chosen, add the following method to your adapter (untested code):
public Employee getItemAt(int position){
return listEmployees.get(position);
}
Then in your handler, pass the position to the new adapter method above
public void onItemClick(AdapterView<?> parent, View view, int position, long id){
Employee e = adapter.getItemAt(position); //or whatever your adapter instance is named
Toast.makeText(getApplicationContext(), e.getName(), Toast.LENGTH_SHORT).show();
}
Since the view is just for displaying data, you really don't care about the view itself (unless you want to remove it, hilight it, etc).

Categories

Resources