Unable to change default font in Android app - java

I am trying to change the default font in my app. But its not working. These are steps I have taken:
1) Created class TypefaceUtil.java
import android.content.Context;
import android.graphics.Typeface;
import android.util.Log;
import java.lang.reflect.Field;
public class TypefaceUtil {
public static void overrideFont(Context context, String defaultFontNameToOverride, String customFontFileNameInAssets) {
try {
final Typeface customFontTypeface = Typeface.createFromAsset(context.getAssets(), customFontFileNameInAssets);
final Field defaultFontTypefaceField = Typeface.class.getDeclaredField(defaultFontNameToOverride);
defaultFontTypefaceField.setAccessible(true);
defaultFontTypefaceField.set(null, customFontTypeface);
} catch (Exception e) {
Log.e("CustomFontException", "Can not set custom font " + customFontFileNameInAssets + " instead of " + defaultFontNameToOverride);
}
}
}
2) In a class extending Application:
public void onCreate() {
super.onCreate();
TypefaceUtil.overrideFont(getApplicationContext(), "MONOSPACE", "fonts/varelaround_regular.ttf");
}
3) In styles.xml
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="android:typeface">monospace</item>
</style>
Still its not working. Am I missing something ?

I had faced this problem once. I am not very sure why it works, but you can try the following :
Instead of "monospace", try each of these:
DEFAULT, SANS_SERIF, SERIF. It might not work for all textviews, like those in ListView or recyclerView (weird, right?). But in those cases, I set the typeface programatically from the adapter.
Sorry for unable to explain the reason.

For this purpose, i highly recommend you to use Calligraphy, https://github.com/chrisjenx/Calligraphy, an awesome lib, really strait-forward to change the default font with it, and has many other useful functionalities.
Everything you need to set this up should be in the Readme.

Why not define your custom TextView and assign any font to it.
import android.content.Context;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.widget.EditText;
import com.exmple.util.Utility;
public class CustomFontEditText extends EditText {
private Context mContext;
private String ttfName;
String TAG = getClass().getName();
public CustomFontEditText(Context context) {
super(context);
this.mContext = context;
}
public CustomFontEditText(Context context, AttributeSet attrs) {
super(context, attrs);
this.mContext = context;
// Typeface.createFromAsset doesn't work in the layout editor.
// Skipping...
if (isInEditMode()) {
return;
}
for (int i = 0; i < attrs.getAttributeCount(); i++) {
this.ttfName = attrs.getAttributeValue(Utility.ATTRIBUTE_SCHEMA,
Utility.ATTRIBUTE_TTF_KEY);
if (null != ttfName)
init();
}
}
public CustomFontEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.mContext = context;
}
private void init() {
Typeface font = Utility.getFonts(mContext, ttfName);
if (null != font)
setTypeface(font);
}
#Override
public void setTypeface(Typeface tf) {
super.setTypeface(tf);
}
}
Load and store font from asset in a hash map in your Utility class so that you can reuse font later. Imagine loading font each time new View get loaded .. OOM ..!!!
private static Map<String, Typeface> TYPEFACE = new HashMap<String, Typeface>();
public static Typeface getFonts(Context context, String fontName) {
Typeface typeface = TYPEFACE.get(fontName);
if (typeface == null) {
typeface = Typeface.createFromAsset(context.getAssets(), "fonts/"+fontName);
TYPEFACE.put(fontName, typeface);
}
return typeface;
}
Add ttf attribute to set font from xml
public static final String ATTRIBUTE_TTF_KEY = "ttf_name";
public static final String ATTRIBUTE_SCHEMA = "http://schemas.android.com/apk/lib/com.exmaple.ui.customfont";
and now use in your layout file
<com.example.ui.customviews.CustomFontEditText
xmlns:font="http://schemas.android.com/apk/lib/com.exmaple.ui.customfont"
android:id="#+id/edt_pay_input"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="20dp"
android:background="#null"
android:cursorVisible="false"
android:drawableBottom="#drawable/dashed_white"
android:includeFontPadding="false"
android:inputType="numberDecimal"
android:maxLength="4"
android:minWidth="20dp"
android:singleLine="true"
android:textColor="#color/white"
android:textSize="30sp"
font:ttf_name="FedraSansStd-Light.otf" >
<requestFocus />
</com.example.ui.customviews.CustomFontEditText>
You can do the same for Button,TextView etc.

Related

How to Create CardViews Dynamically in Android

