I have created a public class in my main activity e.g.:
public class ActivityMain extends FragmentActivity {
// ...
public class MyClass extends Something implements SomethingListener{
public MyClass(Context context) {
super(context);
}
public MyClass(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyClass(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
// Listener overrides
}
}
And I use it in my layout xml like:
<my.package.ActivityMain.MyClass
app:pstsShouldExpand="true"
//parameters
/>
That way I get a ClassNotFoundException just on the setContentView(R.layout.my_layout) line in Activity's onCreate().
Also the xml design editor on Android Studio complains about this class:
Exception Details java.lang.NoSuchMethodException:
my.package.ActivityMain$MyClass.<init>(android.content.Context, android.util.AttributeSet)
If I used in the xml the class which I extend, all render good. E.g:
xml:
<external.package.Something
android:id="#+id/object"
app:pstsShouldExpand="true"
//parameters
/>
ActivityMain:
Something something = (Something) findViewById(R.id.object)
something.setSomethingListener(new SomethingListener( ... ))
Of course the above solves this issue but is it possible to use a class created in an Activity in my XML?
Update:
The Something class has custom attributes e.g. app:pstsShouldExpand="true" not sure if they are passed down to it from my MyClass. It might be the issue.
Related
I'm trying to add a custom view to an Android layout, but get this error when I run it:
Caused by: java.lang.NoSuchMethodException: <init> [class android.content.Context, interface android.util.AttributeSet]
I thought that meant it was missing a constructor, but it doesn't appear to be. Here are the constructors I have for the class:
public ChartView(Context context) {
super(context);
init();
}
public ChartView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public ChartView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
I checked the imports, and it is using android.content.Context and android.util.AttributeSet. I tried rebuilding the app, and reinstalling on my device, but no dice. The view is implemented as an inner class of the Activity that contains it, but is public. I feel think I missed something really obvious...
I have a Widget defined in xml and java. To initialise it, I use:
LayoutInflater.from(getContext()).inflate(...)
which automatically calls the constructor
public Widget(Context context, AttributeSet attrs)
How can I pass more parameters, say, a String, to this constructor?
Create a CustomWidget class that extends the Widget class and create the constructor that receives the same as the super class but also the String you want.
Don't forget to call super(context, attrs);
I'm following an example from a book and I can't understand why findViewById returns null.
This is my activity:
package it.mt.compass;
import android.app.Activity;
import android.os.Bundle;
import android.widget.Toast;
public class CompassActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
CompassView cv = (CompassView)this.findViewById(R.id.compassView1);
// this crashes the application
//cv.setBearing(45);
// some debug code
Toast test_result;
if(cv == null) {
test_result = Toast.makeText(this, "1", Toast.LENGTH_SHORT);
test_result.show();
}
else {
test_result = Toast.makeText(this, "0", Toast.LENGTH_SHORT);
test_result.show();
}
// it shows 1
}
}
and this is the res/layout/main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<it.mt.compass.CompassView
android:id="#+id/compassView1"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</LinearLayout>
Already cleaned (as suggested in other similar topics; what does "Clean" do?) the project with no luck.
Many thanks in advance.
Mirko
As requested, the constructors' code:
// Constructors
public CompassView(Context context) {
super(context);
initCompassView();
}
public CompassView(Context context, AttributeSet attrs) {
super(context);
initCompassView();
}
public CompassView(Context context, AttributeSet ats, int defaultStyle) {
super(context);
initCompassView();
}
That's the correct version (the problem was I didn't passed the parameters correctly to the superclass constructor):
// Constructors
public CompassView(Context context) {
super(context);
initCompassView();
}
public CompassView(Context context, AttributeSet attrs) {
super(context, attrs);
initCompassView();
}
public CompassView(Context context, AttributeSet ats, int defaultStyle) {
super(context, ats, defaultStyle);
initCompassView();
}
CompassView constructor implementation is incorrect. You're not passing the attributes to superclass and hence the id is lost.
Change here the superclass constructor invocation
public CompassView(Context context, AttributeSet attrs) {
super(context);
to super(context, attrs);
and
public CompassView(Context context, AttributeSet ats, int defaultStyle) {
super(context);
to super(context, attrs, defaultStyle); if the superclass has a ctor that accepts three args. Otherwise just use super(context, attrs). Oh, and rename the arg name from ats, even though the name doesn't matter.
In eclipse do:
Projects -> Clean.
Eefresh your app.
Run.
this will clear generated old R class.
I would try closing eclipse completely and then open it again. I've seen some really bizarre things like this happening. Another way you can try this is to just add a "textView" and try to do a findById on that and see if it's returning null. You could be loading the wrong xml view..
ie: your are loading a layout from one directory but it's actually loading a different view in a different directory with the same name...
add import it.mt.compass.R;
and try another View, like a Image or TextView instead
I have a compound control that needs to access the Application object. My control extends LinearLayout, so because it isn't an Activity I can't call getApplication(). Is there a way I can do this from a Layout/View or pass the Application in?
There are a couple of things you could be depending on what you need the Application object for.
If you need the specific application instance, you could try casting your Context object to an Activity:
public class MyLinearLayout extends LinearLayout {
private Application mApplication;
public MyLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
//As this is a custom ViewGroup, Context will be an Activity, but just to make sure..
if(context instanceof Activity)
mApplication = ((Activity) context).getApplication();
else
throw new IllegalArguementException("Context must be an Activity");
}
}
The code above checks to make sure that the Context passed to your custom view is an Activity, but in reality this should always be the case.
If you only need your Application object to use as a `Context', then you can call the 'context.getApplicationContext()' method:
public class MyLinearLayout extends LinearLayout {
private Context mAppContext;
public MyLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
mAppContext = context.getApplicationContext();
}
}
You have to pass the Context in Constructor when you call My Control Class.
Hello i have a problem with the elimination of NullEx ...
I set mContext = context and now i have errors:
Implicit super constructor LinearLayout() is undefined. Must explicitly invoke another constructor
Constructor call must be the first statement in a constructor
public DigitalClock(Context context) {
mContext=context;
this(context, null);
}
Earlier thread Android alarm Clock which shows problem.
You need a superclass constructor call.
public DigitalClock(Context context) {
super(context); // Add a line like this.
// Consult constructor documentation for correct usage.
this(context, null); // this line must also be at the top.
mContext=context;
}
I would assume that you are extending View, in that case you need at least two constructors.
//...Override Constructors...
public DigitalClock(Context context, AttributeSet attrs) {
super(context, attrs);
}
public DigitalClock(Context context){
super(context);
}
See if that helps.