I have a list view and a custom adapter for it. It works all perfect but now I want to add something like a non clickable label, if a condition is true. But if the condition is true it should also display the normal list item. And this is my problem I don't know how I can add the label and afterwards the normal item.
I am a beginner and I tried a lot but I didn't get it.
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView;
if (position == 3){
rowView = inflater.inflate(R.layout.event_date, parent, false);
TextView date = (TextView) rowView.findViewById(R.id.event_date);
// set text
} else {
rowView = inflater.inflate(R.layout.events_list, parent, false);
TextView title = (TextView) rowView.findViewById(R.id.event_title);
// set text
}
return rowView;
}
BaseAdapter has a method called isEnabled() which you can override. You can use that to assign if the specific position is clickable or not.
#Override
public boolean isEnabled(int position) {
if (position == 3) {
return false;
} else {
return true;
}
}
You will also need to declare that not all the items are enabled using areAllItemsEnabled().
#Override
public boolean areAllItemsEnabled() {
return false;
}
If you just need the label to appear beside the list when a certain condition is met you could create a label in the XML for the page and set its visibility.
eg Label a = findViewById(R.id.labela);
a.setVisibility(View.GONE);
put this in the "if statements" you have created to control the label and set the listview to display the value you want and make it clickable or unclickable accordingly.
lv.setEnabled(false);
Related
I was setting the onClickListener for the ListView, and I have set it in each activity at first and it works. For fun I thought of trying to set onClickListener somewhere else to find more then one solution. So I write the onCLickListener in the getView method of the arrayAdapter.
#Override
public View getView(int position, View convertView, ViewGroup parent) {
//Checking if there is a View present for reusing if not inflate one.
View listItemView = convertView;
if (listItemView == null) {
listItemView = LayoutInflater.from(getContext()).inflate(R.layout.list_view, parent, false);
}
//getting the current position of the word object in the View
final Word currentWord = getItem(position);
//getting the text view resource for setting our desired text.
TextView mivok = listItemView.findViewById(R.id.mivokTranslation);
mivok.setText(currentWord.getmMiwokTrans());
TextView defaultTran = listItemView.findViewById(R.id.defaultTranslation);
defaultTran.setText(currentWord.getmDefaultTrans());
ImageView imageView = listItemView.findViewById(R.id.image);
//Checking if the View has an Image resource, if yes then setting the correct image.
if (currentWord.checkImageResource == 0) {
imageView.setImageResource(currentWord.getmImageResource());
} else {
imageView.setVisibility(View.GONE);
}
// Set the theme color for the list item
View textContainer = listItemView.findViewById(R.id.text_container);
// Find the color that the resource ID maps to
int color = ContextCompat.getColor(getContext(), mColorResourceId);
// Set the background color of the text container View
textContainer.setBackgroundColor(color);
listItemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mediaPlayer = MediaPlayer.create(getContext(),currentWord.getmAudioResource());
mediaPlayer.start();
}
});
return listItemView;
}
While doing I though it won't work. Because as far as I have understood the getView method it set the view on the listView when we return the listItemView at th end. But it worked how can a clickListener event response to an activity that is yet to be added.
Inside getView you simply assign a listener to the returned view. Why would it have not worked? It doesn't matter when you assign a listener - it's an object of anonymous class that is "saved" by the view for later use.
I have a List view with a custom adapter (imageviews), in the same activity I have a header and footer, the listView is between those.
What I want is to add a button as the last item of the list view so when you arrive to the last item it appear, i cant add the button outside because it wont scroll
Sorry about my english
Regards
use ListView.addFooterView() to add view as a footer which is visible only in the end of the list:
http://developer.android.com/reference/android/widget/ListView.html#addFooterView(android.view.View)
If you already have a custom adapter class implemented, the solution is rather simple. Based on an xml layout implemented for your list-view rows which contains both a Button and an ImageView, you can hide/display them in the adapter's getView() method based on the index. This is a code sample, which I currently don't have the chance to test and might not be the most efficient solution, but it should give you an idea:
class CustomAdapter extends SimpleAdapter {
[...]
#Override
public int getCount() {
// number of images to be displayed + 1 for the button
return images.length + 1;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final View row = inflater.inflate(R.layout.row, parent, false);
final ImageView imageView = (ImageView) row.findViewById(R.id.image);
final Button button = (Button) row.findViewById(R.id.button);
if (position == getCount() - 1) {
// The last element
imageView.setVisibility(View.GONE);
// set an OnClickListener on the button or whatever...
} else {
button.setVisibility(View.GONE);
// do your regular ImageView handling...
}
return row;
}
}
I have AlertDialog with single choice list.
I want to put some 'fake' items inside - like labels of following items. I'm using different layout for regular item and for 'label' item. It it OK.
My problem is: How to make labels NON clickable?
Here is my getView code:
// #Override
public View getView(int position, View convertView, ViewGroup parent)
{
if (m_data.get(position).BaseElementType == ElementType.Divider)
{
convertView = m_li.inflate(this.m_groupResurceID, null);
TextView post = (TextView)convertView.findViewById(R.id.text1);
post.setText(m_data.get(position).TypeToString());
post.getClickable();
}
else
{
convertView = m_li.inflate(this.m_itemResurceID, null);
TextView post = (TextView)convertView.findViewById(R.id.text1);
post.setText(m_data.get(position).Header);
ImageView img = (ImageView)convertView.findViewById(R.id.image1);
Drawable dr = m_data.get(position).TypeToIconId();
dr.setColorFilter(BGMapsApp.IconColor, PorterDuff.Mode.SRC_ATOP);
img.setImageDrawable(dr);
}
The answer is so simple!
Just put this to adapter code:
public boolean isEnabled(int position)
{
//return super.isEnabled(position);
return (m_data.get(position).BaseElementType != ElementType.Divider);
}
Now some items become non clickable :)
I have custom groupViews that need to change state when they are expanded and collapsed.
If the same group view is expanded it toggles between two states.
The problem i'm having is that the expand method seems to be pulling up some cached version of the views because my updates aren't visible after calling expandGroup.
If my listener returns true (handles the whole event itself) without calling expandGroup the update does happen. So something is happening with expandGroup that only allows cached view to be drawn.
I have tried invalidating() just about everything. I've tried firing off data update events on the List View. i've tried all this other stuff as well:
expandableList.setGroupIndicator(null);
expandableList.setAlwaysDrawnWithCacheEnabled(false);
expandableList.setWillNotCacheDrawing(true);
expandableList.setItemsCanFocus(false);
no luck on any of those :(
Here's my onClick code:
expandableList.setOnGroupClickListener(new OnGroupClickListener() {
public boolean onGroupClick(ExpandableListView parent, View v,
int groupPosition, long id) {
MusicTrackRow mt = (MusicTrackRow) v;
if (mt.isPlaying == true) {
mt.setPaused();
} else {
mt.setPlaying();
}
mt.invalidate();
parent.invalidate();
trackAdapter.notifyDataSetInvalidated();
//need to call expandGroup if the listener returns true.. if returning false expandGroup is //returned automatically
expandableList.expandGroup(groupPosition); //no view refresh
return true;
Found a solution finally!
When the expandable list is expanded a call to getGroupview in the adapter is made for every group on the list.
That is the place where you want to effect changes.
the isExpanded argument lets you determine which group view is expanded.
Then you can do stuff that looks like this:
public View getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
View v;
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) getBaseContext()
.getSystemService(LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.expandablelistitem, null);
} else {
v = convertView;
}
int id = (!isExpanded) ? R.drawable.list_plus_selector
: R.drawable.list_minus_selector;
TextView textView = (TextView) v.findViewById(R.id.list_item_text);
textView.setText(getGroup(groupPosition).toString());
ImageView icon = (ImageView) v.findViewById(R.id.list_item_icon);
icon.setImageResource(id);
return v;
}
An activity has a Button and a ListView.
Initially, only the Button is visible. When the button is pressed, the ListView is displayed.
When displayed, is it possible for me to show one particular item as selected/focussed?
A use case could be that suppose it is a list of language settings and when the list opens, the currently selected language must be shown as highlighted.
If I know the index of the item, how to set it as focused on display?
I post my solution, because google still doesn't know the answer.
getListView().setItemChecked(selectedGroupIndex, true);
In short, ListView::setSelection(int position) is what you need. However, depending on whether the device is in touch mode or not, it may or may not have visual effect (background highlighting). For more details, refer to Android ListView Selection Problem
If you use an Adapter for your ListView add this code to your adapter:
public class MyAdapter extends ArrayAdapter<MyClass> {
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater inflator = (LayoutInflater) getContext()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
rowView = inflator.inflate(R.layout.my_adapter, null);
} else {
rowView = (View) convertView;
}
//...
// set selected item
LinearLayout ActiveItem = (LinearLayout) rowView;
if (position == selectedItem){
ActiveItem.setBackgroundResource(R.drawable.background_dark_blue);
// for focus on it
int top = (ActiveItem == null) ? 0 : ActiveItem.getTop();
((ListView) parent).setSelectionFromTop(position, top);
}
else{
ActiveItem.setBackgroundResource(R.drawable.border02);
}
}
private int selectedItem;
public void setSelectedItem(int position) {
selectedItem = position;
}
}
In your Activity:
myAdapter.setSelectedItem(1);
I am using an Adapter and didn't want to set custom background colors, but use the android:state_selected in drawable xml. SetSelection didn't work for me, but maybe that's also since I needed SetNotifyDataChanged which shows that the Selected State is not persistent.
I also found that the Selected state for an item in a ListView is not persistent, since SetNotifyDataChanged results in updating the ListView layout which clears them all. Setting the item to Selected in the Adapter's GetView is too soon too.
Eventually I set the Selected state for the view of the selected item after the layout of the listview has been changed, which is when LayoutChange event is being triggered (in Java it's probably attaching a to OnLayoutChangeListener of the ListView).
To make it really easy I store the view of the selected item as Adapter's SelectedItemView.
In the ListView's LayoutChange eventhandler I just set the adapter's SelectedItemView.Selected to true.
Here's the code from my Activity where I set the Adapter for the ListView and also subscribe to LayoutChange (or in Java attach an OnLayoutChangeListener)
ringTonesListView.Adapter = ringTonesListAdapter;
ringTonesListView.LayoutChange += (s, layoutChangeArgs) => {
//At this stage the layout has been updated and the Selected can be set to true for the view of the selected item. This will result in android:state_selected logic to be applied as desired and styling can be completely done per layout in Resources.
ringTonesListAdapter.SelectedItemView.Selected = true;
};
Here's my code for the Adapter:
public class RingTonesListAdapter : BaseAdapter<RingToneItem>
{
List<RingTone> Items { get; set; }
public override View GetView(int position, View convertView, ViewGroup parent)
{
View view = convertView;
// re-use an existing view, if one is available
// otherwise create a new one
if (view == null)
{
view = Context.LayoutInflater.Inflate(Resource.Layout.AlertSoundItem, parent, false);
view.Click += SelectRingTone;
}
RingTone ringTone = this[position];
if (ringTone.Selected)
{
//==> Important
//Store this view since it's the view for the Selected Item
SelectedItemView = view;
//Setting view.Selected to true here doesn't help either, since Selected will be cleared after.
}
return view;
}
private void SelectRingTone(object sender, EventArgs args)
{
View view = (View)sender;
string title = view.FindViewById<TextView>(Resource.Id.ringToneTitle).Text;
RingToneItem ringToneItem = Items.First(rt => rt.Title == title);
if (!ringToneItem.Selected)
{
//The RingTone was not selected and is selected now
//Deselect Old and Select new
foreach (RingToneItem oldItem in Items.Where(rt => rt.Selected))
{
oldItem.Selected = false;
}
// Select New RingTone
ringToneItem.Selected = true;
//Update the ListView.
//This will result in removal of Selected state for all Items when the ListView updates it's layout
NotifyDataSetChanged();
}
//Now play the test sound
NotifierService.TestSound(Context, ringToneItem);
}
public View SelectedItemView { get; set; }
}