I've been trying to get an app idea of mine to come to fruition for some time now. The idea is a weather app in which users can choose the content they want to see, and it is represented by cards (CardViews). For example, if they want to see only current weather and a 3 day forecast, they can enable that, and they'll see only those two cards in the MainActivity in a Google Now sort of fashion.
I've run into a few problems, and I need some help.
Firstly, how can I create the CardViews dynamically? My first attempt had the views completely defined in XML, but that didn't work very well because it doesn't seem very intuitive to hide/show them all the time. So I decided to extend the CardView class into things like a CurrentWeatherCardView and create the card completely programatically.
Here's the class I created from that. It's a child of the WeatherCardView class, which just extends CardView and doesn't do a whole lot else at this point.
package com.photonfighterlabs.particleweather.weathercardviews;
import android.app.Activity;
import android.content.Context;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.photonfighterlabs.particleweather.MainActivity;
import com.photonfighterlabs.particleweather.weatherobjects.CurrentWeather;
import com.photonfighterlabs.particleweather.weatherobjects.Weather;
import java.io.File;
import static android.widget.LinearLayout.HORIZONTAL;
import static android.widget.LinearLayout.VERTICAL;
public class CurrentWeatherCardView extends WeatherCardView {
private ViewGroup viewGroup;
private LinearLayout linearLayout_600, linearLayout_604, linearLayout_434;
private TextView cw_title, temp_text_view;
private ImageView icon_image_view;
private int is_day;
private CurrentWeather currentWeather;
public CurrentWeatherCardView(CurrentWeather currentWeather, Context context, Activity activity, ViewGroup viewGroup) {
super(context, activity);
this.currentWeather = currentWeather;
this.currentWeather.initialize(context, activity, MainActivity.API_KEY);
this.context = currentWeather.getContext();
this.viewGroup = viewGroup;
this.currentWeather.doOnResponse(() -> {
setupLayout();
setCw_title(currentWeather.getName(), currentWeather.getText());
Weather.setIconDrawable(currentWeather.getIcon(), icon_image_view, currentWeather.getIs_day());
setTemperature(currentWeather.getTemp_f());
});
}
public CurrentWeatherCardView(Context context) {
super(context);
}
public CurrentWeatherCardView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CurrentWeatherCardView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void setupLayout() {
LayoutParams cardParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, pixels(200));
cardParams.setMargins(
pixels(15),
pixels(15),
pixels(15),
0
);
super.setLayoutParams(cardParams);
super.setRadius(pixels(4));
super.setUseCompatPadding(true);
linearLayout_604 = new LinearLayout(context);
linearLayout_604.setBaselineAligned(false);
linearLayout_604.setOrientation(VERTICAL);
LayoutParams layout_170 = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
linearLayout_604.setLayoutParams(layout_170);
this.addView(linearLayout_604);
linearLayout_600 = new LinearLayout(context);
linearLayout_600.setOrientation(LinearLayout.HORIZONTAL);
LayoutParams layout_676 = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, pixels(50));
linearLayout_600.setLayoutParams(layout_676);
linearLayout_604.addView(linearLayout_600);
cw_title = new TextView(context);
cw_title.setTypeface(Typeface.SANS_SERIF);
cw_title.setTextSize(pixels(5));
LayoutParams layout_914 = new LayoutParams(pixels(250), pixels(25));
layout_914.setMarginStart(pixels(10));
layout_914.topMargin = pixels(10);
cw_title.setLayoutParams(layout_914);
linearLayout_600.addView(cw_title);
icon_image_view = new ImageView(context);
LayoutParams layout_501 = new LayoutParams(pixels(75), pixels(40));
layout_501.setMarginStart(pixels(45));
layout_501.topMargin = pixels(10);
icon_image_view.setLayoutParams(layout_501);
linearLayout_600.addView(icon_image_view);
linearLayout_434 = new LinearLayout(context);
linearLayout_434.setOrientation(HORIZONTAL);
LayoutParams layout_204 = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
linearLayout_434.setLayoutParams(layout_204);
temp_text_view = new TextView(context);
temp_text_view.setTextAlignment(TEXT_ALIGNMENT_TEXT_START);
temp_text_view.setTextSize(pixels(8));
LayoutParams layout_725 = new LayoutParams(pixels(100), pixels(100));
layout_725.setMarginStart(pixels(25));
layout_725.topMargin = pixels(10);
temp_text_view.setLayoutParams(layout_725);
linearLayout_434.addView(temp_text_view);
linearLayout_604.addView(linearLayout_434);
viewGroup.addView(this);
}
private void setCw_title(String title, String condition) {
cw_title.setText(title + " - " + condition);
}
private void setTemperature(double temp) {
temp_text_view.setText(String.valueOf((int) temp) + '\u00b0');
}
}
It's messy, but is there a better way? Doing it this way allows me to create this CardView by just instantiating the class, but I'm running into issues with figuring out what kind of view I should put these in. RecyclerView doesn't really seem like the right choice because as far as I can tell it's creates cards from a dataset. In my case, the CurrentWeatherCardView will always be the same.
That leads me to my next question. In what way can I have a scrollable, side-swipeable set of cards? RecyclerView? ListView? I'm pretty lost, and any guidance would help.
CardView is extended from FrameLayout, so you can just use a xml to design what your card looks like, and use findViewById in this CurrentWeatherCardView. For example:
public CurrentWeatherCardView(Context context) {
super(context);
init();
}
public CurrentWeatherCardView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public CurrentWeatherCardView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
LayoutInflater.from(this).inflate(R.layout.xxx, this, true);
xxx = findViewById(R.id.xxxxx);
...
xxx.setText(xxxx)
// if you want to change visibility, just call:
setVisibility(View.GONE/View.VISIBILE);
}

