Android custom drawable state not working - android

I am trying to implement a custom drawable state. I can see the state changing inside my custom view, however visually there is no colour change. Any help appreciated!
Here's my code:
selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res/com.example.test.myapplication">
<item android:drawable="#drawable/defaultt" />
<item android:drawable="#drawable/error" app:my_state="1" />
<item android:drawable="#drawable/success" app:my_state="2" />
</selector>
error.xml
<?xml version="1.0" encoding="UTF-8"?>
<shape
android:shape="rectangle"
xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="3dip" />
<stroke android:width="3dip" android:color="#ff0000" />
<solid android:color="#ff0000"/>
</shape>
attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="MyState">
<attr name="my_state" format="integer" />
</declare-styleable>
</resources>
activity_main.xml
<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:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:orientation="vertical"
android:paddingBottom="#dimen/activity_vertical_margin" tools:context=".MainActivity">
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<com.example.test.myapplication.CustomView
android:id="#+id/view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/selector"
/>
</LinearLayout>
CustomView.java
public class CustomView extends View {
public static final int DEFAULT = 0;
public static final int ERROR = 1;
public static final int SUCCESS = 2;
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
}
private int state = DEFAULT;
private static final int[] VALIDATION_STATE = new int[] { R.attr.my_state };
#Override
protected int[] onCreateDrawableState(int extraSpace) {
if( state == DEFAULT ) {
return super.onCreateDrawableState(extraSpace);
}
final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
if (state > 0) {
Log.d("tag", "state is "+state);
mergeDrawableStates(drawableState, VALIDATION_STATE);
}
return drawableState;
}
public void setState(int state) {
this.state = state;
refreshDrawableState();
}
}
MainActivity.java
public class MainActivity extends ActionBarActivity {
private int mCurrentState = CustomView.DEFAULT;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mCurrentState != CustomView.ERROR) {
((CustomView) findViewById(R.id.view)).setState(CustomView.ERROR);
mCurrentState = CustomView.ERROR;
} else {
((CustomView) findViewById(R.id.view)).setState(CustomView.SUCCESS);
mCurrentState = CustomView.SUCCESS;
}
}
});
}
}

Selector states should be defined as boolean attributes. You can place them directly inside a <resources> element -- you don't need to place them inside a <styleable> element.
res/attrs.xml:
<resources>
...
<attr name="state_mystate" format="boolean" />
</resources>
When you reference the attribute from a selector <item>, a value of true means the state must exist within the current state set while a value of false means the state must not exist. If you don't include a state on the <item> the it doesn't matter whether it exists within the current state set.
When matching is performed on the selector, the items are matched in the order they are defined. If the first item has no states defined, as it does in your example, it will match all possible states and always be matched first. As a result, you should order your selector items as most-specific to least-specific.
The example below is for drawable, but it applies to all selectors (color, etc.).
res/drawable/my_selector.xml:
<selector>
<!-- Matches only state sets that include app:state_mystate
and don't include android:state_pressed. -->
<item app:state_mystate="true"
android:state_pressed="false" ... />
<!-- Matches all state sets that include state_mystate. -->
<item app:state_mystate="true" ... />
<!-- Matches all possible states. -->
<item ... />
</selector>

Related

Coordinating drawable state between parent and child

