Android custom EditTextPreference UI is not getting updated - android

I am trying to customise an EditTextPreference to display a textview(i.e to display value of the preference) and a clear/delete button on its right side.
I created CustomEditTextPreference.java
package com.customedittextpreference;
import android.content.Context;
import android.content.SharedPreferences;
import android.media.Image;
import android.preference.EditTextPreference;
import android.preference.Preference;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.ImageButton;
import android.widget.TextView;
/**
* Created by cyong on 23/04/16.
*/
public class CustomEditTextPreference extends EditTextPreference {
private ImageButton clearButton;
private TextView valueTextView;
public CustomEditTextPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setupChangeListener();
}
public CustomEditTextPreference(Context context, AttributeSet attrs) {
super(context, attrs);
setupChangeListener();
}
public CustomEditTextPreference(Context context) {
super(context);
setupChangeListener();
}
#Override
protected void onBindView(View view) {
super.onBindView(view);
valueTextView = (TextView) view.findViewById(R.id.value_textview);
clearButton = (ImageButton) view.findViewById(R.id.clear_button);
clearButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
setText("");
}
});
String valueString = getText();
Log.v(Settings.APP_NAME, "refreshValue(): valueString=" + valueString);
valueTextView.setText(valueString);
toggleClearButton(valueString);
}
private void toggleClearButton(String value)
{
if (value.length()==0)
{
clearButton.setVisibility(View.GONE);
}
else
{
clearButton.setVisibility(View.VISIBLE);
}
}
private void setupChangeListener()
{
setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
String newStringValue = (String) newValue;
valueTextView.setText(newStringValue);
toggleClearButton(newStringValue);
return true;
}
});
}
}
CustomEditTextPreference class use the layout below(i.e prefwidget_edittext.xml) as widget layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal"
android:descendantFocusability="blocksDescendants"
android:padding="0dp">
<TextView
android:id="#+id/value_textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:layout_gravity="center_vertical"
android:singleLine="true" />
<ImageButton
android:id="#+id/clear_button"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:scaleType="centerInside"
android:layout_marginRight="5dp"
android:paddingLeft="6dp"
android:paddingRight="6dp"
android:layout_gravity="center_vertical"
android:src="#mipmap/delete_icon"
android:background="#00000000"
/>
</LinearLayout>
I specify my custom EditTextPreference in a preferences_list.xml under res/xml
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<ListPreference
android:key="status_choice"
android:entries="#array/array_status_entries"
android:entryValues="#array/array_status_values"
android:title="#string/choose_status_title"
android:summary="%s"
android:defaultValue="0"
/>
<CheckBoxPreference
android:defaultValue="false"
android:key="has_email"
android:title="#string/has_email_title" >
</CheckBoxPreference>
<com.customedittextpreference.CustomEditTextPreference
android:widgetLayout="#layout/prefwidget_edittext"
android:title="#string/productcode_title"
android:key="code"/>
</PreferenceScreen>
I can click on the edittextpreference and enter a string. The string entered would be saved, but would not display in textview of my custom widget layout after that. However, if I kill my app, and start it again, the textview would display the saved string. Now, when I click on the clear/delete button, I can see the value being deleted in but, the UI is not being updated to clear the string the textview and hide the clear/delete button.
For convenience, I have uploaded my sample project into github below:
Sample GitHub Project

Seems like notifyChanged() needs to be called when updating a Preference.
I noticed calls setTitle() and setSummary() would update the UI. It turns out, notifyChanged() is called in those both those functions.
Update the github project with the fix.
GitHub Project

Related

Event clicks on android CustomView controls - React Native

