I can set appropriate layout for preference through android:layout
attribute. For an example
<Preference
android:key="friction"
android:title="@string/friction"
android:layout="@layout/friction_fragment"
android:shouldDisableView="true"
android:defaultValue="30"
android:enabled="true"
android:selectable="true"
android:summary="Bite friction">
</Preference>
where layout is
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:text="@string/friction" android:textAppearance="?android:attr/textAppearanceLarge" android:layout_height="wrap_content" android:layout_gravity="center_horizontal"></TextView>
<SeekBar android:layout_height="wrap_content" android:layout_width="fill_parent" android:id="@+id/sbFriction"></SeekBar>
<TextView android:text="@string/friction_little" android:id="@+id/txtSummary" android:layout_width="wrap_content" android:layout_height="wrap_content"></TextView>
<Button android:text="Button" android:id="@+id/btnFriction" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>
</LinearLayout>
I can get views in OnCreate in PreferenceActivity
Preference fric = (Preference)this.findPreference("friction");
View v = fric.getView(null, null);
SeekBar sbFriction = (SeekBar)v.findViewById(R.id.sbFriction);
sbFriction.setOnSeekBarChangeListener(this);
Button btnFric = (Button) v.findViewById(R.id.btnFriction);
btnFric.setOnClickListener(m_onClick);
but these events listeners, that I have set, are not fired.
How I can catch these events, for example - click from button.
Edit.
No, It did not fire any exception.
Here is more detailed code
public class SettingsActivity extends PreferenceActivity implements OnPreferenceChangeListener, OnSeekBarChangeListener
{
private TextView m_txtSummary;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
ListPreference difficulty = (ListPreference)this.findPreference("difficulty");
difficulty.setSummary(difficulty.getEntry());
difficulty.setOnPreferenceChangeListener(this);
Preference fric = (Preference)this.findPreference("friction");
View v = fric.getView(null, null);
SeekBar sbFriction = (SeekBar)v.findViewById(R.id.sbFriction);
sbFriction.setOnSeekBarChangeListener(this);
Button btnFric = (Button) v.findViewById(R.id.btnFriction);
btnFric.setOnClickListener(m_onClick);
m_txtSummary = (TextView)v.findViewById(R.id.txtSummary);
fric.setSummary(fric.toString());
fric.setOnPreferenceChangeListener(this);
CheckBoxPreference music = (CheckBoxPreference)this.findPreference("music");
music.setOnPreferenceChangeListener(this);
}
private OnClickListener m_onClick = new OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
v.getId();
}
};
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if(newValue instanceof Boolean)
return true;
preference.setSummary(newValue.toString());
return true;
}
@Override
public void onProgressChanged(SeekBar v, int nProgress, boolean arg2) {
// TODO Auto-generated method stub
m_txtSummary.append(" " + nProgress);
m_txtSummary.invalidate();
}
@Override
public void onStartTrackingTouch(SeekBar arg0) {
// TODO Auto-generated method stub
}
@Override
public void onStopTrackingTouch(SeekBar arg0) {
// TODO Auto-generated method stub
//notifyChanged();
}
}
I'm not sure you are able to use a custom layout in conjunction with a PreferenceActivity
in the way that you describe above.
I believe you should either:
Use a PreferenceScreen
via addPreferencesFromResource()
and implement classes like CheckBoxPreference
, DialogPreference
, and MultiSelectListPreference
for the SharedPreferences
items. (example)
or
Create a custom Activity
(not PreferenceActivity
) with custom layout (using setContentView()
), and manually hook into the SharedPreferences
using PreferenceManager.getDefaultSharedPreferences()
editing them in the event listeners (View.onClickListener()
, etc) using SharedPreferences.Editor
.
Hope that makes sense.
Actually I found for an another solution. You could still use the Preferenceability:
Simply add a Fragment which calls the Custom Layout and add it’s class.
However you'll get a warning in the Manifest: (which you can ignore or fix)
[res] (AndroidManifest.xml)
android:name=".SettingsActivity_CUSTOMLAYOUT1"
"YOURPACKAGE.SettingsActivity_CUSTOMLAYOUT1 is not public"
It's only called from your SettingsActivity so you can ignore it
or
if you want to call this Activity from outside just create an own class for it and name it SettingsActivity_CUSTOMLAYOUT1.java.
CODE:
[java] (SettingsActivity.java)
public class SettingsActivity extends AppCompatPreferenceActivity {
private static Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object value) {
String stringValue = value.toString();
if (preference instanceof ListPreference) {
ListPreference listPreference = (ListPreference) preference;
int index = listPreference.findIndexOfValue(stringValue);
preference.setSummary(
index >= 0
? listPreference.getEntries()[index]
: null);
} else if (preference instanceof RingtonePreference) {
if (TextUtils.isEmpty(stringValue)) {
preference.setSummary(R.string.pref_ringtone_silent);
} else {
Ringtone ringtone = RingtoneManager.getRingtone(
preference.getContext(), Uri.parse(stringValue));
if (ringtone == null) {
preference.setSummary(null);
} else {
String name = ringtone.getTitle(preference.getContext());
preference.setSummary(name);
}
}
} else {
preference.setSummary(stringValue);
}
return true;
}
};
private static boolean isXLargeTablet(Context context) {
return (context.getResources().getConfiguration().screenLayout
& Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_XLARGE;
}
private static void bindPreferenceSummaryToValue(Preference preference) {
preference.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener);
sBindPreferenceSummaryToValueListener.onPreferenceChange(preference,
PreferenceManager
.getDefaultSharedPreferences(preference.getContext())
.getString(preference.getKey(), ""));
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setupActionBar();
}
private void setupActionBar() {
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
}
@Override
public boolean onIsMultiPane() {
return isXLargeTablet(this);
}
@Override
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public void onBuildHeaders(List<Header> target) {
loadHeadersFromResource(R.xml.pref_headers, target);
}
protected boolean isValidFragment(String fragmentName) {
return PreferenceFragment.class.getName().equals(fragmentName)
|| YOURFRAGMENT1.class.getName().equals(fragmentName)
|| YOURFRAGMENT2.class.getName().equals(fragmentName)
|| CUSTOMLAYOUT1.class.getName().equals(fragmentName)
//... Add Fragments
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class YOURFRAGMENT1 extends PreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.YOURFRAGMENTXML1);
setHasOptionsMenu(true);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
startActivity(new Intent(getActivity(), SettingsActivity.class));
return true;
}
return super.onOptionsItemSelected(item);
}
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class YOURFRAGMENT2 extends PreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_private_data);
setHasOptionsMenu(true);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
startActivity(new Intent(getActivity(), SettingsActivity.class));
return true;
}
return super.onOptionsItemSelected(item);
}
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class FRAGMENTFORCUSTOMLAYOUT1 extends PreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
startActivity(new Intent(getActivity(), SettingsActivity.class));
startActivity(new Intent(getActivity(), CUSTOMLAYOUT1.class));
setHasOptionsMenu(true);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
startActivity(new Intent(getActivity(), SettingsActivity.class));
return true;
}
return super.onOptionsItemSelected(item);
}
}
}
class SettingsActivity_CUSTOMLAYOUT1 extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.CUSTOMLAYOUT1);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
finish();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}
[xml] (pref_headers.xml)
<preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
<header
android:fragment="YOURPACKAGE.SettingsActivity$YOURFRAGMENT1"
android:icon="@drawable/YOURICON"
android:title="@string/TITLE"
android:summary="@string/SUBTITLE"/>
<header
android:fragment="YOURPACKAGE.SettingsActivity$YOURFRAGMENT2"
android:icon="@drawable/YOURICON"
android:title="@string/TITLE"
android:summary="@string/SUBTITLE"/>
<header
android:fragment="YOURPACKAGE.SettingsActivity$CUSTOMLAYOUT1"
android:icon="@drawable/YOURICON"
android:title="@string/TITLE"
android:summary="@string/SUBTITLE"/>
</preference-headers>
[layout] (CUSTOMLAYOUT1.xml)
<?xml version="1.0" encoding="utf-8"?>
<...your custom layout>
Dont forget to add in Manifest.
[res] (AndroidManifest.xml)
<?xml version="1.0" encoding="utf-8"?>
<manifest>
<application
//Add activity
<activity
android:name=".SettingsActivity_CUSTOMLAYOUT1"
android:parentActivityName=".SettingsActivity">
</activity>
</application>
</manifest>