如何在RecyclerView中为TextView设置自定义字体?

时间:2015-10-27 15:15:11

标签: android textview android-recyclerview

我正在使用RecyclerView来填充云中的数据。但看起来,设置TextView的自定义字体并不容易,因为它在视图中。传统方式,这就是我的尝试:

TextView tx = (TextView)findViewById(R.id.person_age);

    Typeface custom_font = Typeface.createFromAsset(getAssets(), "fonts/Dancing Script.ttf");

    tx.setTypeface(custom_font);

但是在这里,它崩溃了应用程序,所以寻找修复,这里是Main Activiy的代码:

    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Parse.initialize(this, "app-id", "clientkey");
    setContentView(R.layout.activity_big_board);
    initializeData();
    TextView tx = (TextView)findViewById(R.id.person_age);

    Typeface custom_font = Typeface.createFromAsset(getAssets(), "fonts/Dancing Script.ttf");

    tx.setTypeface(custom_font);
    adapter = new RVAdapter(persons);


    rv=(RecyclerView)findViewById(R.id.rv);

    LinearLayoutManager llm = new LinearLayoutManager(this);
    rv.setLayoutManager(llm);
    rv.setHasFixedSize(true);


    initializeAdapter();

}

private void initializeData(){
    persons = new ArrayList<>();


    ParseQuery<ParseObject> query = new ParseQuery<ParseObject>("BigBoard");
    query.findInBackground(new FindCallback<ParseObject>() {
        public void done(List<ParseObject> credentialList, ParseException e) {
            if (e == null) {
                for(int i=0;i<credentialList.size();i++)
                {
                    a=credentialList.get(i).getString("Location");
                    b=credentialList.get(i).getString("Feed");
                    persons.add(new Person(a,b));



                    Log.d("OUT", "So the Val::------> " +a +b);


                }
            } else {
                Log.d("score", "Error: " + e.getMessage());
            }

            adapter.notifyDataSetChanged();
        }
    });


}

private void initializeAdapter(){

    rv.setAdapter(adapter);
}

以下是Adapter类的代码:

public class RVAdapter extends RecyclerView.Adapter<RVAdapter.PersonViewHolder> {

public static class PersonViewHolder extends RecyclerView.ViewHolder {

    CardView cv;
    TextView personName;
    TextView personAge;
    //ImageView personPhoto;

    PersonViewHolder(View itemView) {
        super(itemView);
        cv = (CardView)itemView.findViewById(R.id.cv);
        personName = (TextView)itemView.findViewById(R.id.person_name);
        personAge = (TextView)itemView.findViewById(R.id.person_age);
        //personPhoto = (ImageView)itemView.findViewById(R.id.person_photo);
    }
}

List<Person> persons;

RVAdapter(List<Person> persons){
    this.persons = persons;
}

@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
    super.onAttachedToRecyclerView(recyclerView);
}

@Override
public PersonViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
    View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item, viewGroup, false);
    PersonViewHolder pvh = new PersonViewHolder(v);
    return pvh;
}

@Override
public void onBindViewHolder(PersonViewHolder personViewHolder, int i) {
    personViewHolder.personName.setText(persons.get(i).name);
    personViewHolder.personAge.setText(persons.get(i).surname);
   // personViewHolder.personPhoto.setImageResource(persons.get(i).photoId);
}

@Override
public int getItemCount()
{
    if(persons!=null)
    {
        return persons.size();
    }
    else
    {
        return 0;
    }
}

}

那么,在没有对UI线程造成任何问题的情况下,最好的方法是什么?谢谢,

4 个答案:

答案 0 :(得分:2)

Typeface逻辑移入PersonViewHolder,可能在其构造函数中,原因有两个:

  1. 此时TextView存在。

  2. 您的RecyclerView可能会有多个PersonViewHolder,在这种情况下,您需要在每个 {{1}中设置Typeface },因为会有多个项目和多个PersonViewHolder需要TextView

答案 1 :(得分:1)

 public class Adapter_Recycler_Film extends RecyclerView.Adapter<Adapter_Recycler_Film.DataViewHolder> {
    private static Typeface face;
    private Context mContext;
    Adapter_Recycler_Film.DataViewHolder viewHolder;

    public Adapter_Recycler_Film(Context context,List<String> dateData) {
        ........
        this.mContext=context;
        face = Typeface.createFromAsset(mContext.getAssets(),"fonts/IRANSansMobile(FaNum)_Medium.ttf");
    }
}

public class DataViewHolder extends RecyclerView.ViewHolder {
    public TextView tDate;

