android - Custom layout for ListPreference -
i using preferenceactivity setting of app. want add new preference allow user select icon. task want use listpreference, want show icon in list.
i tried customize listpreference use custom layout, problem once list items not clickable (it show custom layout , use default value current selection).
i tested on different emulator version , on galaxy s2. when pressing item see effect of pressed/unpressed, onclick method not called.
i followed instruction on android: checkable linear layout adding custom layout (i tried option describe in how customize list preference radio button, same result).
icontypepreference.java (copied listpreference , modified):
public class icontypepreference extends dialogpreference { private icontype value; private int clickeddialogindex; private boolean valueset; @targetapi(build.version_codes.lollipop) public icontypepreference(context context, attributeset attrs, int defstyleattr, int defstyleres) { super(context, attrs, defstyleattr, defstyleres); } public icontypepreference(context context, attributeset attrs, int defstyleattr) { super(context, attrs, defstyleattr); } public icontypepreference(context context, attributeset attrs) { super(context, attrs); } @targetapi(build.version_codes.lollipop) public icontypepreference(context context) { super(context); } public void setvalue(string value) { // persist/notify first time. final boolean changed = !textutils.equals(getvaluetext(), value); if (changed || !valueset) { if (value == null) { this.value = null; } else { this.value = icontype.valueof(value); } valueset = true; persiststring(value); if (changed) { notifychanged(); } } } public void setvalueindex(int index) { setvalue(icontype.values()[index].tostring()); } public icontype getvalue() { return value; } public string getvaluetext() { return (value == null ? null : value.tostring()); } public int findindexofvalue(string value) { icontype[] values = icontype.values(); (int = values.length - 1; >= 0; i--) { if (values[i].tostring().equals(value)) { return i; } } return -1; } private int getvalueindex() { return findindexofvalue(getvaluetext()); } @override protected void onpreparedialogbuilder(alertdialog.builder builder) { super.onpreparedialogbuilder(builder); clickeddialogindex = getvalueindex(); builder.setsinglechoiceitems(new icontypeadapter(getcontext()), clickeddialogindex, new dialoginterface.onclicklistener() { public void onclick(dialoginterface dialog, int which) { clickeddialogindex = which; icontypepreference.this.onclick(dialog, dialoginterface.button_positive); dialog.dismiss(); } }); /* * typical interaction list-based dialogs have * click-on-an-item dismiss dialog instead of user having * press 'ok'. */ builder.setpositivebutton(null, null); } @override protected void ondialogclosed(boolean positiveresult) { super.ondialogclosed(positiveresult); if (positiveresult && clickeddialogindex >= 0) { string value = icontype.values()[clickeddialogindex].tostring(); if (callchangelistener(value)) { setvalue(value); } } } @override protected object ongetdefaultvalue(typedarray a, int index) { return a.getstring(index); } @override protected void onsetinitialvalue(boolean restorevalue, object defaultvalue) { setvalue(restorevalue ? getpersistedstring(getvaluetext()) : (string)defaultvalue); } @override protected parcelable onsaveinstancestate() { final parcelable superstate = super.onsaveinstancestate(); if (ispersistent()) { // no need save instance state since it's persistent return superstate; } final savedstate mystate = new savedstate(superstate); mystate.value = getvaluetext(); return mystate; } @override protected void onrestoreinstancestate(parcelable state) { if (state == null || !state.getclass().equals(savedstate.class)) { // didn't save state in onsaveinstancestate super.onrestoreinstancestate(state); return; } savedstate mystate = (savedstate)state; super.onrestoreinstancestate(mystate.getsuperstate()); setvalue(mystate.value); } private static class savedstate extends basesavedstate { string value; public savedstate(parcel source) { super(source); value = source.readstring(); } @override public void writetoparcel(parcel dest, int flags) { super.writetoparcel(dest, flags); dest.writestring(value); } public savedstate(parcelable superstate) { super(superstate); } public static final parcelable.creator<savedstate> creator = new parcelable.creator<savedstate>() { public savedstate createfromparcel(parcel in) { return new savedstate(in); } public savedstate[] newarray(int size) { return new savedstate[size]; } }; } private static class icontypeadapter extends arrayadapter<icontype> { private final string[] icontypetext; private layoutinflater inflater; public icontypeadapter(context context) { super(context, r.layout.icon_type_item, icontype.values()); this.inflater = layoutinflater.from(context); icontypetext = context.getresources().getstringarray(r.array.icon_type); } @override public view getview(int position, view convertview, viewgroup parent) { if (convertview == null) { convertview = inflater.inflate(r.layout.icon_type_item, parent, false); } ((textview)convertview.findviewbyid(r.id.text)).settext(icontypetext[position]); convertview.setclickable(true); // todo: set view text return convertview; } @override public boolean hasstableids() { return true; } @override public long getitemid(int position) { return position; } } }
checkablelinearlayout.java
public class checkablelinearlayout extends linearlayout implements checkable { private checkable checkable; public checkablelinearlayout(context context) { super(context); } public checkablelinearlayout(context context, attributeset attrs) { super(context, attrs); } @targetapi(build.version_codes.honeycomb) public checkablelinearlayout(context context, attributeset attrs, int defstyleattr) { super(context, attrs, defstyleattr); } @targetapi(build.version_codes.lollipop) public checkablelinearlayout(context context, attributeset attrs, int defstyleattr, int defstyleres) { super(context, attrs, defstyleattr, defstyleres); } @override protected void onfinishinflate() { super.onfinishinflate(); // setdescendantfocusability(viewgroup.focus_block_descendants); checkable = getcheckable(this); if (checkable == null) { throw new runtimeexception("missing checkable component"); } } private checkable getcheckable(viewgroup viewgroup) { view v; int childcount = viewgroup.getchildcount(); (int = 0; < childcount; ++i) { v = getchildat(i); if (v instanceof checkable) { return (checkable)v; } else if (v instanceof viewgroup) { checkable result = getcheckable((viewgroup)v); if (result != null) { return result; } } } return null; } @override public void setchecked(boolean checked) { checkable.setchecked(checked); } @override public boolean ischecked() { return checkable.ischecked(); } @override public void toggle() { checkable.toggle(); } }
icon_type_item.xml
<?xml version="1.0" encoding="utf-8"?> <com.utils.ui.widget.checkablelinearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <textview android:id="@+id/text" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:focusable="false" android:focusableintouchmode="false"/> <radiobutton android:layout_width="wrap_content" android:layout_height="wrap_content" android:clickable="false" android:focusable="false" android:focusableintouchmode="false"/> </com.utils.ui.widget.checkablelinearlayout>
added settings.xml
<com.utils.ui.preference.icontypepreference android:key="icon_type" android:defaultvalue="type_b" android:title="@string/icon_type_preference_title"/>
edit
there bug in checkablelinearlayout.java
replace getcheckable method this:
private checkable getcheckable(viewgroup viewgroup) { view v; int childcount = viewgroup.getchildcount(); (int = 0; < childcount; ++i) { v = viewgroup.getchildat(i); if (v instanceof checkable) { return (checkable)v; } else if (v instanceof viewgroup) { checkable result = getcheckable((viewgroup)v); if (result != null) { return result; } } } return null; }
found solution problem.
the problem in getview method of adapter: changed
convertview.setclickable(true);
to
convertview.setclickable(false);
Comments
Post a Comment