Im rendering a android layout.xml file on react native.while trying to implement events on views inside layout.xml on android.I'm not able to acheive it
my customview.xml layout.
<?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='40dp'
android:orientation="horizontal"
>
<TextView android:id="#+id/multipleCameraText"
android:layout_marginTop="20dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello, Text View from Native"
/>
<Button android:id="#+id/button1"
android:layout_width="wrap_content"
android:height="40dp"
android:layout_height="wrap_content"
android:text="Button 1"
/>
<Button android:id="#+id/button2"
android:layout_marginLeft="20dp"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:height="40dp"
android:text="Button 2"
/>
</LinearLayout>
my customview.java
package com.typesproject;
import android.content.Context;
import android.widget.LinearLayout;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.uimanager.events.RCTEventEmitter;
public class CustomView2 extends LinearLayout {
private Context context;
public CustomView2(Context context) {
super(context);
this.context=context;
this.init();
}
public void init() {
//modified here.
inflate(context, R.layout.customview2, this);
}
public void onReceiveNativeEvent() {
WritableMap event = Arguments.createMap();
event.putString("message", "MyMessage");
ReactContext reactContext = (ReactContext)getContext();
reactContext.getJSModule(RCTEventEmitter.class).receiveEvent(
getId(),
"topChange",
event);
}
}
I want to implement button clicks on two buttons(button1 and button2) and change text inside text view(multipleCameraText).
my customViewManager.java
package com.typesproject;
import android.view.View;
import com.facebook.react.uimanager.SimpleViewManager;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.annotations.ReactProp;
import com.facebook.react.views.image.ReactImageView;
import javax.annotation.Nonnull;
public class CustomViewManager extends SimpleViewManager<CustomView> {
public static final String Custom_View="CustomView";
#Nonnull
#Override
public String getName() {
return Custom_View;
}
#Nonnull
#Override
protected CustomView createViewInstance(#Nonnull ThemedReactContext reactContext) {
return new CustomView(reactContext);
}
}
Please let me know how we can achieve separate events for buttons and textview.
the layout view can not use in this situation. you have to define a class for the view, then use it in the ViewManager.
As for your situation, you firstly could define a class which extends Button,
public class CustomButton extends Button {}
then in the CustomViewManager expose the props and event
#ReactProp(name = "text")
public void setContenxt(CustomButton button, #Nullable String text) {
view.setSource(sources);
}
#ReactProp(name = "text")
public void setContenxt(CustomButton button, #Nullable String text) {
button.setText(sources);
}
as for the event, you can read official API.
If you want to define a view that shows like the layout XML. the view have to extend Linearlayou or ViewGroup. that effect realizes is complex. the related
knowledge is the android custom view. you may have to override onDraw, onMeasure, onLayout.
you can look at the ReactViewGroup class, it will give you some clues

Android Casting Custom View

This is my view's XML file:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<EditText
android:id="#+id/bsv_edit_beaconname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ems="10"
android:inputType="textPersonName"
android:text="Beacon Name" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<CheckBox
android:id="#+id/bsv_check_fix"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="#string/cinit_table_isfixpoint" />
<CheckBox
android:id="#+id/bsv_check_draw"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="#string/cinit_table_drawbeacon" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="horizontal">
<Button
android:id="#+id/bsv_btn_setpos"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="set_position_click"
android:text="#string/cinit_set_position" />
<TextView
android:id="#+id/bsv_text_pos"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Position ?" />
</LinearLayout>
With the corresponding java class being the following
package talogs.beacontalogs;
import android.content.Context;
import android.graphics.Point;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
public class BeaconSetupView extends LinearLayout {
private static final String TAG = "BeaconSetupView";
private EditText edit_beaconName;
private CheckBox check_isFixpoint;
private CheckBox check_draw;
private Button btn_setpos;
private TextView text_pos;
public BeaconSetupView(Context context) {
this(context, null);
}
public BeaconSetupView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public BeaconSetupView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
public void init(Context context) {
// inflate(getContext(), R.layout.beacon_setup_view, this);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate( R.layout.beacon_setup_view, this );
edit_beaconName = (EditText) findViewById(R.id.bsv_edit_beaconname);
check_isFixpoint = (CheckBox) findViewById(R.id.bsv_check_fix);
check_draw = (CheckBox) findViewById(R.id.bsv_check_draw);
btn_setpos = (Button) findViewById(R.id.bsv_btn_setpos);
text_pos = (TextView) findViewById(R.id.bsv_text_pos);
}
public void setPosition(Point point) {
Log.v(TAG, "setting position to " + point.toString());
text_pos.setText(String.format("(%d, %d)", point.x, point.y));
}
}
My custom view BeaconSetupView is created programmatically using this code when a button in an activity is pressed.
public void btn_addbeacon_Click(View view) {
BeaconSetupView beacon = new BeaconSetupView(this);
beaconList.addView(beacon, beaconList.getChildCount() - 1);
}
The button that's part of the custom view calls this method:
public void set_position_click(View view) {
ViewParent parent1 = view.getParent();
ViewParent parent2 = parent1.getParent();
BeaconSetupView bsv = (BeaconSetupView) view.getParent().getParent();
Log.v(LOG_TAG, "set_position called, point is currently " + String.valueOf(lastClicked));
if (lastClicked != null) {
bsv.setPosition(lastClicked);
}
}
The problem is that the button click cannot be implemented outside of the root activity (because it has data that I need), but I also need to get its corresponding BeaconSetupView. Calling view.getParent().getParent() and casting it results in a ClassCastException. So I tried changing the root element of the XML layout to BeaconSetupView, but that causes the app to crash when the view is first added to the activity.
I either need a way to cast my custom class properly and still be able to add it programmatically to my activity, or I need to be able to access the activity's instance from another class that doesn't have a reference to it. What are my options?

