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);
}
Related
I am creating a simple view where on the top I have some elements and below a recyclerView. When I scroll it down, would like to scroll the whole screen, not the only recycler.
I have achieved it with NestedScrollView, however, now the problem appears. Items in the list will be pretty heavy and in this configuration, all the items are bind at the same time(call of onBindViewHolder).
any ideas how to make them recycle and solve this problem?
Here is my xml file
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView 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:background="#android:color/darker_gray"
android:orientation="vertical"
tools:context="com.gkuziel.testkotlin.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:layout_width="100dp"
android:layout_height="100dp"
android:src="#drawable/ic_available_stores_default" />
<TextView
android:id="#+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="test text" />
<android.support.v7.widget.RecyclerView
android:id="#+id/list_test"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:isScrollContainer="false"
android:nestedScrollingEnabled="false">
</android.support.v7.widget.RecyclerView>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
Update:
The found a sweet solution: you add a complex header as ItemDecoration, its great cause your adapter can stay untouched, you just add sth like this:
recyclerView.addItemDecoration(dividerItemDecoration);
the only drawback of this solution is i couldn't make this header clickable (in my case it contains another recyclerView), however I know some people achieved it as well.
For this moment I decided implement heterogeneous recyclerview, with 1 instance of header type and the rest of simple row types.
What is important, the header type is fully binded once in HeaderViewHolder constructor and onBindViewHolder looks like this:
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
if (holder is HeaderViewHolder) {
//do nothing
Log.d("ProductAdapter", "Binding: Header")
} else if (holder is ItemViewHolder) {
Log.d("ProductAdapter", "Binding: " + position.toString())
val searchItem = items!![position - 1]
//here the proper binding is going on
}
}
You can try setting the recyclerview layout manager's method canScrollVertical to false and it won't respond to any touch inner scroll events.
override below method and return false.
boolean canScrollVertically()
here it is how to set.
#Override
protected void onCreate(Bundle savedInstanceState) {
// ...
// Lookup the recyclerview in activity layout
RecyclerView listTest = (RecyclerView) findViewById(R.id.list_test);
// Attach the adapter to the recyclerview to populate items
listTest.setAdapter(adapter);
// Set layout manager to position the items
listTest.setLayoutManager(new LinearLayoutManager(this){
#Override
public boolean canScrollVertically(){
return false;
}
});
// That's all!
}
I'm looking for a solution to this that will allow me to expand a cardview to see more information and then easily collapse it. Google Keep has examples of cards like this. Anyone know how they do this? Would I create 2 versions of my cardview (one collapsed and one expanded) and then use an Animator class coupled with gesture methods to transition between the two views? I'm using a Recyclerview to hold my cardviews.
I found this if it is at all relevant: http://developer.android.com/training/animation/layout.html
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:orientation="vertical"
android:animateLayoutChanges="true"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
//here put the view which is always visible
<LinearLayout
android:layout_width="match_parent"
android:visibilty="gone"
android:id="#+id/expandableLayout"
android:layout_height="wrap_content">
//here put which will collapse and expand
</LinearLayout>
</android.support.v7.widget.CardView>
take a boolean isexpanded in you arraylist object class
if (listobj.isexpanded)
{
holder.expandableLayout.setVisibility(View.VISIBLE);
}
else {
holder.expandableLayout.setVisibility(View.GONE);
}
holder.cardView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (listobj.isexpanded)
{
holder.expandableLayout.setVisibility(View.GONE);
listobj.isexpanded=false;
notifyItemChanged(position);
}
else {
holder.expandableLayout.setVisibility(View.VISIBLE);
listobj.isexpanded=true;
notifyItemChanged(position);
}
}
});
try someting like this
I use an adapter to load a list view from a content provider. Each item in the list uses the below 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">
<LinearLayout
android:id ="#+id/wrapper"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<CheckedTextView
android:id="#+id/txt_chat"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_gravity="center"
android:checkMark="?android:attr/listChoiceIndicatorMultiple"
/>
</LinearLayout>
</LinearLayout>
I have set the list item to allow multiple choice mode :
onCreate(){
...
lv_chatMessages = (ListView) findViewById(R.id.listview_chat);
lv_chatMessages.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
lv_chatMessages.setItemsCanFocus(false);
...
}
But at run time, i am not able to check any of the items in the list view. If i touch the box, the item just gets highlighted momentarily, but no check mark appears.
I can set a default for all the items if i add an attribute to the CheckedTextView :
android:checked="true"
How do i let the user change the check status of each item at runtime?
refer this link...
CheckedTextView
this may help you..
[Edit by Faizal] :
Using the toggle() inside the onItemClickListener did the trick :
lv_chatMessages.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3){
CheckedTextView ctv = (CheckedTextView) (((ViewGroup) arg1).findViewById(R.id.txt_chat));
ctv.toggle();
}
});
can you add this into list items
android:descendantFocusability="blocksDescendants"
android:focusableInTouchMode="false"
Since, you are using a custom adapter, you'll have to maintain the status of the checkbox in the getView() method of the custom adapter.
What you could probably do is to add another Boolean field to your ArrayList of Objects which you use to populate the adapter and check that value in the getView() method. to Something like :
if(status) {
checkBox.setChecked(true);
}
Also, update the status variable using OnCheckedChangeListener().
This method will let you toggle status and also ensure that the checkbox status is maintained even when a list item goes out of the view.
Edit 1 : When not using a custom adapter. This is how I did it.
ListView rendererList;
ArrayList<String> friendlyNames;
friendlyNames = new ArrayList<String>();
rendererList = (ListView) dialog.findViewById(R.id.rendererList);
ArrayAdapter rendererSelectionAdapter = new ArrayAdapter<String>(activity,R.layout.custom_list_layout, friendlyNames);
rendererList.setAdapter(rendererSelectionAdapter);
rendererList.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
custom_list_layout was the same layout which android provides, however, I had to make slight modifications so I copied the default file and edited.
here is the custom_list_layout :
<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#android:id/text1"
android:layout_width="match_parent"
android:layout_height="?android:attr/listPreferredItemHeightSmall"
android:background="#color/white"
android:checkMark="?android:attr/listChoiceIndicatorSingle"
android:gravity="center_vertical"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:textSize="#dimen/dialog_box_button_textsize" />
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 this ListView that just needs to show data.
So I don't want to make it clickable.
First I've tried changing XML listview to:
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:clickable="false" >
But it didn't work.
So to solve my problem I set through code:
list.setSelector(android.R.color.transparent);
but I can't believe there's no better solution. Any idea?
Here it is, following the comment:
One way to do so is:
ListView.setOnClickListener(null); OR
You can add android:focusable="false" android:focusableInTouchMode="false" OR
another way in the layout android:listSelector="#android:color/transparent"
Cheers.
Just override isEnabled(position) in your adapter and return false
#Override
public boolean isEnabled(int position) {
return false;
}
override the below method. Return false to say all the items are not clickable.
#override
public boolean areAllItemsEnabled() {
return false;
}
And override below method to return which item is not clickable
public boolean isEnabled(int position) {
if(position == your_item_pos) {
return false;
}
return true;
}
android:listSelector="#android:color/transparent"
it changes the on-clicked color to same as when it is not clicked!
so it appears as if it is plain text...it's a work around.
Just copy this method in your adapter class.
Nothing to do .........
#Override
public boolean isEnabled(int position) {
return false;
}
You may set any condition to make some selected item unclickable.
#Override
public boolean isEnabled(int position) {
//Y for non clickable item
if(data_list.get(position).equalsIgnoreCase("Y"))
{
return false;
}
return true;
}
android:focusable="true"
to any of the item inside listview now listview wont clickable
You could use
yourListView.setOnItemClickListener(null);
Just set android:enabled="false" to the listview and it would do the trick..why to unneccesary keep overriding methods..
Easy way:
listView.setSelector(android.R.color.transparent);
Try this code
In Adapter.getView()
i.setOnClickListener( null );
i.setLongClickable( false );
i.setClickable( false );
In fact,
#override isEnabled() and
setOnClickListener(null)
setClickable(false)
setLongClickable(false)
There are not working for me.
I solve it by override performItemClick
#Override
public boolean performItemClick(View view, int position, long id) {
if(!clickAble){
return false;
}
return super.performItemClick(view,position,id);
}
This is because your ListView item may have a focusable or clickable element, please try the following approach either in XML Layout file or in code:
Add this attribute to the root ViewGroup element of your ListItem XML file (i.e. LinearLayout, RelativeLayout, ...) :
android:descendantFocusability="blocksDescendants"
Add this line to your List Adapter method which is responsible for creating/recycling the list item (most probably getView() or newView()), while parent is the ViewGroup of list item:
parent.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
Only using list.requestFocusFromTouch() in the onResume() method of the containing fragment worked for me.
¯\(ツ)/¯
I have this ListView that just needs to show data. So I don't want to make it clickable.
I have done this in one of my projects, and the sample bellow works fine.
Basically, you just need:
a data source (ArrayList, for example)
a ListView Widget
an ArrayAdapter, in order to bind the data source with the ListView
MainActivity.java
package com.sample.listview;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;
public class SecondActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// data source
String[] arrayData = {"Debian", "Ubuntu", "Kali", "Mint"};
// ListView Widget from a Layout
ListView listView = (ListView) findViewById(R.id.mainListView);
// an ArrayAdapter (using a layout as model for displaying the array items)
ArrayAdapter aa = new ArrayAdapter<String>(this, R.layout.main_list_item_layout, arrayData);
// binding the ArrayAdapter with the ListView Widget
listView.setAdapter(aa);
}
}
activity_main.xml
--->Make sure that the ListView Widget is using wrap_content for layout_width and layout_height
<?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:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.sample.listview.MainActivity">
<ListView
android:id="#+id/mainListView"
android:layout_width="wrap_content" <---- HERE
android:layout_height="wrap_content" <---- HERE
/>
</LinearLayout>
main_list_item_layout.xml
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/mainListItem"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textColor="#ff0000"
android:textSize="20sp"
>
</TextView>
That's it: a ListView not clickable, just presenting data on the screen.