let's say that i have a list of items and i want to build a form with each of these items. This form consist of two checkboxes and an editText. For example i want to know if each item is present in a warehouse and its quantity. I'm thinking for solving my problem to use a listview where each element of my listview will consist of the name of an item, two checkboxes and an editText.
The problem is that the only use of listview i know to present list of elements, i don't how to solve my problem with it (i'm a beginner in android). Can someone help me ?
Is there another way to solve my problem ? Thank you
Try to implements a cusom ListView adapter! This is easier than you might think!
First you need to create layout which would will represent each item in your list:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Test TEST" />
<LinearLayout android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignBottom="#id/itemTextView"
android:layout_alignParentRight="true">
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/doneCheckBox" />
</LinearLayout>
Then implement cusom adapter inside your code:
public CusomAdapter(Context mainContex, YourItems<SomeItem> someItems) {
this.mainContex = mainContex;
this.someItems = someItems;
}
#Override
public int getCount() {
return someItems.size();
}
#Override
public Object getItem(int position) {
return someItems.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View item = convertView;
if (item == null) {
item = LayoutInflater.from(mainContex).inflate(R.layout.shoplist_item, null); // your listView layout here!
}
//fill listView item with your data here!
//initiate your check box
CheckBox doneCheckBox = (CheckBox)item.findViewById(R.id.doneCheckBox);
//add a checkbox listener
doneCheckBox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(isChecked){
doneCheckBox.ischecked=true;
}
else{
doneCheckBox.ischecked=false;
}
}
});
return item;
}
don't forget to add ListView element inside your Activity layout!
Given the ListView below, I wanted to perform two different actions depending on whether the user selects the text (create a new activity) or clicks the associated checkbox (add it to a favorites list). Is this possible in with this setup or will I have to use a custom adapter or even a different layout?
<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">
<ListView
android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout>
setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_multiple_choice, teams));
getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
String team_name = adapterView.getItemAtPosition(i).toString().trim();
Intent intent = new Intent("blah.blah.blah");
intent.putExtra("team", team_name);
startActivity(intent);
}
});
A
If I am understanding you correctly, your ListView should contain TextBox and CheckBox and TextBox and CheckBox are clickable, not ListView itself.
For this you have to make custom adapter, where you will make listeners for both the TextBox and CheckBox.
public class CustomAdapter extends BaseAdapter {
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// your_costum_view should contain textbox and checkboc
view = inflater.inflate(R.layout.your_costum_view, null);
// Get your checkbox and textbox and add listeners
TextView textView = (TextView) view.findById(R.id.textView);
textView.setOnClickListener...
Checkbox checkbox=(CheckBox)view.findById(R.id.checkBox);
checkBox.setOnClickListener...
return view;
}
}
your_costum_view layout example
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<CheckBox
android:id="#+id/checkBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
Using a custom adapter will help you keep trace of your views, it will be easier than use a default adapter that you can't control. For references: http://www.vogella.com/tutorials/AndroidListView/article.html#adapterown_custom
Using a custom adapter will definitely make your life easier. In the adapter you can make reference to both the checkbox and the textView and add an onClick Listener to each - from there you can also add code to handle each event. I would also suggest using a recyclerView instead of a ListView. It is the new thing in Android 5.0 and it really is easier to use then a regular ListView. Hope this helps:
RecyclerView Help
Set the CheckBox as focusable="false" in your XML layout.
android:focusable="false"
if don't run go to this link and see example because you need a create custom row in list view and set:
Checkbox checkbox=(CheckBox)view.findById(R.id.checkboxID);
checkbox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
//do stuff
}
});
Activity class code:
conversationList = (ListView)findViewById(android.R.id.list);
ConversationArrayAdapter conversationArrayAdapter=new ConversationArrayAdapter(this, R.layout.conversation_list_item_format_left, conversationDetails);
conversationList.setAdapter(conversationArrayAdapter);
conversationList.setOnItemClickListener(new AdapterView.OnItemClickListener(){
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int position, long arg3) {
Log.d("test","clicked");
}
});
The getView function in the Adapter class:
if (v == null) {
LayoutInflater vi = (LayoutInflater)ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if(leftSideMessageNumber.equals(m.getTo())) {
v = vi.inflate(R.layout.conversation_list_item_format_left, null);
} else {
v = vi.inflate(R.layout.conversation_list_item_format_right, null);
}
}
Is there a problem with using two xmls while inflating?
I just found a solution from here, but by deep clicking.
If any row item of list contains focusable or clickable view then OnItemClickListener won't work.
The row item must have a param like
android:descendantFocusability = "blocksDescendants".
Here you can see an example of how your list item should look like.
Your list item xml should be...
row_item.xml (your_xml_file.xml)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:baselineAligned="false"
android:descendantFocusability="blocksDescendants"
android:gravity="center_vertical" >
// your other widgets here
</LinearLayout>
The problem is that your layouts contain either focusable or clickable items.
If a view contains either focusable or clickable item the OnItemCLickListener won't be called.
Click here for more information.
Please post one of your layout xmls if that isn't the case.
For my lists, my rows have other things that can be clicked, like buttons, so doing a blanket blocksDescendants doesn't work. Instead I add a line in the button's xml:
android:focusable="false"
That keeps the buttons from blocking the clicks on the rows, but still lets the buttons take the clicks, too.
you need to do 2 steps in your listview_item.xml
set the root layout with: android:descendantFocusability="blocksDescendants"
set any focusable or clickable view in this item with:
android:clickable="false"
android:focusable="false"
android:focusableInTouchMode="false"
Here is an example: listview_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:layout_marginTop="10dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:gravity="center_vertical"
android:orientation="vertical"
android:descendantFocusability="blocksDescendants">
<RadioButton
android:id="#+id/script_name_radio_btn"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textStyle="bold"
android:textColor="#000"
android:padding="5dp"
android:clickable="false"
android:focusable="false"
android:focusableInTouchMode="false"
/>
</LinearLayout>
use the below code inside button tag in custom row layout of listview
android:focusable="false"
android:clickable="false"
I had the same problem and I just saw I had accidentally set:
#Override
public boolean isEnabled(int position)
{
return false;
}
on my CustomListViewAdapter class.
By changing this to:
return true;
I've managed to fix the problem.
Just in case if someone has done the same mistake...
Use android:descendantFocusability
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="80dip"
android:background="#color/light_green"
android:descendantFocusability="blocksDescendants" >
Add above in root layout
I solved it with the help of this answer
1.Add the following in Linear Layout of list_items.xml
android:descendantFocusability="blocksDescendants"
2.Child Views of LinearLayout in list_items.xml
android:focusable="false"
if you have textviews, buttons or stg clickable or selectable in your row view only
android:descendantFocusability="blocksDescendants"
is not enough. You have to set
android:textIsSelectable="false"
to your textviews and
android:focusable="false"
to your buttons and other focusable items.
Even I was having the same problem, I am having checkbox, did the following to masker itemClickListener work,
Added the following properties to the checkbox,
android:focusable="false"
android:focusableInTouchMode="false"
android:clickable="false"
and ItemClickListner started working.
For detailed example you can go through the link,
http://knowledge-cess.com/android-itemclicklistner-with-checkbox-or-radiobutton/
Hope it helps Cheers!!
I had the same problem and tried all of the mentioned solutions to no avail. through testing i found that making the text selectable was preventing the listener to be called. So by switching it to false, or removing it my listener was called again.
android:textIsSelectable="false"
hope this helps someone who was stuck like me.
Add this in main Layout
android:descendantFocusability="blocksDescendants"
Write this code into every button,Textview,ImageView etc which have
onClick
android:focusable="false"
android:clickable="false"
Hope it will work.
Two awesome solutions were this, if your extending ListFragment from a fragment, know that mListView.setOnItemClickListener wont be called before your activity is created, this ensured it is set when activity has been created
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mListView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long rowId) {
// Do the onItemClick action
Log.d("ROWSELECT", "" + rowId);
}
});
}
While looking at the source code for ListFragment, I came across this
public class ListFragment extends Fragment {
...........................................
................................................
final private AdapterView.OnItemClickListener mOnClickListener
= new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
onListItemClick((ListView)parent, v, position, id);
}
};
................................................................
................................................................
public void onListItemClick(ListView l, View v, int position, long id) {
}
}
An onItemClickListener object is attached and it calls onListItemClick()
As such the other similar solution, which works in the exact same way is to override onListItemClick()
#Override
public void onListItemClick(ListView l, View v, int position, long rowId) {
super.onListItemClick(l, v, position, id);
// Do the onItemClick action
Log.d("ROWSELECT", "" + rowId);
}
in my case none of xml layout properties was not helpful.
I just add a single line of code like this:
convertView.setClickable(false);
#NonNull
#Override
public View getView(final int position, View convertView, #NonNull ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null || convertView.getTag() == null) {
LayoutInflater inflater = LayoutInflater.from(context);
convertView = inflater.inflate(R.layout.my_layout_id, parent, false);
viewHolder = new ViewHolder(convertView);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
...
convertView.setClickable(false);
return convertView;
}
so basically it do the same thing as setting up properties in xml layout but it was only thing which works in my case.
It is not perfect timing but maybe it will helps somebody
Happy coding
I've tried all the above and NOTHING worked.
I solved the problem as follows:
First I define a custom Button called ListButton
public class ListButton extends android.widget.Button
{
private ButtonClickedListener clickListener;
public ListButton(Context context)
{
this(context, null);
}
public ListButton(Context context, AttributeSet attrs)
{
this(context, attrs, 0);
}
public ListButton(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
}
public void setClickListener(ButtonClickedListener listener) {
this.clickListener = listener;
}
#Override
public boolean isInTouchMode() {
return true;
}
#Override
public boolean onTouchEvent(MotionEvent event) {
return false;
}
#Override
public boolean dispatchTouchEvent(MotionEvent event) {
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_UP:
eventClicked();
break;
case MotionEvent.ACTION_CANCEL:
break;
case MotionEvent.ACTION_MOVE:
break;
default :
}
return true;
}
private void eventClicked() {
if (this.clickListener!=null) {
this.clickListener.ButtonClicked();
}
}
}
The XML looks like:
<dk.example.views.ListButton
android:id="#+id/cancel_button"
android:layout_width="125dp"
android:layout_height="80dp"
android:text="Cancel"
android:textSize="20sp"
android:layout_margin="10dp"
android:padding="2dp"
android:background="#000000"
android:textColor="#ffffff"
android:textStyle="bold"
/>
Then I define my own ButtonClicked Listener interface:
public interface ButtonClickedListener {
public void ButtonClicked();
}
Then I use my own listener just as if it was the normal OnClickListener:
final ListButton cancelButton = (ListButton) viewLayout.findViewById(R.id.cancel_button);
cancelButton.setClickListener(new ButtonClickedListener() {
#Override
public void ButtonClicked() {
//Do your own stuff here...
}
});
I had the same issue, I was using a style for my texts in the row layout that had the "focusable" attribute. It worked after I removed it.
In my case, I had to remove the next line from the Layout
android:clickable="true"
Android:autoText attribute also makes TextView auto focusable.
If you want to use both the simple click and long click on list view items better way to implement that would be to use context menu for long click. Avoid using setItemLongClickListener especially if you have multiple row layouts for your listview.
Faced same problem, tried for hours. If you have tried all of the above than try changing layout_width of Listview and list item to match_parent from wrap_content.
All of the above failed for me. However, I was able to resolve the problem (after many hours of banging my head - Google, if you're listening, please consider fixing what I encountered below in the form of compiler errors, if possible)
You really have to be careful of what android attributes you add to your xml layout here (in this original question, it is called list_items.xml). For me, what was causing the problem was that I had switched from an EditText view to a TextView and had leftover attribute cruft from the change (in my case, inputType). The compiler didn't catch it and the clickability just failed when I went to run the app. Double check all of the attributes you have in your layout xml nodes.
private AdapterView.OnItemClickListener onItemClickListener;
#Override
public View getView(final int position, View convertView, final ViewGroup parent) {
.......
final View view = convertView;
convertView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (onItemClickListener != null) {
onItemClickListener.onItemClick(null, view, position, -1);
}
}
});
return convertView;
}
public void setOnItemClickListener(AdapterView.OnItemClickListener onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
Then in your activity, use adapter.setOnItemClickListener() before attaching it to the listview.
Copied from github its worked for me
The thing that worked for me was to add the below code to every subview inside the layout of my row.xml file:
android:focusable="false"
android:focusableInTouchMode="false"
So in my case:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
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">
<TextView
android:focusable="false"
android:focusableInTouchMode="false"
android:id="#+id/testingId"
android:text="Name"
//other stuff
/>
<TextView
android:focusable="false"
android:focusableInTouchMode="false"
android:id="#+id/dummyId"
android:text="icon"
//other stuff
/>
<TextView
android:focusable="false"
android:focusableInTouchMode="false"
android:id="#+id/assignmentColor"
//other stuff
/>
<TextView
android:focusable="false"
android:focusableInTouchMode="false"
android:id="#+id/testID"
//other stuff
/>
<TextView
android:focusable="false"
android:focusableInTouchMode="false"
android:text="TextView"
//other stuff
/>
</android.support.constraint.ConstraintLayout>
And this is my setOnItemClickListener call in my Fragment subclass:
CustomListView = (PullToRefreshListCustomView) layout.findViewById(getListResourceID());
CustomListView.setAdapter(customAdapter);
CustomListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Log.d("Testing", "onitem click working");
// other code
}
});
I got the answer from here!
Had the same problem with onClick. The solution was to remove from the xml the following
android:tooltipText=""
I solved the problem by removing the clickable views from the list.
I have an activity with a list, whose items are made of an image+text. I need to allow the user to change the view and have a gridview instead of it (whose elements are still made of the same image+text).
The user can do it through an icon menu:
public boolean onOptionsItemSelected(MenuItem item)
{
if(item.getItemId()== R.id.change_view)
{
// ?
}
}
I tried to just set the new adapter(see below) but it doesn't work..do I have to create a new activity to do that?
if(item.getItemId()== R.id.change_view)
{
setContentView(R.layout.grid_view);
gridViewAdapter = new GridViewAdapter(this,R.layout.bookmark_list_item,MyApp.getItems().findAll());
list.setAdapter(gridViewAdapter);
list.setVisibility(View.VISIBLE);
}
There are several ways you could achieve that.
One solution is to have both the ListView and GridView stacked in a FrameLayout, and when you want to switch between these views, set the visibility GONE to one view and VISIBLE to another, then viceversa.
Put both the ListView and GridView in a ViewFlipper
Or, use a ViewSwitcher
And finally, use just a GridView, but when you want to transition to a list view, set programmatically the number of columns to 1.
I finally resolved with something like this:
For the layout of my activity i have:
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ViewStub android:id="#+id/list"
android:inflatedId="#+id/showlayout"
android:layout="#layout/list_view"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"/>
<ViewStub android:id="#+id/grid"
android:inflatedId="#+id/showlayout"
android:layout="#layout/grid_view"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"/>
</merge>
then i've defined the layout for the list and the grid (and also for their items), and managed the passage between them inflating the layouts and then by this method:
private void changeView() {
//if the current view is the listview, passes to gridview
if(list_visibile) {
listview.setVisibility(View.GONE);
gridview.setVisibility(View.VISIBLE);
list_visibile = false;
setAdapters();
}
else {
gridview.setVisibility(View.GONE);
listview.setVisibility(View.VISIBLE);
list_visibile = true;
setAdapters();
}
}
the complete code is available in this article: http://pillsfromtheweb.blogspot.it/2014/12/android-passare-da-listview-gridview.html
I have a ListView that I'm populating with values from my database. If the database is empty, I'm setting the first item of the ListView to "No data.". I want to disable clicking on this item. I've used ArrayAdapter. I tried making areAllItemsEnabled,isEnabled false, but it was of no use. Even if I set the ListView's isClickable and setEnabled to false, it is of no use. And I put the code for the OnItemClickListener in the else condition,even that doesn't stop the list item from being clickable. Does someone have an alternate solution? Thanks!
In your custom ArrayAdapter use isEnabled function to return false:
#Override
public boolean isEnabled(int position) {
return false;
}
always works for me.
all the easier! list.setEnabled(false)
You can set the empty View as showed and it will be handled automatically:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="8dp"
android:paddingRight="8dp">
<ListView android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#00FF00"
android:layout_weight="1"
android:drawSelectorOnTop="false"/>
<TextView android:id="#android:id/empty"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FF0000"
android:text="No data"/>
</LinearLayout>
create Adapter for that list, and there override this method
public boolean isEnabled(int position);
then return false when you want to disable the click
Try setting these two attributes on the ListView:
android:listSelector="#android:color/transparent"
android:cacheColorHint="#android:color/transparent"
Perhaps you could use an if statement to check the contents of the listview entry in the OnClick, if it contains 'No data' do nothing, else do the usual
I did like this according to my requirement hope it can help you some how
#Override
public boolean isEnabled(int position) {
if(data.get(position).isClickable==false)
{
return false;
}
return super.isEnabled(position);
}