Simple custom control - Force closed

I have created an android project using eclipse.the default system generated code looked as below
package com.rmycustomclass.bengler;
import android.app.Activity;
import android.os.Bundle;
public class RMyCustomClassActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
I wanted to try a simple custom control , so i changed the code as below. when i searched the web to create a simple custom control there are mentioned like "create class by subclassing a View". so tried as below by modifying the code.but it was not running and always force closed.
package com.rmycustomclass.bengler;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
public class RMyCustomClassActivity extends View {
private Paint myPaint;
public RMyCustomClassActivity(Context cxt, AttributeSet attribute){
super(cxt,attribute);
init();
}
public RMyCustomClassActivity(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
init();
}
public void init(){
myPaint = new Paint();
myPaint.setTextSize(12);
myPaint.setColor(0xFF668800);
myPaint.setStyle(Paint.Style.FILL);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawText("TEEEST", 100, 100, myPaint);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
this.setMeasuredDimension(150,200);
}
}
Below is my xml file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:layout_width="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="fill_parent" android:orientation="vertical">
<TextView
android:id="#+id/textView1"
android:text="Enter text"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</TextView>
<TableLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/tableLayout1">
<Button
android:id="#+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
android:layout_weight="1">
</Button>
<Button android:layout_width="wrap_content" android:id="#+id/button1" android:layout_height="40dip" android:text="My button" android:layout_weight="1"></Button>
<test.control
android:id="#+id/control"
android:layout_height="match_parent"> </test.control>
</TableLayout>
</LinearLayout>
When you create a project in eclipse it links your activity (RMyCustomClassActivity in your case) as the launcher in Android manifest...But since you have changed the activity to a View
android runtime cannot find the activity to launch...See your manifest file and you will find your class as the launcher activity
add android:layout_width="match_parent"
<test.control
android:id="#+id/control"
android:layout_height="match_parent"
android:layout_width="match_parent"
>

How to make a PreferenceActivity launch a Dialog to set a custom preference

