在运行时改变ListView中TextView的TextSize



我有一个使用自定义SimpleCursorAdapter来显示信息的ListView。每个ListView行有3个TextView项。

由于应用程序的性质,读者可能希望也可能不希望更改字体大小来简化行项上显示的文本的阅读。

我想要完成的是一种方法来更新这个TextView项目的文本大小,而不必从bindView()做。

我现在是这样做的:

第一步:通知适配器应该更改textSize。

public void setAdjustTextSize(int size) {       
    switch (size) {
    case ArticleViewFragment.FONT_SIZE_SMALL:
        mTitleTextSizeRes = R.dimen.title_size_small;
        mCategoryTextSizeRes = R.dimen.description_size_small;
        mDescripTextSizeRes = R.dimen.description_size_small;
        break;
    case ArticleViewFragment.FONT_SIZE_MEDIUM:
        mTitleTextSizeRes = R.dimen.title_size_medium;
        mCategoryTextSizeRes = R.dimen.description_size_medium;
        mDescripTextSizeRes = R.dimen.description_size_medium;
        break;
    case ArticleViewFragment.FONT_SIZE_LARGE:
        mTitleTextSizeRes = R.dimen.title_size_large;
        mCategoryTextSizeRes = R.dimen.description_size_large;
        mDescripTextSizeRes = R.dimen.description_size_large;
        break;
    case ArticleViewFragment.FONT_SIZE_EXTRA_LARGE:
        mTitleTextSizeRes = R.dimen.title_size_extra_large;
        mCategoryTextSizeRes = R.dimen.description_size_extra_large;
        mDescripTextSizeRes = R.dimen.description_size_extra_large;
        break;
    default:
        break;
    }
}

mTitleTextSizeRes, mCategoryTextSizeRes和mDescripTextSizeRes是自定义适配器的实例变量。

第二步:在bindView()中设置textSize

@Override
public void bindView(View view, Context arg1, Cursor arg2) {
    ViewHolder mHolder = (ViewHolder) view.getTag();
     //Some other initialization
    mHolder.category.setTextSize(TypedValue.COMPLEX_UNIT_PX, mResources.getDimension(mCategoryTextSizeRes));
    mHolder.title.setTextSize(TypedValue.COMPLEX_UNIT_PX, mResources.getDimension(mTitleTextSizeRes));
    mHolder.description.setTextSize(TypedValue.COMPLEX_UNIT_PX, mResources.getDimension(mDescripTextSizeRes));
}

现在,这是有效的,是的,但是有几点我想争论:

1-我正在改变TextSize在运行时每次convertView被重用的事实。最好通过onNewView这样做,然后convertViews将已经使用新的集合大小。然而,尝试这样做将会失败,因为大多数情况下,适配器已经创建,视图已经在那里了。

2 -事实上,由于代码在bindView上运行,现有的视图将不会立即看到更改,并且在滚动期间的某些点,用户将有一些视图具有旧的文本大小,而一些具有新的文本大小。附图示例。

说了这么多,我希望我能完成一些类似于重新初始化适配器的事情,但我不确定如何做到这一点,除了从头开始创建适配器。我尝试调用notifyDataSetChanged,这没有做任何

任何想法?

尝试将自定义适配器的getView()更改为如下内容:

public View getView(int position, View convertView, ViewGroup parent)
{
    View view = super.getView(position, convertView, parent);
    TextView tv = (TextView)view;
    // NOTE: textSize is set in the custom adapter's constructor
    // int textSize
    tv.setTextSize(textSize);
    return view;
}

创建您自己的适配器是非常容易的,特别是如果您使用的只是每一行的textview。

您只需重写getView()方法并在它不为空时重用convertView,或者在它为空的情况下为该行增加一个新视图(并创建其viewholder作为标记)。

然后,你使用视图的viewHolder来更新textViews到新的大小。

当用户改变了字体大小的偏好,只需调用notifyDataSetChanged.