I have a custom view LockButton which is just a FrameLayout that holds two specific child views. It holds an ImageButton as well as a type of custom view ProgressIndicator. This question centers around the behavior of LockButton and ImageButton. In particular I have added a custom state to the LockButton. The ImageButton has a StateListDrawable for it's source and a ColorStateList for its background.
The problem is when I change the state in LockButton, that change is not displayed in the ImageButton
What am I doing wrong?
LockButton Class:
public class LockButton extends FrameLayout {
private static final int[] STATE_LOCKED = {R.attr.state_locked};
private boolean locked = true;
View button;
public LockButton(#NonNull Context context) {
this(context, null);
}
public LockButton(#NonNull Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
LayoutInflater.from(context).inflate(R.layout.lock_button, this);
button = findViewById(R.id.lock_button_actual);
}
#Override
public void setOnClickListener(#Nullable OnClickListener l) {
button.setOnClickListener(l);
}
#Override
public int[] onCreateDrawableState(int extraSpace) {
final int[] drawableState;
if(locked){
drawableState = super.onCreateDrawableState(extraSpace + 1);
mergeDrawableStates(drawableState, STATE_LOCKED);
} else {
drawableState = super.onCreateDrawableState(extraSpace);
}
return drawableState;
}
public void lock(boolean locked) {
if(this.locked != locked) {
this.locked = locked;
}
refreshDrawableState();
button.refreshDrawableState();
}
public static class ProgressCircle extends View {...}
}
LockButton Layout:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
app:state_locked="true"
android:layout_gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<view class="com.example.LockButton$ProgressCircle"
android:layout_width="68dp"
android:layout_height="68dp"
android:layout_gravity="center"
/>
<ImageButton
android:id="#+id/lock_button_actual"
android:layout_width="#dimen/fab_size"
android:layout_height="#dimen/fab_size"
android:background="#drawable/button_lock_background"
android:src="#drawable/icon_lock_status"
android:tint="#color/white"
android:elevation="6dp"
android:layout_gravity="center"
android:duplicateParentState="true"
/>
</FrameLayout>
Attributes XML:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="lockState">
<attr name="state_locked" format="boolean" />
</declare-styleable>
</resources>
Drawable icon_lock_status.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item app:state_locked="false" android:drawable="#drawable/icon_lock_open" />
<item app:state_locked="true" android:drawable="#drawable/icon_lock_closed"/>
</selector>
Drawable button_lock_background.xml:
<?xml version="1.0" encoding="utf-8"?>
<ripple
xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?android:colorControlHighlight"
>
<item>
<shape android:shape="oval">
<solid android:color="#color/button_lock_color" />
</shape>
</item>
</ripple>
Color button_lock_color.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item app:state_locked="false" android:color="#color/grey_dark" />
<item app:state_locked="true" android:color="#color/vibrant_red" />
</selector>
When I need to change the state, I simply call
lockButton.lock(true); // or false
on the LockButton
I have also tested to see if using default states instead of my custom one would work any better. This did not help. The ImageButton still does not respond to changes in the default states.
Setting a StateListDrawable as a background to the LockButton (FrameLayout) does work. So the state change is working properly on the parent, it is just not reflected in the child.

Make ListView Item Selection remain Stable

How to make ListView Item Selection remain stable ?
<ListView
android:id="#+id/list_slidermenu"
android:layout_height="0dp"
android:layout_width="match_parent"
android:layout_weight="8"
android:layout_gravity="start"
android:scrollbars="none"
android:fastScrollEnabled="true"
android:choiceMode="singleChoice"
/>
You've to make getSelectedIndex() and setSelectedIndex() method in your adapter.
private int selectedIndex;
public int getSelectedIndex() {
return selectedIndex;
}
public void setSelectedIndex(int index) {
this.selectedIndex = index;
// Re-draw the list by informing the view of the changes
notifyDataSetChanged();
}
and then
#Override
public View getView(int position, View convertView, ViewGroup parent) {
.......
// Highlight the selected item in the list
if (selectedIndex != -1 && selectedIndex == position) {
v.setBackgroundResource(R.color.yourColor);
}
return v;
}
and used from onListItemClick(....)
adapter.setSelectedIndex(position);
Another way as #Sun said
Used gradient to make list selection remain stable
gradient_bg.xml:-
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:startColor="#7ecce8"
android:centerColor="#7ecce8"
android:endColor="#7ecce8"
/>
</shape>
gradient_bg_hover.xml:-
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:startColor="#7ecce8"
android:centerColor="#7ecce8"
android:endColor="#7ecce8"
/>
</shape>
list_selector.xml:-
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_selected="false"
android:state_pressed="false"
android:drawable="#drawable/gradient_bg" />
<item android:state_pressed="true"
android:drawable="#drawable/gradient_bg_hover" />
<item android:state_selected="true"
android:state_pressed="false"
android:drawable="#drawable/gradient_bg_hover" />
</selector>
finally in ListView, use listSelector property like below:
android:listSelector="#drawable/list_selector"
I have used gradient to make list selection remain stable
gradient_bg.xml:-
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:startColor="#7ecce8"
android:centerColor="#7ecce8"
android:endColor="#7ecce8"
/>
</shape>
gradient_bg_hover.xml:-
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:startColor="#7ecce8"
android:centerColor="#7ecce8"
android:endColor="#7ecce8"
/>
</shape>
list_selector.xml:-
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_selected="false"
android:state_pressed="false"
android:drawable="#drawable/gradient_bg" />
<item android:state_pressed="true"
android:drawable="#drawable/gradient_bg_hover" />
<item android:state_selected="true"
android:state_pressed="false"
android:drawable="#drawable/gradient_bg_hover" />
</selector>
finally in ListView, use listSelector property like below:
android:listSelector="#drawable/list_selector"
You need to keep track of selected item and accordingly change the background of the list row.
1.Change the selected item's position in item click :
#Override
public void onItemSelected(AdapterView<?> arg0, View arg1,int position, long arg3) {
adapter.setSelectedItem(position);
}
2.Get selected item and set background :
public class AudioAdapter extends ArrayAdapter<Audio> {
Integer selected_position = -1;
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// Your Code
if (position == selected_position) {
// set selected color
v.setBackgroundResource(R.color.yourSelectedColor);
} else {
// set default color
v.setBackgroundResource(R.color.yourDefaultColor);
}
}
public int getSelectedItem() {
return selected_position;
}
public void setSelectedItem(int index) {
this.selected_position = index;
}
}
Hope it helps ツ