I have a working Preferences setup launched from a menu option. In the preferences I have setup a Custom Preference that must launch a dialog with 3 TextViews to set confirm and change a password. Now I do not know how to launch the dialog from the PreferenceActivity's onPreferenceClick. If I sound like a newby - I am, sorry!
Here is my xml layout for the dialog popup:
<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout
android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="vertical"
android:id="#+id/root"
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:id="#+id/TextView_Pwd1"
android:text="#string/settings_oldpassword"
android:textStyle="bold" />
<EditText
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:id="#+id/EditText_OldPwd" />
<TextView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:id="#+id/TextView_Pwd1"
android:text="#string/settings_password"
android:textStyle="bold" />
<EditText
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:id="#+id/EditText_Pwd1"
android:inputType="textPassword" />
<TextView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:id="#+id/TextView_Pwd2"
android:text="#string/settings_password2"
android:textStyle="bold" />
<EditText
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:id="#+id/EditText_Pwd2"
android:inputType="textPassword" />
<TextView
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:id="#+id/TextView_PwdProblem"
android:textStyle="bold"
android:gravity="center" />
<TextView
android:id="#+id/TextView_PwdProblem"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="#string/settings_pwd_not_equal" />
<CheckBox
android:id="#+id/checkShowPwdText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/settings_showpwd_text" />
Here is my DialogChangePassword class for the dialog popup:
package biz.linsys.package;
import android.app.Dialog;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.DialogPreference;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
public class DialogChangePassword extends DialogPreference {
private String strPass1;
private String strPass2;
public DialogChangePassword(Context context, AttributeSet attrs) {
super(context, attrs);
setDialogLayoutResource(R.layout.dialog_pwdchange);
}
#Override
protected void onBindDialogView(View view) {
Dialog pwdDialog = getDialog();
final EditText password1 = (EditText) pwdDialog.findViewById(R.id.EditText_Pwd1);
final EditText password2 = (EditText) pwdDialog.findViewById(R.id.EditText_Pwd2);
final TextView error = (TextView) pwdDialog.findViewById(R.id.TextView_PwdProblem);
password2.addTextChangedListener(new TextWatcher() {
#Override
public void afterTextChanged(Editable s) {
strPass1 = password1.getText().toString();
strPass2 = password2.getText().toString();
if (strPass1.equals(strPass2)) {
error.setText(R.string.settings_pwd_equal);
} else {
error.setText(R.string.settings_pwd_not_equal);
}
} public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
public void onTextChanged(CharSequence s, int start, int before, int count) {}
});
super.onBindDialogView(view);
}
#Override
protected void onDialogClosed(boolean positiveResult) {
if(!positiveResult) return;
SharedPreferences.Editor editor = getEditor();
if (strPass1.equals(strPass2)) {
editor.putString("password", strPass1);
editor.commit();
}
super.onDialogClosed(positiveResult);
}
}
This the PreferenceActivity class containing Custom Preference onPreferenceClick. This is where I need to call the dialog box to change the user password setting.
package biz.linsys.package;
import android.content.Context;
import android.os.Bundle;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceActivity;
public class Preferences extends PreferenceActivity {
public static Context dialogContext;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
// Get the custom preference
Preference customPref = (Preference) findPreference("customPref");
customPref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
public boolean onPreferenceClick(Preference preference) {
// [ NEED TO CALL DIALOG FROM HERE ]
return false;
}
});
}
}
This is something that is missing in the documentation, and I've found lots of similar questions regarding it, mostly with no definite answers. I've faced the same problem today, and somehow I've found the solution, so I'll summarize my quest here, just in hope someone will find this useful. BTW your question is the most detailed and accurate among others.
The general point is that you don't need to create the dialog manually, you just 1) create a subclass of the DialogPreference that will handle the logic of a complex preference and 2) create a node of the proper type in your preferences.xml so the dialog will be spawned automatically.
The problem of the Android SDK is that you cannot add that proper node using the visual XML editor, you need to go and edit the file manually.
The problem of the documentation is that it misses this very bit of information.
So here is the step-by-step solution:
1) Create a subclass of DialogPreference that will handle your special preference. For details on what is needed in your subclass, I'd recommend this answer.
2) Create a Preference node in your preferences.xml.
3) Edit the preferences.xml and replace the Preference with full name of your DialogPreference subclass including the package path, e. g. com.sample.MyPreferenceDialog. You may also add some attributes to the node to customize the dialog (title, icon, etc.), see this answer or the documentation for DialogPreference for details.
That's all. You don't need to add OnPreferenceClickListener to the preferences, the dialog will show up automatically.
Note: I am not 100% sure that this is the intended way of using things, but it seems to be working.

Preference List only shows first element

