I saw an app that had a nice menu structure which I want to replicate in my own app and wanted to know how you think it's done and how I should approach it. Here's a screenshot:
It's from the CRM mobile app (MECRM) and to me, it appears to be a ListView with headers and images. But I'm wondering are they images or buttons with images as a background because of 2 things;
1.) the first image "Announcements" is cut off so if that was an ImageView, I'm not too sure if it would do the same.
2.) The Opportunity image has a different image when pressed (as do all the other images).
I guess my question is what controls would I need use to replicate this?
This sort of view is absolutely possible using ListView
You're going to need to implement your own ListAdapter with custom getView behavior.
Based on the position of the view, you can either render an inactive divider view (that won't be clickable), or you can then render a gridview for the appropriate category. This tutorial can get you started on implementing custom adapters with getView.
Here's some sample code on what getView might look like
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
boolean isDivider = false //TODO logic here
if (isDivider){
if (v == null) {
LayoutInflater li = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = li.inflate(R.layout.custom_adapter_item, null);
}
Map<String, String> item = items.get(position);
initView(v, item);
return v;
} else{
View v = null //TODO init divider view here
return v;
}
}
private void initView(View v, Map<String, String> item) {
String[] keys = DummyData.columns;
((TextView) v.findViewById(R.id.value_left)).setText(item.get(keys[0]));
((TextView) v.findViewById(R.id.value_right)).setText(item.get(keys[1]));
}
You're going to have to inflate your gridview layout where I inflate my custom_adapter_item, but this is the framework for a custom listview with complex list items
Your view hierarchy will end up looking something like this
ListView
Category1Header (LinearLayout))
Title (textbox)
Category1Contents (Gridview)
Cat1Cont1 (LinearLayout)
icon (image)
description (textbox)
Category2Header
You get the idea
It seems a Collection of GridViews with 5 columns. ELement of columns are TextView, and ImageView.
I think to get this type of layout list view is not sufficient.
You have to use ScrollView as parent, TextView and GridView as one layout and each this type of layout as children in ScrollView as below.
child_view
<LinearLayout vertical >
<TextView />
<GridView />
</LinearLayout>
main_view
<ScrollView>
<child_view />
<child_view />
<child_view />
.......
</ScrollView>
I hope it may help you.
For something like this I wouldn't recommend Listview as a base. Listview is usefull if you have a lot of similar items that should react in a similar way. For small qty. Of items with a lot of variation it is not your best choice.
As basis I would use linearlayout or relative layout (depending on how you want to react on different screen sizes).
I would style TextViews with an according 9-patch background to look like the headers.
For the buttons I would use the Button widget with a selector as android:background.
Therefore create a XML file with below code in your drawable folder and exchange the drawable with the names of your drawables.
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true" android:state_pressed="false" android:drawable="#drawable/btn_add_sel0" />
<item android:state_focused="true" android:state_pressed="true" android:drawable="#drawable/btn_add_presssel0" />
<item android:state_focused="false" android:state_pressed="true" android:drawable="#drawable/btn_add_press0" />
<item android:drawable="#drawable/btn_add_norm0" />
</selector>
Related
I have a list with elements that use a custom layout which consists of a text view and an image view. For this, I follow ViewHolder pattern like explained here. The image views display one of two icons and I want to change the icon of the clicked image view.
So my first approach was to define the on click listener of the ImageViews in the overridden getView function of my adapter class. The problem is that when the icon of the first ImageView changes and I scroll down to the last its icon changed as well. This question here was not helpful.
Here I found that it's not the best way to handle the click in the getView function but it's better to do it in the listView.setOnItemClickListener. I tried it but I am not able to find out whether an ImageView was clicked or not as the parent object holds the list item and the view parameter the LinearLayout in which the ImageView is contained (even when I click directly in the ImageView). Setting android:focusable="false" of the outer LinearLayout as it is suggested here did not help.
I'm sure someone must have had this issue / use case but I'm not able to find a solution. So, what's the best way to handle the click of the ImageView in my custon list item view?
Try adding the following attributes to the clickable ImageView instead of its ViewGroup, your LinearLayout:
android:focusable="false"
android:focusableInTouchMode="false"
... and as far as updating UI in a AdapterView/ListView/RecyclerView goes, you should make good use of an int flag that tracks the position of the list item that was clicked, and then set it as a conditional statement in getView() before invoking notifyDataSetChanged(), since "every other" row will be updated, especially in lists of say, 100 rows.
I actually answered this in a similar question here and here.
If you have two icons, you can simply put a custom checkbox instead of an imageview :
<CheckBox
android:id="#+id/customchechecbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/checkbox_selector"
android:button="#android:color/transparent" />
checkbox_selector :
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="#drawable/checkbox"
android:state_checked="false"/>
<item android:drawable="#drawable/checkboxselected"
android:state_checked="true"/>
<item android:drawable="#drawable/checkbox"/>
</selector>
I'm a bit new in Android, but I know the very basics from it, at least for the custom listview.
I was wondering, searching without much success, if there's a chance to make that items from the sides could have other styles. I'll explain me.
I've got an Horizontal listview. It shows 3 items (one in the middle and one half-cutted on each of the sides). Every item has it's own image with text below. I would like to make those items from the side have different stylings, like image with an opacity and text visibility gone.
May there's a way to know which item is in front and make it the reverse way, the layout with all text hidden and images with opacity, and the current item displayed (the middle one) with text visible and without opacity.
Edit: an schema of what I would like to reach (if possible of course)
You will have to create one Separate child.xml file to design row Element and then by the Help of Adapter you will have to pass every view to Adapter class.
this one is sample code for given to get your view in adapter class.
public View getView(int position, View convertView, ViewGroup parent) {
View rowView = convertView;
// reuse views
if (rowView == null) {
LayoutInflater inflater = context.getLayoutInflater();
rowView = inflater.inflate(R.layout.rowlayout, null);
// configure view holder
ViewHolder viewHolder = new ViewHolder();
viewHolder.text = (TextView) rowView.findViewById(R.id.TextView01);
viewHolder.image = (ImageView) rowView
.findViewById(R.id.ImageView01);
rowView.setTag(viewHolder);
}
Please check this website for more detail: http://www.vogella.com/tutorials/AndroidListView/article.html
In res/values/ folder style.xml file
create
<style name="CustomFontStyle">
<item name="android:layout_width">fill_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:capitalize">characters</item>
<item name="android:typeface">monospace</item>
<item name="android:textSize">12pt</item>
<item name="android:textColor">#00FF00</item>/>
</style>
then use in your view
<TextView
android:id="#+id/text_id"
style="#style/CustomFontStyle"
android:text="#string/hello_world" />
i have a android listview. i want to change listview item background when i click one listview item.
and then previous selected item must go back to default background. this means only one item has to be selected.
i have searched it for a long time. i can change background of selected item using onItemClick()
but i can't change previous selected item. for example, if i select second item, it was changed. and then i select third item. oh my god! it is changed too! what can i do for this. how can i get the previous position?
here is my android code.
private class ListViewItemClickListener implements
AdapterView.OnItemClickListener {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
TextView title = (TextView) view.findViewById(R.id.title);
title.setBackgroundResource(R.drawable.list_shape);
}
}
You should use the built in methods of selecting items in a listview. Manually changing the background is prone to error as you have found.
Add this attribute to the root view in your listview item xml
android:background="?android:attr/activatedBackgroundIndicator"
then call setItemChecked(x, true) on your ListView where x is the position of the item you want to be selected.
Ensure your listview has a ChoiceMode set that allows selection (such as "SingleChoice")
When I have this in a similar example I have a global field named:
selectedListItem;
This would be updated in your onitemClickListener and the previous item would then have it's background returned to the default.
So to update your code:
private class ListViewItemClickListener implements
AdapterView.OnItemClickListener {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
//First update the previously selected item if one has been set
if(selectedListItem!=null){
TextView previousTitle = (TextView) selectedListItem.findViewById(R.id.title);
previousTitle.setBackgroundResource(R.drawable.list_default_background);
}
//Then update the new one
TextView title = (TextView) view.findViewById(R.id.title);
title.setBackgroundResource(R.drawable.list_shape);
selectedListItem = view;
}
}
So simply initalise selectedListItem as a field in your adapter with the onClickListener as an inner class and have your default background drawable instead of list_default_background .
Alternatively you can track the position numbers instead of the actual view.
EDIT:
To use this method for your list you will also have to keep track of an ID or object instance for your specific list item. In my own solution, in my ListAdapter's getView method I make sure only the list item that matches the ID/instance of the correct item is updated. With your code the way it is you will also find that when you scroll down the view at the same position in this list of visible items is also updated. This is because list view's refer to the list in sets of items, where each set corresponds to the items visible on the screen at any one time.
To update a singular, specific item you would be better suited to using a selector background or indicator as mentioned in the other answers.
HTH
You can change the ListView item colour on clicking it like below. Follow these steps.
(Remember, This is for Custom List View)
Create an XML file in Drawable Folder as Below:
<item android:drawable="#color/orange" android:state_focused="true"/>
<item android:drawable="#color/orange" android:state_pressed="true"/>
<item android:drawable="#drawable/listview"></item>
Choose your own resources.
While implementing Custom ListVIew, you'll have additional layout for Custom List Item design. Below is such an Example.
<ImageView
android:id="#+id/imageView1"
android:layout_width="60dp"
android:layout_height="60dp" />
<TextView
android:id="#+id/textView1"
android:layout_width="fill_parent"
android:layout_height="60dp"
android:layout_toRightOf="#+id/imageView1"
android:background="#drawable/listselect_picture"
android:gravity="center"
android:text="TextView"
android:textColor="#drawable/select_txtcolor"
android:textSize="16sp" />
In Above code I have put the set the XML file from Step 1 as "background" attribute. This will work as you want to.
Additionally if you want to change the text colour on ListItem selection as well, use below XML code and set that XML file as "TextColor" attribute.
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:color="#android:color/white"/>
<item android:state_focused="true" android:color="#android:color/white"/>
<item android:state_pressed="true" android:color="#android:color/white"/>
<item android:color="#android:color/black"/>
</selector>
The code above will change the text color to while on selection and revert to original when unclicked.
Can somebody please help me to change the text color of list view without using any base adapter. I have used android.R.layout.simple_list_item_single_choice for displaying option button, But by default the text inside the list view is displaying in white color i need to change it to black color. Is there any way to change the text to black without using custom adapter. I have pasted the code which i used to create list view with option button.
ListView lvCheckBox = (ListView)findViewById(R.id.lvCheckBox);
save = (ImageView)findViewById(R.id.button1);
lvCheckBox.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
lvCheckBox.setAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_list_item_single_choice, values));
Just change the default layout of the ListView item
Instead of :
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_listview_item, list);
use
adapter = new ArrayAdapter<String>(this, R.layout.customLayout, list);
and customLayout.xml:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/listTextView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textColor="#color/black"
android:textSize="20dp" />
Use this code.
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,R.layout.custom_spinner_textview_layout, from);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinnerAlarmTone.setAdapter(adapter);
Xml LayoutFile
< ?xml version="1.0" encoding="utf-8"?>
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/text1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="16.0sp"
android:textColor="#color/black"
android:gravity="left"/>
Instead of default android.R.layout.simple_list_item_single_choice you can use a custom xml file consisting of a textview and pass this xml file to ArrayAdapter. In this way you can easily change textview color. But still I recomend you to go for a custom adapter for more flexibility.
Yes! you are correct, I tried your code. By default it shows white color background and Textcolor also. when we press it showing text because of selector color. so it becomes visible to us. I accept the above answer. but we can made our customization in particular portion only. no need to create separate Layout or Textview.
ListView lvCheckBox = (ListView)findViewById(R.id.lvCheckBox);
save = (ImageView)findViewById(R.id.button1);
lvCheckBox.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
lvCheckBox.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_single_choice, values) {
#Override
public View getView(int position, View convertView, ViewGroup parent) {
CheckedTextView checkedTxtView = (CheckedTextView) super.getView(position, convertView, parent);
String yourValue = values.get(position);
checkedTxtView.setText(yourValue);
checkedTxtView.setTextColor(this.getResources().getColor(android.R.color.black));
return textView;
}
});
I have created sample hello world project and tried this. It works for me. I hope it would help u to achieve your task.
And one more thing, You need CheckedTextView so you are using android.R.layout.simple_list_item_single_choice. If your creating custom layout as per above some examples, you have to use CheckedTextView in those custom layout design. because, In above examples they have used simple textview only. So care on that.
You could use Custom Selector, for example, for listview:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" +
android:drawable="#drawable/listitem_pressed" />
<item android:state_focused="true" android:drawable="#drawable/listitem_selected" />
</selector>
Reference:
Another Ask
Bro one solution is that you change the background color black of listview your text automatically will b visible.
or you have to set a custom adapter on your listview.
when you inflate the custom layout you can set the textview color according to your need.
I am using multiple choice ListView items. The user can select multiple items. So I wanted to highlight the items selected by the user by changing either the text color or background color of the list row. I have gone through stack overflows links but didn't get the proper solution. When I am trying to do it, it is randomly changing any unselected item background color. Help!!!
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
videocursor.moveToPosition(position);
v.setBackgroundColor(Color.parseColor("#80B7DBE8"));
SaveSelections();
}
That randomly changing background color is due to the reason that ListView recycles views in its list to avoid unnecessary memory consumptions. You need to provide your own custom adapter in which you need to override getView method and perform some checks to highlight only those list items who have some kind of flag set to true for background color
Far better than the above suggestions is to use a selector, also known as a state-list drawable. That way, the OS takes care of all of the business of color highlighting, etc.
more explicitly, take the following xml and save it under res/drawable as something like li_background.xml (I'm using images, but feel free to swap out colors as is appropriate to your situation)
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:state_focused="true"
android:drawable="#drawable/list_item_pressed" />
<item android:state_pressed="true"
android:drawable="#drawable/list_item_pressed" />
<item android:state_selected="true"
android:state_activated="true"
android:drawable="#drawable/list_item_selected" />
<item android:state_activated="true"
android:drawable="#drawable/list_item_selected" />
<item android:state_selected="true"
android:drawable="#android:color/black" />
<item android:drawable="#android:color/transparent" />
</selector>
and set the background of All ListItems in the ListView to R.drawable.li_background. if your listView is properly configured for multiple selections (android:choiceMode="multipleChoice" or listView.setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE); if you prefer) then android will take care of the rest. This stuff isn't well documented, I had a hard time finding the solution and I see similar questions all the time, but the relevant dos are here and here
Wagas is correct. In your adapter's getView, you are passed a View (called convertView by Eclipse's autocomplete). This is because ListViews recycle the views for each row. If you set a property for a given View, it will retain that property when it is recycled.
For this reason, you should never set the properties of anything in a given row's View outside the getView method of the Adapter backing the ListView.
There are a number of ways you could handle this, but the basic idea is that you want to set some piece of data that uses the position passed in to onItemClick to set a flag. Then check the flag in the Adapter's getView to decide how to set the background for the row's View.
For example, if only one item can be selected, you might just set a member variable, say mPosition on the Adapter itself to the position passed in to onItemClick, and then check in getView if position == mSelectedPosition to decide how to set the View. If multiple items can be selected, perhaps you set a member variable on each object contained in the Adapter.
You probably should override getView() in the adapter, and change the row background color in there.
An example:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView != null) {
if (mSelectedPositions.contains(position)) {
convertView.setBackgroundColor(Color.parseColor("#3fa9f5"));
} else {
convertView.setBackgroundColor(Color.parseColor("#ffffff"));
}
}
return super.getView(position, convertView, parent);
}
in onItemClick() just use adapter.notifyDataChange(); also set a flag to true;
in the getView() of your CustomAdapter use boolean flag to know whether the row was selected or not.
Then just check that flag and proceed as you want
i.e.,
if(flag){
v.setBackgroundColor(Color.parseColor("#80B7DBE8"));
}else{
v.setBackgroundColor(Color.parseColor("#FF0000"));
}