i am trying to set a custom TTF font inside my PreferenceActivity.
The preference activity contains 2 ListPreferences, nothing else.
Inside my PreferenceActivity, i have this code:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.prefs);
PreferenceManager.getDefaultSharedPreferences(this).registerOnSharedPreferenceChangeListener(this);
}
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
Preference conPref = findPreference(key);
// this works correctly, i'm able to get the correct text form tv.getText();
TextView tv = (TextView) conPref.getView(null, null).findViewById(android.R.id.title);
Typeface gilFontBook = Typeface.createFromAsset(getAssets(), "fonts/gilbook.ttf");
tv.setTypeface(gilFontBook); // doesnt change the typeface
}
But this doesn't work form me. The fontface remains the same before and after selecting an item from the ListPreference
As far as I know you've to extend the PreferenceActivity class to do that. This answer helped me:
https://stackoverflow.com/a/13193623/814353
I did it the bruteforce way:
public class FontPreference extends Preference {
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public FontPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public FontPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public FontPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
public FontPreference(Context context) {
super(context);
}
#Override
protected void onBindView(View view) {
super.onBindView(view);
loopOverViewGroup(view);
}
private void loopOverViewGroup(View view){
if(view instanceof ViewGroup){
ViewGroup group = (ViewGroup)view;
for(int i = 0; i < ((ViewGroup)view).getChildCount(); i++){
View childView = ((ViewGroup)view).getChildAt(i);
if(childView instanceof ViewGroup){
loopOverViewGroup(childView);
}else{
setTypeFace(childView);
}
}
}
}
private void setTypeFace(View view){
if(view instanceof TextView){
((TextView)view).setTypeface(Typeface.createFromAsset(getContext().getAssets(), "YOURFONT.ttf"));
((TextView)view).setTextColor(getContext().getResources().getColor(Color.WHITE));
}
}
}
Related
I am trying to create a TextView with custom font-family. I have Created one which supports the normal font. But I am unable to implement bold/italic styling on the custom TextView.
This is my Custom TextView Class
public class KTextView extends TextView {
public KTextView(Context context) {
super(context);
TypefaceHelper.setTypeface(context, this);
}
public KTextView(Context context, AttributeSet attrs) {
super(context, attrs);
TypefaceHelper.setTypeface(context, this);
}
public KTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypefaceHelper.setTypeface(context, this);
}
}
This is the TypefaceHelper Class
public class TypefaceHelper {
private static final String FONT = "AvenirNext-Regular.otf";
private static Typeface typeface = null;
public static void setTypeface(Context context, TextView textView) {
if (typeface == null) {
typeface = Typeface.createFromAsset(context.getAssets(), FONT);
}
textView.setTypeface(typeface);
}
Can anyone suggest a way to implement Bold and Italic Styling.
try this:
textview.setTypeface(typeface, Typeface.BOLD);
you can use also ITALIC and BOLD_ITALIC
for custom textview use:
public class MyTextView extends TextView {
public MyTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public MyTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyTextView(Context context) {
super(context);
}
public void setTypeface(Typeface tf, int style) {
if (style == Typeface.BOLD) {
super.setTypeface(Typeface.createFromAsset(getContext().getAssets(), "fonts/fonts_name")/*, -1*/);
} else {
super.setTypeface(Typeface.createFromAsset(getContext().getAssets(), "fonts/fonts_name")/*, -1*/);
}
}
}
I am trying to subclass TextInputLayout, in a CustomTextInputLayout. This is the code:
public class CustomTextInputLayout extends TextInputLayout {
public CustomTextInputLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomTextInputLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public CustomTextInputLayout(Context context) {
super(context);
}
public View getComponent(){
return this.getChildAt(0);
}
public void setHint(String hint){
super.setHint(hint);
}
}
I am using it to wrap another custom component, with a button and an EditText:
public class ComponentesSeleccion extends RelativeLayout {
private EditText editText;
private Button button;
public ComponentesSeleccion(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public ComponentesSeleccion(Context context) {
super(context);
inicializar();
}
public ComponentesSeleccion(Context context, AttributeSet attrs) {
super(context, attrs);
inicializar();
}
private void inicializar() {
String infService = Context.LAYOUT_INFLATER_SERVICE;
LayoutInflater li =
(LayoutInflater)getContext().getSystemService(infService);
li.inflate(R.layout.seleccionlayout, this, true);
editText=(EditText)findViewById(R.id.editText);
button=(Button)findViewById(R.id.button2);
}
public Button getButton() {
return button;
}
public EditText getEditText() {
return editText;
}
public void setInputType(int type){
editText.setInputType(type);
}
public void setImagen(Drawable drawable){
button.setBackgroundDrawable(drawable);
}
}
With this, I am not able to do in my code:
CustomTextInputLayout ctil=(CustomTextInputLayout)view.findViewById(R.id.ctil);
ctil.setHint(“a hint");
No exception, no errors, but the hint is not drawn. i can set the normal hint on the EditText, but I want the animated hint of the TextInputLayout.
How could I get it working?
Thank you.
I have a custom RelativeLayout and I inflate an xml res file in it.
This works fine if I use the custom layout in an xml file and set it as contentview, but if I try to add it in the code with new LocationItem(this) and addChild() the findViewById method always returns null in the constructor of the custom RelativeLayout.
Here is the code:
public class LocationItem extends RelativeLayout {
private String parcelType;
private int countIntoBox, countFromBox;
private RelativeLayout deliveryContainer, pickupContainer;
private TextView countPickup, countDelivery;
public LocationItem(Context context) {
this(context, null);
}
public LocationItem(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public LocationItem(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
inflate(getContext(), R.layout.list_item_location, this);
deliveryContainer = (RelativeLayout) findViewById(R.id.rl_location_delivery_container);
pickupContainer = (RelativeLayout) findViewById(R.id.rl_location_pickup_container);
countPickup = (TextView) findViewById(R.id.tv_location_pickup_count);
countDelivery = (TextView) findViewById(R.id.tv_location_delivery_count);
countPickup.setOnClickListener(getShowNumberPickerListener());
countDelivery.setOnClickListener(getShowNumberPickerListener());
}
private OnClickListener getShowNumberPickerListener() {
return new OnClickListener() {
#Override
public void onClick(View view) {
showNumberPickerDialog(view);
}
};
} ...
}
Add custom view in activity
mRootLayoutLocations.addView(new LocationItem(this));
The view is inflated correctly, because I can see it, but when I try to access a view inside the custom view the app crashes with a NullPointerException.
Ok i inflated the view into a View(holder)
View v = inflate(getContext(), R.layout.list_item_location, this);
and then access the views via v.findViewById. Now it's working.
Code:
View v = inflate(getContext(), R.layout.list_item_location, this);
deliveryContainer = (RelativeLayout) v.findViewById(R.id.rl_location_delivery_container);
pickupContainer = (RelativeLayout) v.findViewById(R.id.rl_location_pickup_container);
countPickup = (TextView) v.findViewById(R.id.tv_location_pickup_count);
countDelivery = (TextView) v.findViewById(R.id.tv_location_delivery_count);
countPickup.setOnClickListener(getShowNumberPickerListener());
countDelivery.setOnClickListener(getShowNumberPickerListener());
You need to be using appropriate constructors, not overloading them.
public class LocationItem extends RelativeLayout {
private String parcelType;
private int countIntoBox, countFromBox;
private RelativeLayout deliveryContainer, pickupContainer;
private TextView countPickup, countDelivery;
public LocationItem(Context context) {
super(context);
init(context, null, 0);
}
public LocationItem(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs, 0);
}
public LocationItem(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context, attrs, defStyle);
}
private void init(Context context, AttributeSet attrs, int defStyle) {
inflate(getContext(), R.layout.list_item_location, this);
deliveryContainer = (RelativeLayout) findViewById(R.id.rl_location_delivery_container);
pickupContainer = (RelativeLayout) findViewById(R.id.rl_location_pickup_container);
countPickup = (TextView) findViewById(R.id.tv_location_pickup_count);
countDelivery = (TextView) findViewById(R.id.tv_location_delivery_count);
countPickup.setOnClickListener(getShowNumberPickerListener());
countDelivery.setOnClickListener(getShowNumberPickerListener());
}
private OnClickListener getShowNumberPickerListener() {
return new OnClickListener() {
#Override
public void onClick(View view) {
showNumberPickerDialog(view);
}
};
}
...
}
I fear you must inflate the view instead of finding it from nowhere. The method
findindViewById(int Id)
must be called within the Actvity's onCreate or with a view within which the child view/widget you are trying to find is resides in.
If all of the child views resides in a single xml file(within single parent root)
View rootView=(View) LayoutInflater.from(context).inflate(R.layout.list_item_location);
pickupContainer = (RelativeLayout) rootview.findViewById(R.id.rl_location_pickup_container);
you can try this. init views in the method onFinishInflate().This method will be called called as the last phase of inflation, after all child views have been added.So you can avoid NPE.
this should work
public LocationItem(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this = inflate(getContext(), R.layout.list_item_location,null);
...
I want to change some textview font-face to external font and i do something like this :
typeFace = Typeface.createFromAsset(getAssets(),"fonts/bkoodak.ttf");
tv1.setTypeface(typeFace);
tv2.setTypeface(typeFace);
tv3.setTypeface(typeFace);
...
But this form is't nice to me.
Is there some way to do this better?
Yes there is a better way.
But you have to create your own derived TextView that apply the TypeFace. And use it in your XML Layout.
Refer to this question for more details:
How to make a custom TextView?
You can create own TextView class:
public class MyTextView extends TextView {
public MyTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(attrs);
}
public MyTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs);
}
public MyTextView(Context context) {
super(context);
init(null);
}
private void init(AttributeSet attrs) {
if (attrs != null) {
TypedArray a = getContext().obtainStyledAttributes(attrs,
R.styleable.MyTextView);
Typeface myTypeface = Typeface.createFromAsset(getContext()
.getAssets(), "fonts/bkoodak.ttf");
setTypeface(myTypeface);
a.recycle();
}
}
}
and use it in you layout:
<yourpackage.MyTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
You can use create a class and use it everywhere.
For example:
FontChanger Class:
public class FontChanger
{
private Typeface typeface;
public FontChanger(Typeface typeface)
{
this.typeface = typeface;
}
public FontChanger(AssetManager assets, String assetsFontFileName)
{
typeface = Typeface.createFromAsset(assets, assetsFontFileName);
}
public void replaceFonts(ViewGroup viewTree)
{
View child;
for(int i = 0; i < viewTree.getChildCount(); ++i)
{
child = viewTree.getChildAt(i);
if(child instanceof ViewGroup)
{
// recursive call
replaceFonts((ViewGroup)child);
}
else if(child instanceof TextView)
{
// base case
((TextView) child).setTypeface(typeface);
}
}
}
}
onCreate of your activity :
FontChanger fontChanger = new FontChanger(getAssets(), "font.otf");
fontChanger.replaceFonts((ViewGroup)this.findViewById(android.R.id.content));
I know how to change to color of the Headings inside a PreferenceCategory.
public class PreferenceCategory1 extends PreferenceCategory {
public PreferenceCategory1(Context context) {
super(context);
}
public PreferenceCategory1(Context context, AttributeSet attrs) {
super(context, attrs);
}
public PreferenceCategory1(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onBindView(View view) {
super.onBindView(view);
TextView titleView = (TextView) view.findViewById(android.R.id.title);
titleView.setTextColor(Color.rgb(238, 120, 30));
}
}
But I also want to change the Divider between the PreferenceCategory and the elements beneath. I've tried to grab the listview and using the setDivider() method:
ListView v = (ListView)view.findViewById(android.R.id.list);
v.setDivider(new ColorDrawable(Color.rgb(238, 120, 30)));
But this causes a NullPointerException due to the fact that it can't find the list in this view. I am aware that I can set this in an xml file and add this as a style, but I want, if possible to do this in java. Any suggestions?