Android: custom selector state never gets "true"

I'm struggling with this already from hours and I cannot find a solution, I hope someone can help me.
I have a ListView with a custom adapter extending BaseAdapter and each element of the list extends a LinearLayout containing only a TextView. I started basically from How to add a custom button state.
This is the list_item.xml layout file of the list element:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res/com.example.mypackage"
android:id="#+id/newItem"
app:state_playing="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/item_selector"
android:orientation="horizontal" >
<TextView
android:id="#+id/textview"
style="#style/Text_View_Style_White"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:duplicateParentState="true"
android:ellipsize="marquee"
android:focusableInTouchMode="true"
android:marqueeRepeatLimit="marquee_forever"
android:padding="3dp"
android:scrollHorizontally="true"
android:singleLine="true"
android:textColor="#drawable/item_text_selector" />
</LinearLayout>
Here is the relevant code of the BaseAdapter:
class AlbumListAdapter extends BaseAdapter implements Checkable {
private Context mContext;
public AlbumListAdapter(Context context) {
mContext = context;
}
#Override
public int getCount() {
return listSize; // is a variable
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
AlbumViewHolder albumHolder = null;
if (convertView == null) {
// Inflate the layout
LayoutInflater li = getActivity().getLayoutInflater();
convertView = li.inflate(R.layout.list_item, null);
albumHolder = new AlbumViewHolder(mContext, null);
albumHolder.albumTitle = (TextView) convertView
.findViewById(R.id.textview);
convertView.setTag(albumHolder);
} else {
albumHolder = (AlbumViewHolder) convertView.getTag();
}
albumHolder.albumTitle.setText("Some text in the TextView");
albumHolder.albumTitle.setSelected(true);
if (myBooleanCondition)
{
albumHolder.setPlaying(true);
albumHolder.refreshDrawableState();
for (int i = 0; i < albumHolder.getDrawableState().length; i++) {
if (albumHolder.getDrawableState()[i] != 0)
System.out.println(TAG + " State i = "
+ i + " -> " + getResources().getResourceEntryName(albumHolder.getDrawableState()[i]));
}
}
return convertView;
}
}
and here the list element class extending the LinearLayout:
static class AlbumViewHolder extends LinearLayout {
private static final int[] STATE_PLAYING_SET = { R.attr.state_playing };
private boolean mIsPlaying = false;
TextView albumTitle;
public AlbumViewHolder(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setPlaying(boolean isPlaying) {
mIsPlaying = isPlaying;
}
#Override
protected int[] onCreateDrawableState(int extraSpace) {
final int[] drawableState = super
.onCreateDrawableState(extraSpace + 1);
if (mIsPlaying) {
System.out.println(TAG
+ " - onCreateDrawableState() -> mIsPlaying = "
+ mIsPlaying);
mergeDrawableStates(drawableState, STATE_PLAYING_SET);
}
return drawableState;
}
}
Here is the attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="music">
<attr name="state_playing" format="boolean" />
<attr name="playing" format="boolean" />
</declare-styleable>
</resources>
and here the 2 selectors trying to use the selector state state_playing, one for the background of the LinearLayout of each element (item_selector.xml):
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res/com.example.mypackage">
<item android:drawable="#color/blue_fluo3" app:state_playing="true"/>
<item android:drawable="#color/orange_fluo" android:state_pressed="true" app:state_playing="false"/>
<item android:drawable="#color/orange_fluo" android:state_activated="true" app:state_playing="false"/>
<item android:drawable="#android:color/transparent" app:state_playing="false"/>
</selector>
and one for the textColor of the TextView (item_text_selector.xml):
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res/com.example.mypackage">
<item app:state_playing="true" android:color="#color/orange_fluo"/>
<item android:state_pressed="true" app:state_playing="false" android:color="#color/black"/>
<item android:state_activated="true" app:state_playing="false" android:color="#color/black"/>
<item app:state_playing="false" android:color="#android:color/white"/>
</selector>
The result is the same for both: the state_playing seems to work but only in state "false", because if I add a line at the beginning of the selector state list with <item app:state_playing="false" android:color="#color/yellow"/> for the text selector and <item android:drawable="#color/red" app:state_playing="false"/> for the background selector everything is working as expected, I can see the LinearLayout with red background and the text with yellow text!
I really don't know what to try anymore... (even if I set the property by default to the objects (app:state_playing="true") in the xml layout it doesn't work!
Any help, hint or experience sharing is extremely appreciated!
It looks okay to me,but I'd suggest setting duplicateParentState in the container layout as below. I have a vague memory of having issues along those lines myself...
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res/com.example.mypackage"
android:id="#+id/newItem"
android:duplicateParentState="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/item_selector"
android:orientation="horizontal" >
<TextView
android:id="#+id/textview"
style="#style/Text_View_Style_White"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:duplicateParentState="true"
android:ellipsize="marquee"
android:focusableInTouchMode="true"
android:marqueeRepeatLimit="marquee_forever"
android:padding="3dp"
android:scrollHorizontally="true"
android:singleLine="true"
android:textColor="#drawable/item_text_selector" />

How do I ensure change the background of a selected GridView cell?

In Android, I have a GridView - each cell in the GridView is an ImageView. When a user clicks on a cell, I would like that cell to be "selected" (have its background turn blue), and all other cells to "unselect" (have their backgrounds turn white).
I have implemented the following background drawable, but it only changes the background while the cell is pressed:
<?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/iconborder_selected" /> <!-- pressed -->
<item android:drawable="#drawable/iconborder_unselected" /> <!-- default -->
</selector>
EDIT: Here is my adapter code for the GridView.
class IconAdapter extends BaseAdapter {
private Context context = null;
private List<Drawable> icons = new ArrayList<Drawable>();
public IconAdapter(Context context) {
this.context = context;
for (Field f : R.drawable.class.getFields()) {
String path = f.getName();
if (path.contains("icon_")) {
int id = context.getResources().getIdentifier(path, "drawable",
context.getPackageName());
Drawable drawable = context.getResources().getDrawable(id);
icons.add(drawable);
}
}
}
#Override
public int getCount() {
return icons.size();
}
#Override
public Object getItem(int position) {
return icons.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView iv = new ImageView(context);
iv.setImageDrawable(icons.get(position));
iv.setBackgroundResource(R.drawable.iconborder);
return iv;
}
}
You should add state_selected too:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true"
android:drawable="#drawable/iconborder_selected" /> <!-- selected -->
<item android:state_pressed="true"
android:drawable="#drawable/iconborder_pressed" /> <!-- pressed -->
<item android:state_pressed="false"
android:drawable="#drawable/iconborder_unselected" /> <!-- default -->
</selector>
Try in the XML declaration of the GridView to put these lines:
<GridView
<!-- Some stuff here, like id, width, e.t.c. -->
android:drawSelectorOnTop="true"
android:listSelector="path_to_your_selector"
/>
And your selector should contain something like this:
<item android:state_pressed="true">
<shape>
<!-- Or a drawable here -->
</shape>
</item>
<item android:state_focused="true">
<shape>
<!-- Or a drawable here -->
</shape>
</item>
<item android:drawable="#android:color/transparent" />

How to customize list preference radio button

I have customized all the radioButtons in my application but the radioButtons in the listPreference does not get customized.
I have used this xml named btn_radio.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:state_window_focused="false"
android:drawable="#drawable/radio_selected" />
<item android:state_checked="false" android:state_window_focused="false"
android:drawable="#drawable/radio_unselected" />
<item android:state_checked="true" android:state_pressed="true"
android:drawable="#drawable/radio_selected" />
<item android:state_checked="false" android:state_pressed="true"
android:drawable="#drawable/radio_unselected" />
<item android:state_checked="true" android:state_focused="true"
android:drawable="#drawable/radio_selected" />
<item android:state_checked="false" android:state_focused="true"
android:drawable="#drawable/radio_unselected" />
<item android:state_checked="false" android:drawable="#drawable/radio_unselected" />
<item android:state_checked="true" android:drawable="#drawable/radio_selected" />
</selector>
This is the customRadioButton which extends the android custom radio button
<style name="CustomRadioButton" Parent="#android:style/Widget.CompoundButton.RadioButton">
<item name="android:button">#drawable/btn_radio</item>
</style>
in the theme of my application I have done this changes
<item name="android:radioButtonStyle">#style/CustomRadioButton</item>
<item name="android:listChoiceIndicatorSingle">#style/CustomRadioButton</item>
This changes customize all the radioButtons in my application except radioButtons in my ListPreference
Styling the ListPreference from XML is not directly possible. The problem is that ListPreference (through DialogPreference) calls AlertDialog.Builder(Context) to build its Dialog, rather than AlertDialog.Builder(Context context, int themeResourceId). While the latter allows for providing a theme, the former does not, causing it to fall back to a default Android theme.
For a project, I needed a ListPreference with a custom title-color, a custom radiobutton-style and a custom ListView-selector (basically, Holo in a different color). I solved this by extending ListPreference and overriding onPrepareDialogBuilder(Builder) and OnCreateDialogView() so I could use a custom ListView with a simple ArrayAdapter, rather than Dialog's built-in ListView (which doesn't have support for styling). I also had to override onDialogClosed() in order to set the right value to the preference.
In order to use it, all you have to do is replace the classname of the preference in your preferences.xml rom ListPreference to com.your.packagename.ThemedListPreference. Other than that, the implementation is identical to ListPreference.
public class ThemedListPreference extends ListPreference implements OnItemClickListener {
public static final String TAG = "ThemedListPreference";
private int mClickedDialogEntryIndex;
private CharSequence mDialogTitle;
public ThemedListPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ThemedListPreference(Context context) {
super(context);
}
#Override
protected View onCreateDialogView() {
// inflate custom layout with custom title & listview
View view = View.inflate(getContext(), R.layout.dialog_settings_updatetime, null);
mDialogTitle = getDialogTitle();
if(mDialogTitle == null) mDialogTitle = getTitle();
((TextView) view.findViewById(R.id.dialog_title)).setText(mDialogTitle);
ListView list = (ListView) view.findViewById(android.R.id.list);
// note the layout we're providing for the ListView entries
ArrayAdapter<CharSequence> adapter = new ArrayAdapter<CharSequence>(
getContext(), R.layout.btn_radio,
getEntries());
list.setAdapter(adapter);
list.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
list.setItemChecked(findIndexOfValue(getValue()), true);
list.setOnItemClickListener(this);
return view;
}
#Override
protected void onPrepareDialogBuilder(Builder builder) {
// adapted from ListPreference
if (getEntries() == null || getEntryValues() == null) {
// throws exception
super.onPrepareDialogBuilder(builder);
return;
}
mClickedDialogEntryIndex = findIndexOfValue(getValue());
// .setTitle(null) to prevent default (blue)
// title+divider from showing up
builder.setTitle(null);
builder.setPositiveButton(null, null);
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
mClickedDialogEntryIndex = position;
ThemedListPreference.this.onClick(getDialog(), DialogInterface.BUTTON_POSITIVE);
getDialog().dismiss();
}
#Override
protected void onDialogClosed(boolean positiveResult) {
// adapted from ListPreference
super.onDialogClosed(positiveResult);
if (positiveResult && mClickedDialogEntryIndex >= 0
&& getEntryValues() != null) {
String value = getEntryValues()[mClickedDialogEntryIndex]
.toString();
if (callChangeListener(value)) {
setValue(value);
}
}
}
}
For my ListView items I used the layout below. Note that drawable/btn_radio_holo_light is an XML-drawable like the one in your android-sdk/platforms/android-x/data/res/drawable folder, only with references to different drawables.
<?xml version="1.0" encoding="utf-8"?>
<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:checkMark="#drawable/btn_radio_holo_light"
android:gravity="center_vertical"
android:minHeight="#dimen/list_item_minheight"
android:paddingLeft="#dimen/list_item_paddingLeft"
android:paddingRight="#dimen/list_item_paddingLeft" />
For my Dialog layout (onCreateDialogView()), I used the following:
<?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="match_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/dialog_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:textColor="#color/title_color"
android:textSize="22sp" />
<View
android:layout_width="match_parent"
android:layout_height="2dp"
android:background="#color/divider_color" />
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:listSelector="#drawable/list_selector" />
</LinearLayout>
Please, see my answer here, maybe it helps.
It's a much easier way to solve the problem.

Categories

Resources