set Custom Font for navgiation view header [duplicate]

This question already has answers here:
How to set a particular font for a button text in android?
(9 answers)
Closed 5 years ago.
I created an android studio default navgation view and i put two buttons in nav_header_main.xml (see the picture below)
now i want to set a custom font for the button.
i tried this in MainActivity.java :
Typeface font = Typeface.createFromAsset(getAssets(), "fonts/myfont.ttf");
Button b = (Button) findViewById(R.id.login_btn);
b.setTypeface(font);
but it didn't work!!
how can i do this?
Screenshot
You have to write a custom class extending from Button.
Here is an example:
package com.example.test;
import android.content.Context;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.widget.Button;
import android.widget.TextView;
public class CustomFontButton extends Button {
public CustomFontButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public CustomFontButton(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public CustomFontButton(Context context) {
super(context);
init();
}
private void init() {
Typeface font = Typeface.createFromAsset(getContext().getAssets(), "fonts/myfont.ttf");
setTypeface(font);
}
}
Use it from XML:
<com.example.test.CustomFontButton
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Button Text" />

How can I prevent Android from cropping my ImageView?

I have an ImageView, which will fill the entire width of the screen and will also be animated up and down like a wave at the bottom of the screen. I have used scaleType="matrix" since it should not stretch to fit within the screen.
However, once it has been layouted, Android crops everything away that was outside at the time of layout-update, so once it starts to animate the bottom part is missing.
So my question is, how can I prevent Android from cropping my ImageView?
I wrote a class that seems to solve the problem, thought I´d share it if someone else faces this problem..
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.ViewGroup;
import android.widget.ImageView;
public class NoCropImageView extends ImageView
{
private int fixedWidth = 0;
private int fixedHeight = 0;
private int[] attrsArray = new int[] { android.R.attr.layout_width, android.R.attr.layout_height };
public NoCropImageView(final Context context, final AttributeSet attrs)
{
super(context, attrs);
TypedArray ta = context.obtainStyledAttributes(attrs, attrsArray);
int layout_width = ta.getDimensionPixelSize(0, ViewGroup.LayoutParams.MATCH_PARENT);
int layout_height = ta.getDimensionPixelSize(1, ViewGroup.LayoutParams.MATCH_PARENT);
ta.recycle();
fixedWidth = layout_width;
fixedHeight = layout_height;
}
#Override
protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec)
{
this.setMeasuredDimension(fixedWidth, fixedHeight);
}
}

The type parameter T is hiding the type T