    public DataViewHolder(View itemView) {
        super(itemView);
        tDate = (TextView) itemView.findViewById(R.id.txt);
        if(tDate!=null){
            tDate.setTypeface(face);
        }

    }
}

答案 2 :(得分:0)

@ CommonsWare的回答可能与您的具体案例最相关。从效率,可读性和后见之明的角度来看,我建议创建自定义TextView,然后将TextView分配到RecyclerView的项目行或应用程序中需要指定的任何位置这件事的字体。

CustomFontTextView.java

package icn.premierandroid.misc;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.TextView;

import icn.premierandroid.R;

public class CustomFontTextView extends TextView {
    AttributeSet attr;
    public CustomFontTextView(Context context) {
        super(context);
        setCustomFont(context, attr);
    }

    public CustomFontTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        setCustomFont(context, attrs);
    }

    public CustomFontTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        setCustomFont(context, attrs);
    }

    private void setCustomFont(Context ctx, AttributeSet attrs) {
        String customFont = null;
        TypedArray a = null;
        if (attrs != null) {
            a = ctx.obtainStyledAttributes(attrs, R.styleable.CustomFontTextView);
            customFont = a.getString(R.styleable.CustomFontTextView_customFont);
        }
        if (customFont == null) customFont = "fonts/portrait-light.ttf";
        setCustomFont(ctx, customFont);
        if (a != null) {
            a.recycle();
        }
    }

    public boolean setCustomFont(Context ctx, String asset) {
        Typeface tf = null;
        try {
            tf = Typeface.createFromAsset(ctx.getAssets(), asset);
        } catch (Exception e) {
            Log.e("textView", "Could not get typeface", e);
            return false;
        }
        setTypeface(tf);
        return true;
    }
}

值/ attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="CustomFontTextView">
        <attr name="customFont" format="string"/>
    </declare-styleable>
</resources >

RecyclerView

的示例项目行
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="100dp"
    card_view:cardUseCompatPadding="true"
    card_view:cardCornerRadius="8dp">

   /** Containers and other Components **/

    <icn.premierandroid.misc.CustomFontTextView
        android:id="@+id/comment_user_name"
        android:layout_height="match_parent"
        android:layout_width="0dp"
        android:layout_marginStart="5dp"
        android:layout_marginLeft="5dp"
        android:gravity="center_vertical"
        android:layout_weight="0.36"/>

    <icn.premierandroid.misc.CustomFontTextView
        android:layout_width="0dp"
        android:layout_weight="0.40"
        android:layout_height="match_parent"
        android:gravity="center_vertical"
        android:layout_marginStart="1dp"
        android:layout_marginLeft="1dp" />

    <icn.premierandroid.misc.CustomFontTextView
        android:id="@+id/comment_time"
        android:layout_width="0dp"
        android:layout_weight="0.25"
        android:gravity="center_vertical"
        android:layout_height="match_parent"/>

/** Containers and other Components **/

</android.support.v7.widget.CardView>

使用此代码,您无需更改RecyclerView.AdapterRecyclerView.ViewHolder或已初始化TextView的任何位置。

注意:您仍然可以使用TextView textView = (TextView) findViewById(R.id.textView);初始化组件。 XML为您完成所有工作。除非您以编程方式创建TextView个组件,否则您需要将其创建为CustomFontTextView textView = new CustomFontTextView();

此外,您可以将相同的逻辑应用于几乎所有组件,例如EditTextSwitchesRadioButtonsTabLayouts

答案 3 :(得分:-1)

创建扩展应用程序的其他类

public class yourApplication extends Application {
public Typeface robotoRegular;
public Typeface robotoLight;
public Typeface robotoBold;
public Typeface robotoMedium;


@Override
public void onCreate() {
    super.onCreate();
    robotoRegular = Typeface.createFromAsset(this.getAssets(), getResources().getString(R.string.robotoRegular));
    robotoLight = Typeface.createFromAsset(this.getAssets(), getResources().getString(R.string.robotoLight));
    robotoBold = Typeface.createFromAsset(this.getAssets(), getResources().getString(R.string.robotoBold));
    robotoMedium = Typeface.createFromAsset(this.getAssets(), getResources().getString(R.string.robotoMedium));

    }
}

然后将其设置为活页夹

 @Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
    // - get element from your dataset at this position
    // - replace the contents of the view with that element
    final String name = mDataset.get(position);

    holder.txtHeader.setTypeface(((yourApplication) mContext.getApplicationContext()).robotoRegular);
    holder.txtFooter.setTypeface(((yourApplication) mContext.getApplicationContext()).robotoLight);
}