Android 自定义 ListPreference 对话框在滚动时未正确更新
Android Custom ListPreference Dialog not updating correctly when scrolling
我有点困惑。我创建了一个自定义列表首选项以容纳字体列表。列表中的每个条目都是一种字体的名称,并设置为实际的字体字样。在大屏幕上它看起来不错而且一切正常...
但在较小的屏幕上,事情会有点不稳定...如果字体不在视线范围内,即...我必须滚动才能看到它,它会将字体字体设置为列表中的第一个字体...在正常屏幕尺寸上滚动后...
代码>>>
public class FontPickerPreference extends ListPreference {
private class CustomListPreferenceAdapter extends ArrayAdapter<fontItem> {
private Context context;
private List<fontItem> fonts;
private int resource;
public CustomListPreferenceAdapter(Context context, int resource, List<fontItem> objects) {
super(context, resource, objects);
this.context = context;
this.resource = resource;
this.fonts = objects;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(resource, parent, false);
holder = new ViewHolder();
holder.fontName = (TextView) convertView
.findViewById(R.id.fontName);
Utils.setFont(context, holder.fontName, fonts.get(position).file);
holder.radioButton = (RadioButton) convertView
.findViewById(R.id.fontRadio);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.fontName.setText(fonts.get(position).name);
holder.radioButton.setChecked(fonts.get(position).isChecked);
convertView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
for (int i = 0; i < fonts.size(); i++) {
if (i == position)
fonts.get(i).isChecked = true;
else
fonts.get(i).isChecked = false;
}
getDialog().dismiss();
}
});
return convertView;
}
}
private static class fontItem {
private String file;
private boolean isChecked;
private String name;
public fontItem(CharSequence name, CharSequence file, boolean isChecked) {
this(name.toString(), file.toString(), isChecked);
}
public fontItem(String name, String file, boolean isChecked) {
this.name = name;
this.file = file;
this.isChecked = isChecked;
}
}
private static class ViewHolder {
protected TextView fontName;
protected RadioButton radioButton;
}
private Context context;
private CharSequence[] fontFile;
private CharSequence[] fontName;
private List<fontItem> fonts;
private SharedPreferences preferences;
private Resources resources;
private String selectedFontFile, defaultFontFile;
private TextView summary;
public FontPickerPreference(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
resources = context.getResources();
preferences = PreferenceManager.getDefaultSharedPreferences(context);
TypedArray a = context.getTheme().obtainStyledAttributes(attrs,
R.styleable.attrs_font, 0, 0);
try {
defaultFontFile = a.getString(R.styleable.attrs_font_fontFile);
} finally {
a.recycle();
}
}
private String getEntry(String value) {
String[] entries = resources.getStringArray(R.array.fontName);
String[] values = resources.getStringArray(R.array.fontFile);
int index = Arrays.asList(values).indexOf(value);
return entries[index];
}
@Override
protected void onBindView(View view) {
super.onBindView(view);
selectedFontFile = preferences.getString(
resources.getString(R.string.custom_font_key), defaultFontFile);
summary = (TextView) view.findViewById(R.id.summary);
summary.setText(getEntry(selectedFontFile));
Utils.setFont(context, summary, selectedFontFile);
}
@Override
protected void onDialogClosed(boolean positiveResult) {
super.onDialogClosed(positiveResult);
if (fonts != null) {
for (int i = 0; i < fonts.size(); i++) {
fontItem item = fonts.get(i);
if (item.isChecked) {
SharedPreferences.Editor editor = preferences.edit();
editor.putString(
resources.getString(R.string.custom_font_key),
item.file);
editor.commit();
selectedFontFile = item.file;
Utils.setFont(context, summary, selectedFontFile);
summary.setText(item.name);
}
Utils.setFont(context, summary, selectedFontFile);
}
}
}
@Override
protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
builder.setNegativeButton("Cancel", null);
builder.setPositiveButton(null, null);
fontName = getEntries();
fontFile = getEntryValues();
if (fontName == null || fontFile == null
|| fontName.length != fontFile.length) {
throw new IllegalStateException(
"ListPreference requires an entries array "
+ "and an entryValues array which are both the same length");
}
String selectedfont = preferences.getString(
resources.getString(R.string.custom_font_key),
resources.getString(R.string.font_type_default));
fonts = new ArrayList<>();
for (int i = 0; i < fontName.length; i++) {
Utils.setFont(context, summary, selectedFontFile);
boolean isSelected = selectedfont.equals(fontFile[i]) ? true
: false;
fontItem item = new fontItem(fontName[i], fontFile[i], isSelected);
fonts.add(item);
}
for (int i = 0; i < fontName.length; i++) {
Utils.setFont(context, summary, selectedFontFile);
}
CustomListPreferenceAdapter customListPreferenceAdapter = new CustomListPreferenceAdapter(
context, R.layout.font_picker, fonts);
builder.setAdapter(customListPreferenceAdapter, null);
}
public static class Utils {
public static boolean setFont(Context context, TextView tv, String fontAssetName) {
Typeface font = Typeface.createFromAsset(context.getAssets(), "fonts/" + fontAssetName + ".ttf");
if (font != null) {
tv.setTypeface(font);
return true;
}
throw new IllegalStateException(
"Could not load font");
}
}
}
感谢任何帮助
当 convertView
不为空时,您需要使用 Utils.setFont()
设置正确的字体,因为视图在滚动过程中离开屏幕时会被回收。
我有点困惑。我创建了一个自定义列表首选项以容纳字体列表。列表中的每个条目都是一种字体的名称,并设置为实际的字体字样。在大屏幕上它看起来不错而且一切正常...
但在较小的屏幕上,事情会有点不稳定...如果字体不在视线范围内,即...我必须滚动才能看到它,它会将字体字体设置为列表中的第一个字体...在正常屏幕尺寸上滚动后...
代码>>>
public class FontPickerPreference extends ListPreference {
private class CustomListPreferenceAdapter extends ArrayAdapter<fontItem> {
private Context context;
private List<fontItem> fonts;
private int resource;
public CustomListPreferenceAdapter(Context context, int resource, List<fontItem> objects) {
super(context, resource, objects);
this.context = context;
this.resource = resource;
this.fonts = objects;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(resource, parent, false);
holder = new ViewHolder();
holder.fontName = (TextView) convertView
.findViewById(R.id.fontName);
Utils.setFont(context, holder.fontName, fonts.get(position).file);
holder.radioButton = (RadioButton) convertView
.findViewById(R.id.fontRadio);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.fontName.setText(fonts.get(position).name);
holder.radioButton.setChecked(fonts.get(position).isChecked);
convertView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
for (int i = 0; i < fonts.size(); i++) {
if (i == position)
fonts.get(i).isChecked = true;
else
fonts.get(i).isChecked = false;
}
getDialog().dismiss();
}
});
return convertView;
}
}
private static class fontItem {
private String file;
private boolean isChecked;
private String name;
public fontItem(CharSequence name, CharSequence file, boolean isChecked) {
this(name.toString(), file.toString(), isChecked);
}
public fontItem(String name, String file, boolean isChecked) {
this.name = name;
this.file = file;
this.isChecked = isChecked;
}
}
private static class ViewHolder {
protected TextView fontName;
protected RadioButton radioButton;
}
private Context context;
private CharSequence[] fontFile;
private CharSequence[] fontName;
private List<fontItem> fonts;
private SharedPreferences preferences;
private Resources resources;
private String selectedFontFile, defaultFontFile;
private TextView summary;
public FontPickerPreference(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
resources = context.getResources();
preferences = PreferenceManager.getDefaultSharedPreferences(context);
TypedArray a = context.getTheme().obtainStyledAttributes(attrs,
R.styleable.attrs_font, 0, 0);
try {
defaultFontFile = a.getString(R.styleable.attrs_font_fontFile);
} finally {
a.recycle();
}
}
private String getEntry(String value) {
String[] entries = resources.getStringArray(R.array.fontName);
String[] values = resources.getStringArray(R.array.fontFile);
int index = Arrays.asList(values).indexOf(value);
return entries[index];
}
@Override
protected void onBindView(View view) {
super.onBindView(view);
selectedFontFile = preferences.getString(
resources.getString(R.string.custom_font_key), defaultFontFile);
summary = (TextView) view.findViewById(R.id.summary);
summary.setText(getEntry(selectedFontFile));
Utils.setFont(context, summary, selectedFontFile);
}
@Override
protected void onDialogClosed(boolean positiveResult) {
super.onDialogClosed(positiveResult);
if (fonts != null) {
for (int i = 0; i < fonts.size(); i++) {
fontItem item = fonts.get(i);
if (item.isChecked) {
SharedPreferences.Editor editor = preferences.edit();
editor.putString(
resources.getString(R.string.custom_font_key),
item.file);
editor.commit();
selectedFontFile = item.file;
Utils.setFont(context, summary, selectedFontFile);
summary.setText(item.name);
}
Utils.setFont(context, summary, selectedFontFile);
}
}
}
@Override
protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
builder.setNegativeButton("Cancel", null);
builder.setPositiveButton(null, null);
fontName = getEntries();
fontFile = getEntryValues();
if (fontName == null || fontFile == null
|| fontName.length != fontFile.length) {
throw new IllegalStateException(
"ListPreference requires an entries array "
+ "and an entryValues array which are both the same length");
}
String selectedfont = preferences.getString(
resources.getString(R.string.custom_font_key),
resources.getString(R.string.font_type_default));
fonts = new ArrayList<>();
for (int i = 0; i < fontName.length; i++) {
Utils.setFont(context, summary, selectedFontFile);
boolean isSelected = selectedfont.equals(fontFile[i]) ? true
: false;
fontItem item = new fontItem(fontName[i], fontFile[i], isSelected);
fonts.add(item);
}
for (int i = 0; i < fontName.length; i++) {
Utils.setFont(context, summary, selectedFontFile);
}
CustomListPreferenceAdapter customListPreferenceAdapter = new CustomListPreferenceAdapter(
context, R.layout.font_picker, fonts);
builder.setAdapter(customListPreferenceAdapter, null);
}
public static class Utils {
public static boolean setFont(Context context, TextView tv, String fontAssetName) {
Typeface font = Typeface.createFromAsset(context.getAssets(), "fonts/" + fontAssetName + ".ttf");
if (font != null) {
tv.setTypeface(font);
return true;
}
throw new IllegalStateException(
"Could not load font");
}
}
}
感谢任何帮助
当 convertView
不为空时,您需要使用 Utils.setFont()
设置正确的字体,因为视图在滚动过程中离开屏幕时会被回收。