7

I created a preference entry inside preference screen, which looks like this:

<PreferenceScreen>
    <Preference
        android:title="title"
        android:key="key"
        android:widgetLayout="@layout/someview"/>
</PreferenceScreen>

Here I set a widgetlayout resource, which should be shown to the right of the preference item (like a checkbox for a checkbox preference). I can also set this resource in code of my PreferenceActivity.onCreate() like this:

Preference myPreference = findPreference("key");
myPreference.setWidgetLayoutResource(R.layout.someview);

Both approaches work fine, so I can see my resource to the right of the preference item. However, I cannot access this resource (someview) to alter its properties on runtime.

Neither manually setting resource id, inflating it from resource or findViewById seem to work - I have invalid resource/resource id not found exceptions. Seems like preference activity inflates the resource sometime later.

Has anybody run into the same problem? Any ideas about how to alter widgetlayout resource's properties on runtime?

Here is a similar question, but it was not answered

Richard Le Mesurier
  • 29,432
  • 22
  • 140
  • 255
kkgery
  • 431
  • 6
  • 13

3 Answers3

13

I seem to have the same problem, and I tried like this:

1) make a custom Preference and override onBindView():

public class ProgressBarPreference extends Preference {

    private ProgressBar mProgressBar;

    // constructors

    @Override
    protected void onBindView(View view) {
        super.onBindView(view);
        mProgressBar = (ProgressBar) view.findViewById(R.id.progressBar);
    }

    public ProgressBar getProgressBar() {
        return mProgressBar;
    }

}

2) add this preference to the screen xml:

<package.ProgressBarPreference
    android:key="key"
    android:summary="summary"
    android:title="title"
    android:widgetLayout="@layout/preference_widget_progressbar" />

preference_widget_progressbar.xml

<?xml version="1.0" encoding="utf-8"?>
<ProgressBar xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/progressBar"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center" />

or call setWidgetLayoutResource().

3) get the ProgressBar when onPreferenceTreeClick():

if (preference instanceof ProgressBarPreference) {
    ProgressBar progressBar = ((ProgressBarPreference) preference).getProgressBar();
    // TODO something
}

However, over a year now!

kuokuo
  • 196
  • 1
  • 4
2

I have a partial workaround for joinAero's case. If the goal is to simply show or hide an indeterminate progress bar in the widget, the trick is to set and clear the widget layout resource in code.

1) Define the widget layout containing the ProgressBar. No need to assign an ID. preference_widget_progressbar.xml:

<?xml version="1.0" encoding="utf-8"?>
<ProgressBar xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center" />

2) Don't specify the widget in settings.xml

<package.ProgressBarPreference
    android:key="key"
    android:summary="summary"
    android:title="title" />

3) When you want to show the progress bar, set the widget resource to preference_widget_progressbar. To clear it, set it to 0. The call to notifyChanged() is needed to update the screen.

public void showProgressBar(boolean isVisible) {
    // Show or hide the entire widget (which contains only a ProgressBar)
    setWidgetLayoutResource(isVisible ? R.layout.preference_widget_progressbar: 0);
    notifyChanged();    // Update screen
}

Getting a pointer to the actual ProgressBar is surprisingly hard, especially if the preference is in a library project. I had some success using getIdentifier() as per this post, but this approach actually hides the entire widget, whereas setting the visibility on the ProgressBar leaves a blank widget visible.

Community
  • 1
  • 1
ehartwell
  • 1,667
  • 19
  • 18
1

Here's a work around:

Create your widget layout setting the onClick attribute,

<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/icon"
    android:layout_width="48dp"
    android:layout_height="wrap_content"
    android:layout_gravity="center_vertical"
    android:background="?android:attr/selectableItemBackground"
    *android:onClick="onMyKeyClicked"*
    android:scaleType="centerInside"
    android:src="@drawable/ic_action_info" />

Then set your widget layout on your Preference,

<ListPreference
    android:defaultValue="1"
    android:entries="@array/my_entries"
    android:entryValues="@array/my_values"
    android:key="my_key"
    android:title="@string/pref_my_key_title"
    android:widgetLayout="@layout/pref_layout_my_key" />

Then in your activity have a method like,

public void onMyKeyClicked(View v) {
    Toast.makeText(this, "My key widget clicked",
       Toast.LENGTH_SHORT).show();
}

So, for each preference with a widget you'd have a layout that has the onClick attribute set to a unique method in the Activity. What do you think?

GaBo
  • 248
  • 5
  • 7