I am developing a PreferenceActivity with custom Preference views. My problem is that I created a view with a ListView and it only shows the first element. I post my code and an image:
http://imageshack.us/photo/my-images/545/sc20120307161530.png/
http://img545.imageshack.us/img545/7207/sc20120307161530.png' border='0'/>
xml:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<PreferenceCategory
android:key="player_settings"
android:title="#string/settings_player_config" >
<EditTextPreference
android:defaultValue="#string/settings_player_default_name"
android:dialogMessage="#string/settings_player_summary"
android:dialogTitle="#string/settings_playersname"
android:key="player_name"
android:summary="#string/settings_player_summary"
android:title="#string/settings_playersname" />
</PreferenceCategory>
<PreferenceCategory
android:key="volume"
android:title="#string/settings_volume" >
<com.battleship.preferences.SeekBarPreferences
android:defaultValue="50"
android:key="volume"
android:title="#string/settings_volume" />
</PreferenceCategory>
<PreferenceCategory
android:key="shine"
android:title="#string/settings_shine" >
<com.battleship.preferences.SeekBarPreferences
android:defaultValue="50"
android:key="shine"
android:title="#string/settings_shine" />
</PreferenceCategory>
<PreferenceCategory
android:key="themeTitle"
android:title="#string/settings_group_themes" >
<com.battleship.preferences.ListPreferences android:key="theme" />
</PreferenceCategory>
<PreferenceCategory
android:key="fontsTitle"
android:title="#string/settings_group_font_size" >
<com.battleship.preferences.ListPreferences android:key="font" />
</PreferenceCategory>
</PreferenceScreen>
The Custom ListPreference:
package com.battleship.preferences;
import com.battleship.R;
import android.content.Context;
import android.content.SharedPreferences;
import android.media.AudioManager;
import android.preference.Preference;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;
import android.widget.Toast;
public class ListPreferences extends Preference implements
OnCheckedChangeListener {
public ListPreferences(Context context) {
super(context);
}
public ListPreferences(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ListPreferences(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onClick() {
super.onClick();
Toast t = Toast.makeText(getContext(), "HOLA!", 3);
t.show();
}
#Override
protected View onCreateView(ViewGroup parent) {
String[] contentString = new String[3];
if (getKey().equals("theme")) {
contentString = new String[] {
(getContext().getString(R.string.settings_theme_default)),
(getContext().getString(R.string.settings_theme_black)),
(getContext().getString(R.string.settings_theme_white)) };
} else {
contentString = new String[] {
(getContext().getString(R.string.settings_font_big)),
(getContext().getString(R.string.settings_font_medium)),
(getContext().getString(R.string.settings_font_little)) };
}
ListView listView = new ListView(getContext());
ArrayAdapter<String> array = new ArrayAdapter<String>(getContext(),
android.R.layout.simple_list_item_single_choice,
android.R.id.text1, contentString);
listView.setAdapter(array);
listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
return listView;
}
private void updatePreference(int intRadio) {
SharedPreferences.Editor editor = getEditor();
editor.putInt(getKey(), intRadio);
editor.commit();
}
}
Don't you hate it when everyone tries to tell you that you shouldn't do it that way instead of just answering your question? Being able to dynamically generate content is crucial to app flexibility, I totally know what you're after.
This will work assuming all the ListView entries will be roughly the same height (non-pertinent parts omitted). The order is important, try to keep it as I've indicated:
import android.view.ViewGroup.OnHierarchyChangeListener;
public class ListPreferences extends Preference implements
OnCheckedChangeListener, OnHierarchyChangeListener {
private ListView listView;
private View thisView;
private int listHeight = 0;
#Override
protected View onCreateView(ViewGroup parent) {
this.setLayoutResource(R.layout.listview_preference_layout);
thisView = super.onCreateView(parent);
listView = (ListView) thisView.findViewById(android.R.id.list);
listView.setOnHierarchyChangeListener(this);
String[] contentString = new String[3];
if (getKey().equals("theme")) {
contentString = new String[] {
(getContext().getString(R.string.settings_theme_default)),
(getContext().getString(R.string.settings_theme_black)),
(getContext().getString(R.string.settings_theme_white)) };
} else {
contentString = new String[] {
(getContext().getString(R.string.settings_font_big)),
(getContext().getString(R.string.settings_font_medium)),
(getContext().getString(R.string.settings_font_little)) };
}
ArrayAdapter<String> array = new ArrayAdapter<String>(getContext(),
android.R.layout.simple_list_item_single_choice,
android.R.id.text1, contentString);
listView.setAdapter(array);
listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
return thisView;
}
public void onChildViewAdded(View parent, View child) {
int childHeight = child.getMeasuredHeight();
if(childHeight > 0)
{
listHeight = listView.getAdapter().getCount() * childHeight;
thisView.setMinimumHeight(listHeight);
Log.i(TAG,"onChildViewAdded, done: "+listHeight+" "+childHeight);
}
}
public void onChildViewRemoved(View parent, View child) {
}
}
You'll also need res/layout/listview_preference_layout.xml with the following:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="fill_vertical|fill_horizontal|fill"
android:gravity="fill"
android:orientation="vertical"
>
<ListView
android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:clipChildren="true"
android:isScrollContainer="true"
android:layout_gravity="fill_vertical|fill_horizontal|fill"
android:layout_weight="1"
android:choiceMode="singleChoice"/>
</LinearLayout
I would advise you create a custom layout for Preferences. You can then create and style your Preferences to how you like. And using the SharedPreferences from PreferenceManager.getDefaultPreferences() will allow you to save any changes as if you were using the normal Preferences solution.
As Malcolm suggested, you should probably adhere to the common practices, and not try to do anything to complex here.
Another suggestion, is dont use a ListView. Instead if you want all of your Views to be displayed, manually add these to a LinearLayout, which you then place inside your Preference View.
The problem is that you're trying to add a ListView as an item of another ListView. ListView is used in the layout of the PreferenceActivity. Therefore it doesn't work.
I don't understand why you don't want to go with the standard solution, ListPreference. It is made exactly for the purpose of presenting a user with a list of radio buttons.

Categories

Resources