Android custom view should extend AppCompatTextView - android

I created simple custom view which that extended from TextView, in Android Studio i get this wanrning
This custom view should extend android.support.v7.widget.AppCompatTextView instead
and i can't use clickable propertise, for example:
<com.myapp.test.Widgets.FontAwesome
android:layout_width="60dp"
android:layout_height="match_parent"
android:layout_marginRight="5dp"
android:background="?selectableItemBackground"
android:gravity="center"
android:clickable="#{()->presenter.clickOnSend()}"
android:text="#string/font_icon_post_message"
android:textColor="#color/gray_text_color"
android:textSize="40sp"/>
i get this error for clickable propertise:
Error:(91, 46) Cannot find the setter for attribute 'android:clickable' with parameter type lambda on com.myapp.test.Widgets.FontAwesome.
my custom class:
import android.content.Context;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.widget.TextView;
public class FontAwesome extends TextView {
public FontAwesome(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public FontAwesome(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public FontAwesome(Context context) {
super(context);
init();
}
private void init() {
Typeface tf = Typeface.createFromAsset(getContext().getAssets(),
"fonts/fontawesome.ttf");
setTypeface(tf);
}
}
how can i resolve this problem?

UPDATE: If you're using androidx libraries instead of the (legacy) v7 support libraries (which you ought to do so now...), please use this instead:
import androidx.appcompat.widget.AppCompatTextView;
OLD ANSWER: (still useful if you've not migrated to androidx yet...)
This custom view should extend
android.support.v7.widget.AppCompatTextView instead
It's a Warning, not an Error.
Instead of
public class FontAwesome extends TextView
You should use AppCompatTextView
public class FontAwesome extends AppCompatTextView

I was with a similar problem but it's fixed. It is probably you only see the result on execution time the first time. I didn't test to rebuild project again without launch the app.
import android.content.Context;
import android.graphics.Color;
import android.support.v7.widget.AppCompatTextView;
import android.util.AttributeSet;
public class CustomTxtView extends AppCompatTextView {
public CustomTxtView(Context context) {
super(context);
init();
}
public CustomTxtView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public CustomTxtView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init(){
setText("Hello World");
setTextColor(Color.RED);
}
}

Related

Can I universally change a Colour of a specific string?

I have created a real time firebase database whose one of the child is "availability". While populating all the firebase data in listview, I want the text from the child to be coloured in Green if the string value of "availability" is "yes" else in Red.
Is it possible? If yes, please show me the way.
(I have populate the child in various activities, it will be really helpful if I could state the condition universally)
Thank You.
yes possible use below class
You have to create custom Textview like this
import android.content.Context;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.widget.TextView;
public class CustomTextViewTest extends android.support.v7.widget.AppCompatTextView {
public CustomTextViewTest(Context context) {
super(context);
}
public CustomTextViewTest(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
}
public CustomTextViewTest(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
public void setText(CharSequence text, BufferType type) {
super.setText(text, type);
// here set color according to text
if (text.toString().contains("availability")) {
this.setTextColor(Your Color);
} else {
this.setTextColor(Your Color);
}
}
}

Using Typeface on another Android Activity

I want to use Typeface on a TextView I have created on another android activity. I have used the typeface on the main activity and it works. When I follow the same procedure in another activity, the app crashes - it tells me the font cannot be found.
The New Activity Screen (this launches from a button click):
public class RegisterUserActivity extends AppCompatActivity {
private TextView heading, description;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register_user);
Typeface myFont = Typeface.createFromAsset(getAssets(), "fonts/Hanken-Light.ttf");
heading = (TextView) findViewById(R.id.registerTitleHeading);
description = (TextView) findViewById(R.id.descriptionTextView);
heading.setTypeface(myFont);
description.setTypeface(myFont);
}
A bit of the main activity (this code works):
public class MainActivity extends AppCompatActivity {
//Snipped
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mainHeading = (TextView) findViewById(R.id.mainHeading);
Typeface myFont = Typeface.createFromAsset(getAssets(), "fonts/Hanken-Light.ttf");
mainHeading.setTypeface(myFont);
myView = (ImageView) findViewById(R.id.myImage);
myView.setImageDrawable(getResources().getDrawable(R.drawable.home));
When trying to use assets from another activity, is there something else I must do??
Do like that :-
Create Typefce above onCreate Method in RegisterUserActivity.
private TextView heading, description;
public static Typeface myFont;
Inside onCreate Method:
myFont = Typeface.createFromAsset(getAssets(), "fonts/Hanken-Light.ttf");
heading = (TextView) findViewById(R.id.registerTitleHeading);
description = (TextView) findViewById(R.id.descriptionTextView);
heading.setTypeface(myFont);
description.setTypeface(myFont)
In MainActivity use like this
mainHeading.setTypeface(RegisterUserActivity.myFont);
Happy coding and Happy To Help.
Use another way for set custom font.
Follow below Steps.
1.put your font file in your asset folder.
2.create one class file name with same your font name for identification. See below.
package com.bhadresh.CustomeView;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Typeface;
import android.os.Build;
import android.util.AttributeSet;
import android.widget.TextView;
public class SF_ui_display_lightTextView extends TextView {
public SF_ui_display_lightTextView(Context context) {
super(context);
init();
}
public SF_ui_display_lightTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public SF_ui_display_lightTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public SF_ui_display_lightTextView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
private void init() {
Typeface tf = Typeface.createFromAsset(getContext().getAssets(),
"SF_ui_display_light.otf");//hear set your font name with extension which stored in your asset folder
setTypeface(tf);
}
}
and after that you declare this class in your layout same as TextView like below.

Error inflating custom Switch class: Android

I have created a custom switch and I am using that in a fragment. But i am getting the following error:
12-30 17:46:55.456: E/AndroidRuntime(13351): android.view.InflateException: Binary XML file line #47: Error inflating class com.arrayent.arrayentcesdemo.customview.CustomSwitch
12-30 17:46:55.456: E/AndroidRuntime(13351): Caused by: java.lang.NoSuchMethodException: <init> [class android.content.Context, interface android.util.Att
The custom switch that i am using is:
import android.content.Context;
import android.util.AttributeSet;
import android.widget.CompoundButton;
import android.widget.Switch;
public class CustomSwitch extends Switch {
public CustomSwitch(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
private CompoundButton.OnCheckedChangeListener myListener = null;
#Override
public void setOnCheckedChangeListener(
CompoundButton.OnCheckedChangeListener listener) {
if (this.myListener == null)
this.myListener = listener;
super.setOnCheckedChangeListener(listener);
}
public void silentlySetChecked(boolean checked) {
toggleListener(false);
super.setChecked(checked);
toggleListener(true);
}
private void toggleListener(boolean on) {
if (on) {
this.setOnCheckedChangeListener(myListener);
} else
this.setOnCheckedChangeListener(null);
}
}
And the switch in the layout file is;
<com.arrayent.arrayentcesdemo.customview.CustomSwitch
android:id="#+id/light_switch"
android:layout_width="100dip"
android:layout_height="5dip"
android:layout_gravity="center_horizontal"
android:layout_marginTop="50dip"
android:scaleY="0.7"
android:textOff=" "
android:textOn=" "
android:thumb="#drawable/plug_thumb_bitmap"
android:track="#drawable/btntoggle_selector_light" />
Could someone please help me figure this out?
Thanks
You need to implement a constructor that takes in a Context and AttributeSet. You can delegate the implementation to the 3-arg constructor:
public CustomSwitch(Context context, AttributeSet attrs) {
this(context, attrs, null);
}
The <init> in the stack trace refers to object initialization, i.e. constructor.

TextView not effected onProgressChanged of seekBar

I have this extension of SeekBar:
package com.simplemathgame;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
public class SeekBarPlus extends SeekBar implements OnSeekBarChangeListener{
private TextView numberOfDrills;
public SeekBarPlus(Context context) {
super(context);
}
public SeekBarPlus(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SeekBarPlus(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
// TODO Auto-generated method stub
Log.w("SeekBarChanged", "change to" + progress);
numberOfDrills.setText(String.valueOf(progress));
}
public void setTextView(TextView textView){
numberOfDrills = textView;
Log.w("SeekBar", "text to bar");
}
}
And here is the main activity code:
package com.simplemathgame;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
import com.simplemathgame.SeekBarPlus;
public class MainActivity extends Activity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SeekBarPlus addSeekBar = (SeekBarPlus) findViewById(R.id.add_seek_bar);
SeekBarPlus subSeekBar = (SeekBarPlus) findViewById(R.id.sub_seek_bar);
SeekBarPlus mulSeekBar = (SeekBarPlus) findViewById(R.id.mul_seek_bar);
SeekBarPlus divSeekBar = (SeekBarPlus) findViewById(R.id.div_seek_bar);
TextView numberOfAddDrills = (TextView) findViewById(R.id.add_drills_number);
TextView numberOfSubDrills = (TextView) findViewById(R.id.sub_drills_number);
TextView numberOfMulDrills = (TextView) findViewById(R.id.mul_drills_number);
TextView numberOfDivDrills = (TextView) findViewById(R.id.div_drills_number);
addSeekBar.setTextView(numberOfAddDrills);
subSeekBar.setTextView(numberOfSubDrills);
mulSeekBar.setTextView(numberOfMulDrills);
divSeekBar.setTextView(numberOfDivDrills);
}
}
After I move the progress bar nothing happens, I have all the needed elements (TextViews).
I would like:
I would like the SeekBarPlus Automatically listen to it's changes and react as I have coded in the onProgressChanged method,in other words I would like that onProgressChanged would be triggered without any code in the main activity.
Screenshot
After reading the documentation:
Clients of the SeekBar can attach a SeekBar.OnSeekBarChangeListener to
be notified of the user's actions.
You need to have a listener on your Seekbar in order to update.
Update
This is possible, but you have to create a single view to house everything and then attach it it that way. Once you have created this, then add the custom view to your layout file. Then add callbacks as necessary from your custom view. Of course this implies that you added your listeners IN your custom view class.
Example
You would have something like this in your class, make sure to set the orientation of the views:
package com.blah.my.package
class MyCustomClass extends LinearLayout{
CustomSeekbar v1 ...
CustomSeekbar v2 ...
CustomSeekbar v3 ...
CustomSeekbar v4 ...
CustomSeekbar v5 ...
CustomSeekbar v6 ...
...
Constructors and methods n' stuff...
}
Once you have this, then in your layout XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<com.blah.my.package.MyCustomClass ... />
...
<LinearLayout>
To learn more:
http://developer.android.com/training/custom-views/index.html
The easiest way is to implement OnSeekBarChangeListener directly on your extended class:
public class SeekBarPlus extends SeekBar implements OnSeekBarChangeListener{
public SeekBarPlus(Context context) {
super(context);
setOnSeekBarChangeListener(this);
}
public SeekBarPlus(Context context, AttributeSet attrs) {
super(context, attrs);
setOnSeekBarChangeListener(this);
}
public SeekBarPlus(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setOnSeekBarChangeListener(this);
}
....
}
Otherwise none of the on* methods will get called. Note: this really should be a composite widget and you shouldn't need to be passing in the TextView.
You also need to do what Sergio suggested and not use the int value directly: numberOfDrills.setText("" + progress);
That's because you're sending an int to setText(), so it doesn't work because it expects a String. Change the line to:
numberOfDrills.setText("" + progress);
Or:
numberOfDrills.setText(String.valueOf(progress));
You may want to change this 4 lines too in your MainActivity, you are setting 4 TextViews to the same seekbar:
/*addSeekBar.setTextView(numberOfAddDrills);
addSeekBar.setTextView(numberOfSubDrills);
addSeekBar.setTextView(numberOfMulDrills);
addSeekBar.setTextView(numberOfDivDrills);*/
addSeekBar.setTextView(numberOfAddDrills);
subSeekBar.setTextView(numberOfSubDrills);
mulSeekBar.setTextView(numberOfMulDrills);
divSeekBar.setTextView(numberOfDivDrills);

why this exception: java.lang.RuntimeException: Error inflating class

I am trying to develop a tiny android app that just opens a browser to a website. I am using mac OS 10.6 and the latest android/eclipse tools. But I keep getting this exception:
11-29 13:03:55.113: E/AndroidRuntime(1012): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.mycomp/com.mycomp.pack}: android.view.InflateException: Binary XML file line #7: Error inflating class com.mycomp.MyTextView
Here is my code:
package com.mycomp;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
public class myapp extends Activity {
/** Called when the activity is first created. */`
private MyTextView myview;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Log.d("onCreate", "onCreate ");
myview = (MyTextView)findViewById(R.id.myview);
myview.setParent(this);
}
public static class MyTextView extends TextView {
private View mLastVisChangedView;
private int mLastChangedVisibility;
private Activity parent;
public void setParent(Activity p){
parent =p;
}
public MyTextView(Context context) {
super(context);
}
public MyTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public View getLastVisChangedView() {
return mLastVisChangedView;
}
public int getLastChangedVisibility() {
return mLastChangedVisibility;
}
#Override
protected void onVisibilityChanged(View changedView, int visibility){
Log.d("onVisibilityChanged", "new vis == " + visibility);
if (parent !=null && visibility == View.VISIBLE){
parent.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.mysite.com")));
parent.moveTaskToBack(true);
}
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<com.mycomp.MyTextView
android:id="#+id/myview"
android:text="#string/hello"/>
</LinearLayout>
The type would be com.mycomp.myapp.MyTextView. (Or $ since it's an inner class?)
You may also need to specify the view as follows:
<view class="com.mycomp.myapp$MyEditText" ...
I don't think you need an onFinishInflate in this case.
You should put the MyTextView class in a separate file. Then com.mycomp.MyTextView would be correct.

Categories

Resources