I am trying to create a Spinner preference like the one over at http://www.hidroh.com/2015/11/30/building-custom-preferences-v7/
So far I've extended Preference like this:
public class SpinnerPreference extends Preference {
protected String[] mEntries = new String[0];
protected String[] mEntryValues = new String[0];
private int mSelection = 0;
private final LayoutInflater mLayoutInflater;
public SpinnerPreference(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public SpinnerPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setWidgetLayoutResource(R.layout.spinner_preference);
mLayoutInflater = LayoutInflater.from(getContext());
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SpinnerPreference);
int entriesResId = ta.getResourceId(R.styleable.SpinnerPreference_entries, 0);
if (entriesResId != 0) {
mEntries = context.getResources().getStringArray(entriesResId);
}
int valuesResId = ta.getResourceId(R.styleable.SpinnerPreference_entryValues, 0);
if (valuesResId != 0) {
mEntryValues = context.getResources().getStringArray(valuesResId);
}
ta.recycle();
}
@Override
protected Object onGetDefaultValue(TypedArray a, int index) {
return a.getString(index);
}
@Override
protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) {
super.onSetInitialValue(restorePersistedValue, defaultValue);
String value = restorePersistedValue ? getPersistedString(null) : (String) defaultValue;
for (int i = 0; i < mEntryValues.length; i++) {
if (TextUtils.equals(mEntryValues[i], value)) {
mSelection = i;
break;
}
}
}
@Override
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
final Spinner spinner = (Spinner) holder.findViewById(R.id.spinner);
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
spinner.performClick();
}
});
spinner.setAdapter(new SpinnerAdapter() {
@Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = createDropDownView(position, parent);
}
bindDropDownView(position, convertView);
return convertView;
}
@Override
public void registerDataSetObserver(DataSetObserver observer) {
// no op
}
@Override
public void unregisterDataSetObserver(DataSetObserver observer) {
// no op
}
@Override
public int getCount() {
return mEntries.length;
}
@Override
public Object getItem(int position) {
return null; // not applicable
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public boolean hasStableIds() {
return true;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
return getDropDownView(position, convertView, parent);
}
@Override
public int getItemViewType(int position) {
return 0;
}
@Override
public int getViewTypeCount() {
return 1;
}
@Override
public boolean isEmpty() {
return false;
}
});
spinner.setSelection(mSelection);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
mSelection = position;
persistString(mEntryValues[position]);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
// no op
}
});
}
protected View createDropDownView(int position, ViewGroup parent) {
return mLayoutInflater.inflate(R.layout.spinner_pref_dropdown, parent, false);
}
/**
* Customize dropdown view for given spinner item
* @param position item position
* @param view item view
*/
protected void bindDropDownView(int position, View view) {
TextView textView = (TextView) view.findViewById(android.R.id.text1);
textView.setText(mEntries[position]);
}
}
However this results in the following:
As you can see the "Server" title looks different than the rest of Preferences, even though Im not touching its style. Padding is alsow very different. Why is this happening and how can I modify this styling?
Also, in the same image, you can see an icon, is it possible to align this icon to the top?
Preference XML:
<android.support.v7.preference.PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<android.support.v7.preference.ListPreference
android:key="prefs-preferred-quality"
android:icon="@drawable/ic_soccer"
android:summary="Bitrate determines the quality of the stream. Auto is recommended."
android:title="Streaming bitrate"/>
<android.support.v7.preference.SwitchPreferenceCompat
android:defaultValue="false"
android:key="prefs-record-locally"
android:summary="Should videos also be saved to the device?"
android:title="Record Locally"/>
<tv.mycujoo.mycujoobroadcast.settings.preferences.SpinnerPreference
android:key="prefs-preferred-server"
android:icon="@drawable/ic_record_dark"
app:entries="@array/stream_bitrate"
app:entryValues="@array/stream_bitrate_values"
android:summary="Streaming region to stream to"
android:title="Server"/>
</android.support.v7.preference.PreferenceScreen>
EDIT: I posted a sample code with just this screen showcasing both problems:
I had the same problem and posted the answer in this post:
Custom Preference shows differently on Preference screen than native Preferences
It will solve your problem.
In your code just move the code from the 3 argument constructor to the 2 argument constructor (call super(context, attrs);
) and delete the 3 argument constructor, the base class Preference
will choose the right style for you.