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.
Related
I'm really curious about constructors for custom views. Currently I have one which extends the RelativeLayout. Each view need context for initialization. So, I put super() in the constructor. Although, I need the activity in my class so I took context from it. As far as I know, activity is a context too so why Android Studio gives me an inspection that I am missing the constructor with context ? My class looks like this:
public class CustomView extends RelativeLayout {
private Activity activity;
public CustomView(Activity activity) {
super(activity.getApplicationContext());
this.activity = activity;
initialize(activity.getApplicationContext());
}
//initialize method
}
This is the exact message Android Studio gives me:
Custom view CustomView is missing constructor used by tools: (Context) or (Context,AttributeSet) or (Context,AttributeSet,int)
Should I ignore this or should I pass in constructor both: activity and context?
Thanks for all information!
Better pass Context instead of Activity, because its possible to call View with Context but without Activity. For example if you call Dialog from Service.
Also based on documentation there is only one constructor is really necessary. But that constructor has contain AttributeSet as argument.
In your case it should looks like
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
this.activity = (Activity) context; //better to hold context actually
initialize(context);
}
And for sure good practice is to use all available constructors
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 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.
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.
I have a MyPreferenceActivity that extends PreferenceActivity like this :
public class MyPreferenceActivity extends PreferenceActivity{
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
}
I also have custom shared preferences that R.xml.preferences are tied to by individual preference classes...for e.g.
preferences.xml has
<!--EditTextPreference-->
<com.myapp.preferences.PrimaryNumberPreference
android:key="PREFS_PRIMARY_NUMBER"
android:title="#string/primary_number_preference_title"
android:summary="#string/primary_number_preference_summary"
android:dialogTitle="#string/primary_number_preference_dialog_title"
android:dialogMessage="#string/primary_number_preference_dialog_message"
/>
PrimaryNumberPreference.java :
public class PrimaryNumberPreference extends EditTextPreference {
Context ctx = null;
public PrimaryNumberPreference(Context context) {
super(context);
this.ctx = context;
}
public PrimaryNumberPreference(Context context, AttributeSet attrs) {
super(context, attrs);
this.ctx = context;
}
public PrimaryNumberPreference(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.ctx = context;
}
#Override
protected void onDialogClosed(boolean positiveResult) {
super.onDialogClosed(positiveResult);
if (positiveResult){
customPreferenceibrary.setPrefsPrimaryNumber(getText());
}
}
}
OK so all seems to be in place. Now what I want is everytime the PreferenceActivity is loaded, it should fetch the current sharedpreference values that are stored in their respective key and prepopulate the elements of the PreferenceActivity...
Eg: PrimaryNumber shared preference is set to 1234 when my app is installed. Now if I go to MyPreferenceActivity and browse the PrimaryNumber EditTextPreference, the text box should be prepopulated by 1234.
Something(pseudo code) like :
MyPreferenceActivity.PrimaryNumberPreference.Val = getSharedPreferences(prefsPrimaryNumber)
How can I do that?
EDIT
Please let me know if the question is unclear and needs better explanantion. I am sure the answer is a simple implementation of something very standard in android. All PreferenceActivity elements pick the current value to be displayed from the stored SharedPreferences only, right?
I think I see two potential problems:
Problem One
If you have a custom preference such as the PrimaryNumberPreference.java you need to manually save the preference when the dialog closes. Is that what you are doing in customPreferenceibrary.setPrefsPrimaryNumber(getText()); ??
If they are not committed in this function then I think they need to be. (Or committed somewhere else in onDialogClosed)
Problem Two
Assuming you are commiting the preferences in setPrefsPrimaryNumber, I think the setPrefsPrimaryNumber needs to receive two paramenters,
The preference name
The actual value
I dont think it is enough just to have the key name set in XML (android:key="PREFS_PRIMARY_NUMBER is not enough)
Hope this helps.
I figured out the answer with the help of suggestions provided by #Mel and Its very easy.
In the class that extends the corresponding PreferenceActivity element(e.g. shown below) just add this.setValue in the constructor of that preference element class. Thats it!
public class selectColorPreference extends ListPreference{
Context ctx = null;
private String error = null;
private int prefsRemoteSMSAccess;
MyPreferencesLibrary myPreferencesLibrary;
public selectColorPreference(Context context) {
super(context);
this.ctx = context;
myPreferencesLibrary = new MyPreferencesLibrary(ctx);
this.setValue(myPreferencesLibrary.getSharedPreferenceValueForColor());
}
}