要更熟悉listView和适配器,请参见" listView的世界"。

显然,我正在使用我自己的SimpleCursorAdapter的实现,@MarsAtomic和@android开发人员都建议我覆盖getView(),然而,当使用SimpleCursorAdapter你不,你覆盖onNewView()onBindView()

我最终做的,这是我想要避免的是简单地从头开始重新创建适配器,并在onNewView()期间设置TextSize。我对结果非常满意,因为通过只设置新视图的大小,可以最大限度地减少对textview.setTextSize(size)的调用量。

第一步,在我的活动中,在onResume期间检查字体大小是否改变,如果改变了,从头开始重新创建适配器:

final int oldSize = mCurFontSize; 
mCurFontSize = Integer.valueOf(mPreferences.getString(getString(R.string.pref_key_font_size), "0"));
if (oldSize != mCurFontSize) {
    //Only re-do the adapter if needed
    Constants.logMessage("re-creating adapter");
    mArticleAdapter = new CursorListAdapter(Home.this, R.layout.list_item,
    mCursor, FROM, TO, 0, mCurFontSize);
    mArticlesListView.setAdapter(mArticleAdapter);
    }
}   

第二步,在适配器构造函数上,将字体大小值设置为实例变量。

public CursorListAdapter(Context context, int layout, Cursor c,
        String[] from, int[] to, int flags, int textSize) {
    super(context, layout, c, from, to, flags);
    mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    mRootLayout = layout;
    mResources = context.getResources();
    setAdjustTextSize(textSize);
}   

Where setAdjustTextSize做这个:

public void setAdjustTextSize(int size) {       
    mTextSize = size;
    switch (size) {
    case ArticleViewFragment.FONT_SIZE_SMALL:
        mTitleTextSizeRes = R.dimen.title_size_small;
        mCategoryTextSizeRes = R.dimen.description_size_small;
        mDescripTextSizeRes = R.dimen.description_size_small;
        break;
    case ArticleViewFragment.FONT_SIZE_MEDIUM:
        mTitleTextSizeRes = R.dimen.title_size_medium;
        mCategoryTextSizeRes = R.dimen.description_size_medium;
        mDescripTextSizeRes = R.dimen.description_size_medium;
        break;
    case ArticleViewFragment.FONT_SIZE_LARGE:           
        mTitleTextSizeRes = R.dimen.title_size_large;
        mCategoryTextSizeRes = R.dimen.description_size_large;
        mDescripTextSizeRes = R.dimen.description_size_large;
        break;
    case ArticleViewFragment.FONT_SIZE_EXTRA_LARGE:
        mTitleTextSizeRes = R.dimen.title_size_extra_large;
        mCategoryTextSizeRes = R.dimen.description_size_extra_large;
        mDescripTextSizeRes = R.dimen.description_size_extra_large;
        break;
    default:
        break;
    }
}   

步骤三:在onNewView()期间设置文本大小。

@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
    View container = mInflater.inflate(mRootLayout, null);
    ViewHolder mHolder = new ViewHolder();
    mHolder.category = (TextView) container.findViewById(R.id.article_category);
    mHolder.title = (TextView) container.findViewById(R.id.article_title);
    mHolder.description = (TextView) container.findViewById(R.id.article_descrp);
    mHolder.image = (ImageView) container.findViewById(R.id.article_image);
    mHolder.category.setTextSize(TypedValue.COMPLEX_UNIT_PX, mResources.getDimension(mCategoryTextSizeRes));
    mHolder.title.setTextSize(TypedValue.COMPLEX_UNIT_PX, mResources.getDimension(mTitleTextSizeRes));
    mHolder.description.setTextSize(TypedValue.COMPLEX_UNIT_PX, mResources.getDimension(mDescripTextSizeRes));
    container.setTag(mHolder);
    return container;       
}

就是这样。它可以工作,它不会在适配器的生命周期内多次调用setTextSize,我只在字体大小发生变化时重新创建适配器,我们都很高兴。

最新更新