My question is: why, if i use LinearLayout, instead of Object, as "Result" of my AsyncTask (TableWithinExpListTask<Params, Progress, LinearLayout>) , Eclipse give me many errors like Cannot instantiate the type LinearLayout?
It seems to me that it doesn't recognise LinearLayout anymore in createFormattedCell() and i can't undertstand why.
In the AsyncTask declaration LinearLayout has yellow underline and Eclipse says: The type parameter LinearLayout is hiding the type LinearLayout.
Please someone can explain this to me?
Here is the code of the class:
import android.content.Context;
import android.graphics.Color;
import android.graphics.Typeface;
import android.os.AsyncTask;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
public class TableWithinExpListTask<Params, Progress, LinearLayout> extends AsyncTask<Params, Progress, LinearLayout> {
private final int TABLE_BORDER = 1;
private final int TABLE_TEXT_PADDING = 10;
private Context context = null;
private String str = null;
private boolean tableHeader = false;
private LinearLayout column = null;
public TableWithinExpListTask(Context context, String str, boolean tableHeader, LinearLayout column) {
this.context = context;
this.str = str;
this.tableHeader = tableHeader;
this.column = column;
}
#Override
protected LinearLayout doInBackground(Params... arg0) {
return this.createFormattedCell(this.tableHeader, this.str);
}
#Override
protected void onPostExecute(LinearLayout result) {
this.column.addView(result);
}
private LinearLayout createFormattedCell(boolean tabHeader, String str) {
// Layout che circonda le textView necessario per disegnare il bordo
// delle celle
LinearLayout container = new LinearLayout(this.context);
container.setPadding(TABLE_BORDER, TABLE_BORDER, 0, 0);
container.setBackgroundColor(Color.BLACK);
TextView textView = new TextView(this.context);
textView.setPadding(TABLE_TEXT_PADDING, TABLE_TEXT_PADDING, TABLE_TEXT_PADDING, TABLE_TEXT_PADDING);
textView.setBackgroundColor(Color.WHITE);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT);
textView.setLayoutParams(params);
if (tabHeader) {
textView.setTypeface(Typeface.DEFAULT_BOLD);
textView.setBackgroundColor(this.context.getResources().getColor(R.color.light_grayish_orange));
}
textView.setText(str);
container.addView(textView);
return container;
}
}
I see other question about this but i don't fully understand this behavior in this case.
Having the generic parameters (the stuff in angle brackets) attached to the name of your class is telling Java that you want users of your class to be able to specify the types involved, and you're using those names as the "variable names" for the types those users choose. See, for example, Map<K,V>, where K and V represent the types of the Map's keys and values. When you listed LinearLayout as a type parameter, the compiler thought that you were just using it as a placeholder for some other class that users would pick, and it didn't know how to construct one.
You're wanting your concrete class to extend a class that uses generics, but you know the specific types that you want to fill in there, so you don't put type parameters on your own class, just on the one you're using. For example, if you were writing a custom Map class that only mapped Strings to Integers, you would say public class MyMap implements Map<String, Integer>.
Change the whole code to this:
import android.content.Context;
import android.graphics.Color;
import android.graphics.Typeface;
import android.os.AsyncTask;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
public class TableWithinExpListTask extends
AsyncTask<Void, Void, LinearLayout> {
private final int TABLE_BORDER = 1;
private final int TABLE_TEXT_PADDING = 10;
private Context context = null;
private String str = null;
private boolean tableHeader = false;
private LinearLayout column = null;
public TableWithinExpListTask(Context context, String str,
boolean tableHeader, LinearLayout column) {
this.context = context;
this.str = str;
this.tableHeader = tableHeader;
this.column = column;
}
#Override
protected LinearLayout doInBackground(Void... arg0) {
return this.createFormattedCell(this.tableHeader, this.str);
}
#Override
protected void onPostExecute(LinearLayout result) {
this.column.addView(result);
}
private LinearLayout createFormattedCell(boolean tabHeader, String str) {
// Layout che circonda le textView necessario per disegnare il bordo
// delle celle
LinearLayout container = new LinearLayout(this.context);
container.setPadding(TABLE_BORDER, TABLE_BORDER, 0, 0);
container.setBackgroundColor(Color.BLACK);
TextView textView = new TextView(this.context);
textView.setPadding(TABLE_TEXT_PADDING, TABLE_TEXT_PADDING,
TABLE_TEXT_PADDING, TABLE_TEXT_PADDING);
textView.setBackgroundColor(Color.WHITE);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT);
textView.setLayoutParams(params);
if (tabHeader) {
textView.setTypeface(Typeface.DEFAULT_BOLD);
textView.setBackgroundColor(this.context.getResources().getColor(
R.color.light_grayish_orange));
}
textView.setText(str);
container.addView(textView);
return container;
}
}
I believe also you would need to have a loot a bit at Java generics. I would start to read the Oracle tutorial for this.

Android - Extended WebView class causing ClassCastException on Initialization

My problem is really straight forward. I can't seem to figure out why it's throwing an error of this kind (to add, I've never really used Java but have to for a simple android app now).
In my activity class I declare:
private MyWebView web;
Inside the 'onCreate' method I do this:
try {
web = (MyWebView)findViewById(R.id.webview);
}
catch(Exception e) {
Toast.makeText(this, e.getMessage(), Toast.LENGTH_SHORT);
}
The class 'MyWebView' looks like this:
import android.app.AlertDialog;
import android.content.Context;
import android.util.AttributeSet;
import android.webkit.WebView;
public class MyWebView extends WebView {
public MyWebView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
#Override
public void onScrollChanged(int l, int t, int oldl, int oldt) {
}
}
This throws an a 'ClassCastException' with detailMessage = "android.webkit.WebView.
I'd really appreciate some help.
Thanks
the name in the layout was the one thing which was wrong. After I tried it again it errored again, but this time it triggered a 'MethodNotFoundException'. It seems like you have to implement this constrcutor
MyWebView(Context context, AttributeSet attrs)
instead of this one
MyWebView(Context context, AttributeSet attrs, int defStyle)
like eclipse suggests...
you have to name your custom WebView like this in your layout:
<yourpackagename.MyWebView
android:id="#+id/webview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
yourpackagename: is the name of the package in wich you decalred your MyWebView Class

Categories