For setting a font to android app, I use below function:
public static void persianizer(ViewGroup viewGroup) {
int childCount = viewGroup.getChildCount();
for (int i = 0; i < childCount; i++) {
View child = viewGroup.getChildAt(i);
if (child instanceof ViewGroup) {
persianizer((ViewGroup) child);
continue;
}
if (child instanceof TextView) {
((TextView) child).setTypeface(RootApp.typeface);
}
}
}
It gets the root view of a layout and then set type face for every textview child of that layout. but I think it's not a good solution.
What's the best practice for changing the font of whole application?
You can create your own Font TextView class that will extends TextView and send font according to you want, have look:
public class TypefacedTextView extends TextView {
public TypefacedTextView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray styledAttrs = context.obtainStyledAttributes(attrs, R.styleable.TypefacedButton);
// String fontName = styledAttrs.getString(R.styleable.TypefacedButton_font);
styledAttrs.recycle();
Typeface typeface = Typeface.createFromAsset(context.getAssets(), "fonts/" +getResources().getString(R.string.roboto_light));
setTypeface(typeface);
}
Save Your fonts file in Assets folder and get by call Typeface.createFromAsset().
Here is the TypeFaceTextview in xml:
<com.demo.TypefacedTextView
android:id="#+id/textview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ems="10"
</com.demo.TypefacedTextView >
Happy coding!!
try this
public class CustomTextView extends android.support.v7.widget.AppCompatTextView {
public CustomTextView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
init();
}
public CustomTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public CustomTextView(Context context) {
super(context);
init();
}
private void init() {
Typeface tf = Typeface.createFromAsset(getContext().getAssets(),
"Walkway Black.ttf");
setTypeface(tf);
}
}
and then use this CustomText view in Your layout Like :
<app.com.demo.CustomTextView
android:id="#+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="#dimen/_10dp"
android:inputType=""
android:text="#string/name"
android:textColor="#color/colorSkyBlue"
android:textSize="20sp"
android:textStyle="bold" />
Related
The text I wrote for the setError() method of TextInputLayout doesn't appear inside a fragment. Tried various solutions but none of them worked...
<itdgroup.myhomedoc.SignUpTextInputLayout
android:id="#+id/email_input_layout1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:errorTextAppearance="#style/error_appearance"
app:errorEnabled="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/textViewAvenirBookFont">
<itdgroup.myhomedoc.CustomEditText
android:id="#+id/input_email"
android:layout_width="295dp"
android:layout_height="50dp"
android:layout_marginTop="11dp"
android:maxLines="1"
android:background="#drawable/custom_signup_edit_text"
android:imeOptions="actionNext"
android:inputType="textEmailAddress"
android:nextFocusDown="#+id/input_password"
android:paddingStart="20dp"
android:paddingEnd="20dp"
android:textSize="14sp"/>
</itdgroup.myhomedoc.SignUpTextInputLayout>
String strUserName = eMail.getText().toString();
if(TextUtils.isEmpty(strUserName) || !isEmailValid(strUserName)) {
emailTIL.setError("Please enter valid email");
return;
This is the custom TextInputLayout
public class SignUpTextInputLayout extends TextInputLayout {
private Context context;
public SignUpTextInputLayout(Context context) {
super(context);
this.context = context;
}
public SignUpTextInputLayout(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
}
public SignUpTextInputLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.context = context;
}
#Override
protected void drawableStateChanged() {
super.drawableStateChanged();
EditText editText = getEditText();
if(editText != null) {
editText.setBackground(ContextCompat.getDrawable(this.context, R.drawable.custom_signup_edit_text));
}
}
#Override
public void setError(#Nullable final CharSequence error) {
super.setError(error);
EditText editText = getEditText();
if(editText != null) {
editText.setBackground(ContextCompat.getDrawable(this.context, R.drawable.error_signup_edit_text));
}
}
```
In your overridden method of setError try adding the setError method as well :
#Override
public void setError(#Nullable final CharSequence error) {
super.setError(error);
EditText editText = getEditText();
if(editText != null) {
editText.setBackground(ContextCompat.getDrawable(this.context, R.drawable.error_signup_edit_text));
editText.setError("Please enter valid email");
}
}
I am trying to set external typeface in one of my expandable list view. I am trying like below
public View getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
String headerTitle = (String) getGroup(groupPosition);
String headerTitleDate = (String) getGroupD(groupPosition);
if (convertView == null) {
LayoutInflater layoutInflater = (LayoutInflater) this._context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = layoutInflater.inflate(R.layout.list_group, null);
}
Typeface bold = Typeface.createFromAsset(getContext().getAssets(), "shruti.ttf");
TextView listTitle = (TextView) convertView
.findViewById(R.id.tv_listtitle);
TextView listTitleDate = (TextView) convertView
.findViewById(R.id.tv_date);
listTitle.setTypeface(null, Typeface.BOLD);
listTitle.setText(headerTitle);
listTitleDate.setTypeface(null, Typeface.BOLD);
listTitleDate.setText(headerTitleDate);
return convertView;
}
But I am getting getAssets() cannot resolved. I have tried to use it with Context and without it but not success. Can anyone please suggest me what is wrong with it ?
Thanks
You should use the view's context when doing this, since it is inside an adapter.
You can get the view's context by: view.getContext()
Replacing this line:
Typeface bold = Typeface.createFromAsset(getContext().getAssets(), "shruti.ttf");
with this:
Typeface bold = Typeface.createFromAsset(convertView.getContext().getAssets(), "shruti.ttf");
will fix the error. Hope this helps, let me know if it does.
This is how i do it
STEP 1:
I first make a customizable font class, for your case you are using shruti.ttf
public class Shruti extends TextView{
public Champagne(Context context) {
super(context);
applyCustomFont(context);
}
public Champagne(Context context, AttributeSet attrs) {
super(context, attrs);
applyCustomFont(context);
}
public Champagne(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
applyCustomFont(context);
}
private void applyCustomFont(Context context) {
Typeface customFont = FontCache.getTypeface("shruti.ttf", context);
setTypeface(customFont);
}
}
STEP 2:
Then you also include a FontCache class
public class FontCache {
private static HashMap<String, Typeface> fontCache = new HashMap<>();
public static Typeface getTypeface(String fontname, Context context) {
Typeface typeface = fontCache.get(fontname);
if (typeface == null) {
try {
typeface = Typeface.createFromAsset(context.getAssets(), fontname);
} catch (Exception e) {
return null;
}
fontCache.put(fontname, typeface);
}
return typeface;
}
}
STEP 3:
Then lastly ,you attach the customized class on to your TextView. in your xml item class like this
<company.override.huzykamz.pixsar.customization.Shruti
android:layout_width="match_parent"
android:id="#+id/post_desc"
android:layout_height="wrap_content"
android:text=""
android:textColor="#000"
android:textSize="15dp"
android:paddingLeft="15dp"
android:paddingRight="15dp"
android:paddingBottom="15dp" />
NOTE:
company.override.huzykamz.pixsar.customization is just a package name example , but you just put yours.
Instead of
<TextView
android:layout_width="match_parent"
android:id="#+id/post_desc"
android:layout_height="wrap_content"
android:text=""
android:textColor="#000"
android:textSize="15dp"
android:paddingLeft="15dp"
android:paddingRight="15dp"
android:paddingBottom="15dp" />
Hope it works well. This is a sure deal solution
I have a simple GridView with custom Adapter in my layouts. My code is as follows:
CircleActivity.java:
public class CircleActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_circle);
List<Integer> listColors = new ArrayList<>();
listColors.add(getResources().getColor(R.color.colorAccent));
listColors.add(getResources().getColor(R.color.colorPrimary));
listColors.add(getResources().getColor(R.color.colorPrimaryDark));
GridView gridView = (GridView) findViewById(R.id.grid_colors);
CircleAdapter adapter = new CircleAdapter(this,listColors);
gridView.setAdapter(adapter);
}
}
activity_circle.xml:
<?xml version="1.0" encoding="utf-8"?>
<GridView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/grid_colors"
android:layout_width="match_parent"
android:layout_height="match_parent" />
CircleAdapter.java:
public class CircleAdapter extends BaseAdapter{
private Context context;
private List<Integer> listColor;
public CircleAdapter(Context context, List<Integer> listColor) {
this.listColor = listColor;
this.context = context;
}
#Override
public int getCount() {
return listColor.size();
}
#Override
public Integer getItem(int position) {
return listColor.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if(convertView==null){
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.row_grid,parent,false);
holder = new ViewHolder(convertView);
convertView.setTag(holder);
}
else{
holder = (ViewHolder) convertView.getTag();
}
holder.customCircleView.setFillColor(listColor.get(position));
holder.customCircleView.setCircleRadius(100);
return convertView;
}
static class ViewHolder{
private CustomCircleView customCircleView;
public ViewHolder(View row){
customCircleView = (CustomCircleView) row.findViewById(R.id.custom_circle_view);
}
}
}
row_grid.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:background="#color/colorAccent"
android:layout_width="match_parent"
android:gravity="center"
android:layout_height="match_parent">
<com.droidexperiments.gridexpand.CustomCircleView
android:id="#+id/custom_circle_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
custom:fill_color="#color/colorPrimary"
custom:circle_radius="50"
android:padding="25dp" />
</LinearLayout>
CircleView.java:
public class CustomCircleView extends View {
private int circleRadius = 20;
private int fillColor = Color.BLACK;
public CustomCircleView(Context context) {
super(context);
}
public CustomCircleView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public CustomCircleView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public CustomCircleView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
TypedArray typedArray = context.obtainStyledAttributes(R.styleable.CustomCircle);
circleRadius = typedArray.getInteger(R.styleable.CustomCircle_circle_radius,20);
fillColor = typedArray.getColor(R.styleable.CustomCircle_fill_color, Color.BLACK);
typedArray.recycle();
}
public int getCircleRadius() {
return circleRadius;
}
public void setCircleRadius(int circleRadius) {
this.circleRadius = circleRadius;
}
public int getFillColor() {
return fillColor;
}
public void setFillColor(int fillColor) {
this.fillColor = fillColor;
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint();
paint.setColor(fillColor);
paint.setStyle(Paint.Style.FILL);
canvas.drawCircle(canvas.getWidth()/2,canvas.getHeight()/2,circleRadius,paint);
}
}
attrts.xml:
<declare-styleable name="CustomCircle">
<attr name="fill_color" format="reference|color"/>
<attr name="circle_radius" format="integer"/>
</declare-styleable>
The issue is that screen remains blank and no row is inflated/showing in GridView.
I have checked everything. There is not any issue in GridView or the layout of grid row or in CustomCircleView. If I change adapter to simple ArrayAdapter, it works fine. So, there must be issue with my adapter:
I double checked getView() in adapter;
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if(convertView==null){
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.row_grid,parent,false);
holder = new ViewHolder(convertView);
convertView.setTag(holder);
}
else{
holder = (ViewHolder) convertView.getTag();
}
holder.customCircleView.setFillColor(listColor.get(position));
holder.customCircleView.setCircleRadius(100);
return convertView;
}
but couldn't identify why it shows blank. can anyone help me please?
When you implement a custom view, it is essential that you implement onMeasure. This method will tell the Android framework what size your view should be. Since you didn't specify this for CustomCircleView and used wrap_content in your layout, it had size zero. Therefore, all the elements of the GridView were invisible, making it look like the adapter was not working. I made a simple example implementation of onMeasure that solves your problem (just add this method in CustomCircleView):
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int size = View.MeasureSpec.makeMeasureSpec(2 * this.circleRadius, MeasureSpec.EXACTLY);
setMeasuredDimension(size, size);
}
The documentation advises that size stays within the given parameters (widthMeasureSpec and heightMeasureSpec). I have not included that restriction here, you can determine yourself what you want to do in that case.
You can find more information about this in the guide on creating custom components. Specific information about onMeasure can be found here.
I am working on an Android app. I have a custom view and layout as follows:
<com.hello.view.card.inner.SimpleCardView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/card_simple_linear_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/simple_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</com.hello.view.card.inner.SimpleCardView>
And this is the Java class:
public class SimpleCardView extends LinearLayout {
protected SimpleCard card = null;
protected TextView textView;
public SimpleCardView(Context context) {
super(context);
init(context);
}
public SimpleCardView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public SimpleCardView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
protected void init(Context context) {
textView = (TextView)findViewById(R.id.simple_label);
}
public void setCard(SimpleCard card) {
this.card = card;
textView.setText(card.getMessage());
}
}
And this is how I am inflating the view (I tried both following calls):
SimpleCardView view = (SimpleCardView)inflater.inflate(R.layout.card_simple, null);
//SimpleCardView view = (SimpleCardView)inflater.inflate(R.layout.card_simple, parent);
view.setCard(card);
The problem I am having is when view.setCard(card) is called, I see that textView is null, even though I am expecting it to be set in the init(..) method. Can anyone tell me what it not being set correctly? Thanks in advance.
Thank you for your answers. It turns out init(context) should not be called in the constructor. The right place to call it is in onFinishInflate(). The following change helped fix it:
public class SimpleCardView extends LinearLayout {
protected SimpleCard card = null;
protected TextView textView;
public SimpleCardView(Context context) {
super(context);
}
public SimpleCardView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SimpleCardView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onFinishInflate() {
super.onFinishInflate();
init(getContext());
}
protected void init(Context context) {
textView = (TextView)findViewById(R.id.simple_label);
}
public void setCard(SimpleCard card) {
this.card = card;
textView.setText(card.getMessage());
}
}
Instead of using root element
com.hello.view.card.inner.SimpleCardView
try using
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:id="#+id/simple_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</merge>
then, in your init method
LayoutInflater.from(context).inflate(R.layout.card_simple, this);
setOrientation(LinearLayout.VERTICAL);
textView = (TextView)findViewById(R.id.simple_label);
When you use the view in other layouts, that's where you will want to put
<com.hello.view.card.inner.SimpleCardView />
and any properties that it needs, its id, its width/height, etc.
In my application i can scaling an ImageView using this class
`public class resizeAvatar extends View {
private final Drawable sfondoAvatar;
public resizeAvatar(Context context) {
super(context);
sfondoAvatar = context.getResources().getDrawable(R.drawable.main_voice);
setBackgroundDrawable(sfondoAvatar);
}
public resizeAvatar(Context context, AttributeSet attrs) {
super(context, attrs);
sfondoAvatar = context.getResources().getDrawable(R.drawable.main_voice);
setBackgroundDrawable(sfondoAvatar);
}
public resizeAvatar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
sfondoAvatar = context.getResources().getDrawable(R.drawable.main_voice);
setBackgroundDrawable(sfondoAvatar);
}
#Override
protected void onMeasure(int widthMeasureSpec,
int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = width * sfondoAvatar.getIntrinsicHeight() / sfondoAvatar.getIntrinsicWidth();
setMeasuredDimension(width, height);
}
}
`
And writing in the layout:
<com.myapp.app.resizeAvatar
android:id="#+id/mainvoice"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:layout_centerVertical="true"/>
But in this way i can't have the onClick event.. i need do the same but using an ImageButton.. Is there a way?
In the activity where you include this view and in the onCreate method do the following:
resizeAvatar myMainvoice = (resizeAvatar) v.findViewById(R.id.mainvoice);
myMainVoice.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
//place your on click logic here
}
});