I have an adapter which extends ArrayAdapter> filling fragment layout with multiple choices each time.
The problem is that sometimes background disappears completely on items choose before, or all other items. If you check this image
http://i.imgur.com/S1KEfM1.png
you can see that ccc option lost background. Layout inflates this Relative Layout
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="67dp"
android:background="#drawable/selectable_background_example"
android:descendantFocusability="blocksDescendants"
android:gravity="center_vertical"
android:paddingLeft="20dp"
android:paddingRight="10dp" >
With this background xml
<selector xmlns:android="http://schemas.android.com/apk/res/android" android:exitFadeDuration="#android:integer/config_mediumAnimTime">
<item android:drawable="#drawable/list_focused_example" android:state_focused="true" android:state_pressed="false"/>
<item android:drawable="#drawable/pressed_background_example" android:state_pressed="true"/>
<item android:drawable="#drawable/pressed_background_example" android:state_selected="true"/>
<item android:drawable="#drawable/pressed_background_example" android:state_activated="true"/>
<item android:drawable="#drawable/new_strip"/>
</selector>
Pressed_background_example
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<solid android:color="#color/pressed_example" />
<stroke
android:width="3dp"
android:color="#color/pressed_example" />
<padding
android:bottom="1dp"
android:left="1dp"
android:right="1dp"
android:top="1dp" />
</shape>
Pressed_example
<resources>
<color name="pressed_example">#CCCC0000</color>
</resources>
And new_strip is basically just that background white image with border, and list_focused_example is image for checkbox pressed.
GetView in my class
public View getView(int position, View convertView, ViewGroup parent) {
Holder mhHolder;
if (convertView == null) {
mhHolder = new Holder();
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.row_a, parent, false);
mhHolder.txtValue = (TextView) convertView.findViewById(R.id.txtValue);
mhHolder.txtCheckbox = (CheckBox) convertView.findViewById(R.id.checkBox1);
mhHolder.txtText = (TextView) convertView.findViewById(R.id.txtText);
convertView.setTag(mhHolder);
} else {
mhHolder = (Holder) convertView.getTag();
}
HashMap<String, String> hm = values.get(position);
mhHolder.txtValue.setText(hm.get("Value"));
mhHolder.txtText.setText(hm.get("Text"));
mhHolder.txtCheckbox.setVisibility(View.VISIBLE);
//TODO CHANGE WHEN CHECKED IS SEND
mhHolder.txtCheckbox.setChecked(Base.checked[position]);
}
Does anyone have any clue on why the background dissapears on previous selected items or sometimes on all items except the selected one.
I think it´s a kind of bug (or I don't really get the real function).
Anyhow you should try to call
mhHolder.txtValue.setbackground(R.drawable.selectable_background_example);
in your code so that it is executed for each item.
In the end the problem was the image (new_strip). I had to make a drawable the same as the image (which had only white background and gray rounded corners), so that fixed the problem.
Related
I pretty like the selector behavior generated in navigation drawer.
It has ripple effect.
Its ImageView and TextView has proper color, when being selected.
In my dialog, I try to achieve the same effect, by using the following layout.
label_array_adapter.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:background="?android:attr/selectableItemBackground"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal">
<ImageView
android:duplicateParentState="true"
android:id="#+id/image_view"
android:paddingStart="24dp"
android:paddingLeft="24dp"
android:paddingEnd="16dp"
android:paddingRight="16dp"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:src="?attr/labelIconSelector" />
<TextView
android:duplicateParentState="true"
android:textSize="16sp"
android:id="#+id/text_view"
android:layout_width="0dp"
android:width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:textColor="?attr/labelTextViewColorSelector" />
</LinearLayout>
labelIconSelector
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true">
<bitmap android:src="#drawable/ic_label_white_24dp"
android:tint="#color/colorPrimaryBrown" />
</item>
<item>
<bitmap android:src="#drawable/ic_label_white_24dp"
android:tint="#ff757575" />
</item>
</selector>
labelTextViewColorSelector
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:color="#color/colorPrimaryBrown" />
<item android:color="#color/primaryTextColorLight" />
</selector>
In my ArrayAdapter, I try to programmatically select the 1st item via view.setSelected(true)
public class LabelArrayAdapter extends ArrayAdapter<TabInfo> {
private static class ViewHolder {
public final ImageView imageView;
public final TextView textView;
public ViewHolder(View view) {
imageView = view.findViewById(R.id.image_view);
textView = view.findViewById(R.id.text_view);
Utils.setCustomTypeFace(textView, Utils.ROBOTO_REGULAR_TYPE_FACE);
}
}
public LabelArrayAdapter(#NonNull Context context, List<TabInfo> tabInfos) {
super(context, R.layout.label_array_adapter, tabInfos);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = null;
if (convertView == null) {
LayoutInflater inflator = LayoutInflater.from(this.getContext());
view = inflator.inflate(R.layout.label_array_adapter, null);
final ViewHolder viewHolder = new ViewHolder(view);
view.setTag(viewHolder);
// Not sure why this is required.
view.setLayoutParams(new AbsListView.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT, Utils.dpToPixel(48)));
} else {
view = convertView;
}
ViewHolder holder = (ViewHolder) view.getTag();
TabInfo tabInfo = getItem(position);
if (tabInfo == null) {
holder.imageView.setVisibility(View.INVISIBLE);
holder.textView.setText("(No label)");
} else {
holder.imageView.setVisibility(View.VISIBLE);
holder.textView.setText(tabInfo.getName());
}
if (position == 0) {
view.setSelected(true);
} else {
view.setSelected(false);
}
return view;
}
}
This is how I try to show Dialog via DialogFragment.
return new AlertDialog.Builder(getActivity())
.setTitle("Move to")
.setAdapter(new LabelArrayAdapter(this.getContext(), customTabInfos), (dialog, which) -> {
})
.create();
However, it doesn't work as you can see in the following screenshot. The 1st item doesn't look like it is being selected.
May I know, is there anything I had missed out?
How to make a View looks like it is being selected programmatically, if its background is ?android:attr/selectableItemBackground (ListView in AlertDialog)
Update
Using
alertDialog.getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
alertDialog.getListView().setSelection(position);
wouldn't help either.
Here is an approach using a layer list drawable as the background for the view group that represents the item being selected.
First, for API 21+, we define a layer list drawable that displays the selected color when the item is selected. A call to View#setSelected() must be made for this to have an effect.
layer_list.xml (v21)
color/selected is #2000ffe5 for the demos.
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<selector>
<item
android:drawable="#color/selected"
android:state_selected="true" />
</selector>
</item>
<item
android:id="#+id/selectableBackground"
android:drawable="?android:selectableItemBackground" />
</layer-list>
For API < 21, we cannot use android:drawable="?android:selectableItemBackground" in the layer list, so we will fall back to an alternate but similar visual cue.
layer_list < API 21
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<selector android:exitFadeDuration="#android:integer/config_shortAnimTime">
<item
android:drawable="#color/selected"
android:state_pressed="false"
android:state_selected="true" />
<item
android:drawable="#color/selectable_background"
android:state_pressed="true" />
</selector>
</item>
</layer-list>
I use layer-list to create button shape and add image
myshape.xml
<?xml version="1.0" encoding="UTF-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<solid android:color="#FDD400"/>
<corners android:radius="15dp" />
</shape>
</item>
<item>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="#drawable/buy_card_24dp"
android:gravity="center" />
</item>
</layer-list>
I add this myshape.xml as the background resource of an appcompact button using an adapter class since this button is in gridview
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.menu_view_item, null);
TextView textView = (TextView) v.findViewById(R.id.menuName);
AppCompatButton appCompatButton = (AppCompatButton) v.findViewById(R.id.menuImage);
appCompatButton.setBackgroundResource(menuList.get(position).getMenuImage());
textView.setText(menuList.get(position).getMenuName());
return v;
}
and i specify the myshape.xml file in the main class like
ArrayList<MenuGridItem> menuList=new ArrayList<>();
menuList.add(new MenuGridItem("Home",R.drawable.myshape));
but the icon in the button is too small and is it possible to cover the icon some percent of the shape
I was using 24dp material icon now i changed to 48dp...now icon size is almost ok...
I want to set selector on its groupView but when I click selector on groupView it goes to childView in expandable listview..
Here is my expandable listview.
<ExpandableListView
android:id="#+id/lvLeft"
android:layout_width="280dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#color/white"
android:choiceMode="singleChoice"
android:dividerHeight="0dp"
android:listSelector="#drawable/group_indicator"
android:transcriptMode="alwaysScroll
/>
Here is my group_indication.xml.
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/normal" android:state_expanded="true"></item>
<item android:drawable="#drawable/normal"></item>
</selector>
Here is my normal.xml.
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#color/red" />
<padding
android:bottom="5dp"
android:left="5dp"
android:right="5dp"
android:top="5dp" />
</shape>
actually I want to set custom color on groupView in expandable listview but when I click on groupView, custom color set on groupView 's childView. I have attach screen shot which problem I am getting now in which Transaction History is GroupView and My Transaction is childView . Please help me solve this issue. Thanks in advance.
I have solve the problem by Prakash Gavade's answer. here is answer. In expandable listiview adapter, I have added below code.
#Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent)
{
TextView tvUserName = null;
ImageView imgMenuIcon = null;
View drawerView = convertView;
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (groupPosition == 0)
{
drawerView = inflater.inflate(R.layout.profile_image, parent, false);
ImageView ivProfilePic = (ImageView) drawerView.findViewById(R.id.imgProfile);
tvUserName = (TextView) drawerView.findViewById(R.id.tvFname);
TextView tvLname = (TextView) drawerView.findViewById(R.id.tvLname);
}
else if(isExpanded){
convertView.setBackgroundResource(R.color.gray);
}
return drawerView;
}
i wanna set my listview's background like in the link's pic, it should be shown as button but i cant set background separately.
http://www.delta.edu/images/OIT/Android%20List%20View.png
i've tried android:listSelector="#drawable/pic" and this didnt work for me.
i tried tools:listitem="#layout/row" too, but it didnt worked for me.
I hope i was clear about my problem.
Check out a tutorial like this for some hints.
Create an XML file in drawable similar to this:
rounded_corners.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<solid android:color="#00FF00"/>
<corners android:radius="5dp" />
<padding android:left="3dp" android:top="3dp" android:right="3dp" android:bottom="3dp" />
<stroke android:width="3dp" android:color="#00CC00"/>
</shape>
listview_selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="#drawable/rounded_corner" android:state_enabled="true"/>
<item android:drawable="#drawable/rounded_corner" android:state_pressed="true"/>
<item android:drawable="#drawable/rounded_corner" android:state_focused="true"/>
</selector>
Apply it to the ListView Adapter similar to this:
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
PlanetHolder holder = new PlanetHolder();
// First let's verify the convertView is not null
if (convertView == null) {
// This a new view we inflate the new layout
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.row_layout, null);
// Now we can fill the layout with the right values
TextView tv = (TextView) v.findViewById(R.id.name);
holder.planetNameView = tv;
v.setTag(holder);
v.setBackgroundResource(R.drawable.rounded_corner);
}
else
holder = (PlanetHolder) v.getTag();
Planet p = planetList.get(position);
holder.planetNameView.setText(p.getName());
return v;
}
i have StateListdrawable in xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_activated="false" android:drawable="#drawable/ic_checked_off" />
<item android:state_activated="true" android:drawable="#drawable/ic_checked_on" />
<item android:drawable="#drawable/ic_checked_on" android:state_pressed="true" />
<item android:drawable="#drawable/ic_checked_off" />
</selector>
i have GridView images which has StateListDrawable, and programically try to change drawable state with
if(mSelected.contains(photo)){
view.findViewById(R.id.selector).setActivated(true);
}
images which selected changes state, but when i click his state not change, i'm sorry i can't explain what i want, my english is worse
i try to explain it
if mSelected.contains(photo) [state - active] -> [checked_on.jpg] when i click ->
state drawable begins from first and ignoring my programically state changes
==Edit==
Adapter Item --
private View getPhoto(int position, View convertView, ViewGroup parent){
View view = convertView;
if(convertView == null){
view = LayoutInflater.from(mContext).inflate(R.layout.gallery_photo_item, parent, false);
}
ImageView mPhoto = (ImageView)view.findViewById(R.id.photoview);
Photo photo = (Photo) getItem(position - COLUMNS_NUM);
if(mSelected.contains(photo)){
view.findViewById(R.id.selector).setActivated(true); // here i change my drawable state because it's front of my imageView
}
mLoader.displayImage(MediaStore.Images.Media.EXTERNAL_CONTENT_URI + File.separator + photo.id,
mPhoto);
return view;
}
The problem is the order of the states. They are checked top to bottom, and the first one that matches the situation is used. So that means that the first two are always used. This should work:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="#drawable/ic_checked_on" />
<item android:state_activated="false" android:drawable="#drawable/ic_checked_off" />
<item android:state_activated="true" android:drawable="#drawable/ic_checked_on" />
<item android:drawable="#drawable/ic_checked_off" />
</selector>