Android : how to set context to a view in layout xml? - android

I am using WebView in an ActivityGroup and it will throw an exception if WebView show Dialog and complain the activity is not valid. But it's okay if I set the context of the WebView to the TOP activity. So I wish to know how to set the context in the layout xml ?

You can use layoutinflater to achieve this:
View viewToLoad = LayoutInflater.from(this.getParent()).inflate(R.layout.yourLayoutName, null);
this.theSpinner = (Spinner) viewToLoad.findViewById(R.id.Spinny);
this.setContentView(viewToLoad );
Hope that helps. for dialog you can just change context from this to
this.getParent()

So I wish to know how to set the context in the layout xml ?
That's not possible. Though, I have some experience with ActivityGroup, so I know how to solve this problem:
// in your ActivityGroup...
public class YourActivityGroup extends ActivityGroup{
public static YourActivityGroup self;
public YourActivityGroup(){
self = this;
// the rest of your code here
}
}
Then, when you need a context in order to show a dialog or a Toast or whatever, you use YourActivityGroup.self.

Related

Clicking a link in a TextView that is part of an adapter in android

I am designing a chatting app where I am required to make links clickable inside a TextView. I have used android:autoLink="all" in TextView to distinguish links/phones etc.
This works up to displaying the part of TextView that are links/phones as clickable but when I click it, I get the following exception:
android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
I searched a bit and it seems that I need to pass the activity context while inflating the TextView from XML. But how can I do that as i am inflating this view inside an adapter? This TextView is part of card view that is part of a recycler view in an adapter.
Instead of using layoutInflater.inflate() to inflate the view, I used LayoutInflater.from(parent.getContext()).inflate() and it worked.
Either use the Parent Activity to start a new activity from adapter or set the Intent flag.
For parent activity pass the Activity to Adapter's Construcutor and initialize it to use in the adatper like this.
in you MainActivity
Activity activity = this;
MyAdapter _adpater = new MyAdapter(....., activity);
in MyAdapter class
//constructor
Activity activity;
public MyAdapter (......, Activity _activity) {
........
this.activity= _activity;
}
now you can use this activity to start new activity.
activity.startActivity(new Intent(activity,target.class));
or you can try setting the flag with your current method.
context.startActivity(new Intent(context.getApplicationContext, target.class).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));

android button in class

All i want to do is to have a class that creates dynamically a button and fills it with the text 'tarr' automatically. So i generated a new class and wrote the following in it:
import android.widget.Button;
public class FloatButton {
Button button = new Button(this);
button.setText("tarr");
}
in my main activity it should make an object of this class. So i wrote this in the activity (snippet):
...
public void onCreate() {
super.onCreate();
FloatButton myButton = new FloatButton();
}
Sadly this gives me some mistakes marked. The mistake i don't realy understand is why the 'this' is marked. Can you tell me the problem?
When sending this to the Button constructor method, you are not sending a
valid Context, but your FloatButton object.
Android Context
What you can do is :
public class FloatButton {
private Context _context;
public FloatButton(Context context) {
this._context = context;
}
public createButton() {
Button mButton = new Button(_context);
mButton.setText("tarr");
}
}
PS : Why are you trying to create a button in a separate class, and not directly in your activity ?
You are trying to create a button dynamically and then add it to your activity.
The thing you are doing wrong is obviously not providing any context and two, you are not adding it to your activity's layout without which you will not be able to actually 'display' the button.
Here's what you need to do:
Create a function in the FloatButton class which receives a context and returns a button object as:
public Button createNew(Context c){
Button b = new Button(c);
b.setText("tarr");
return b;
}
In your main class, create a FloatButton object and call the createNew function as:
FloatButton fb = new FloatButton();
Button button = fb.createNew(this);
This will give you a button object which you then have to add to your layout
Now you need to declare the mandatory layout parameters which are height and width. Do it as:
LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT);
Get your activity's primary layout (LinearLayout or RelativeLayout) as:
LinearLayout ll = (LinearLayout)findViewById(R.id.layout_main);
where layout_main is the id of your layout
Finally add your button to the layout and set its layout parameters as:
ll.addView(button, lp);
Though I would NOT recommend doing such a thing because you can replace the FloatButton class creation and instantiate using a simple Button button = new Button(this) in your main class itself. So, it is very redundant unless you want to do several customizations to your button in the FloatButton class itself like making it a different color or something and creating the button several times at several places.

Access to getString() in android.support.v4.app.FragmentPagerAdapter?

In a class extending android.support.v4.app.FragmentPagerAdapter, is there any way to get access to the Context.getString(..) method without the extending class being an inner class of an activity or passing in some context from the outside?
Thanks for any hint!
From a fragment use :
getActivity().getString(...)
From an adapter use :
getContext().getResources().getString(...)
Yes, you need a context to access the resources.
From an Activity, use:
this.getString(R.string.string_name);
From a Fragment, use:
getActivity.getString(R.string.string_name);
From an adapter, use:
getContext().getResources().getString(R.string.string_name);
I had a similar issue. From a drawer layout, I wanted to decide which fragment to use in a method called from a helper class.
So in onCreateView...
String form = getResources().getStringArray(R.array.drawer_array)[i];
Context context = getActivity().getApplicationContext();
FragmentHelper fh = new FragmentHelper();
int myFragment = fh.getCurrentFragment(form,context);
And in public FragmentHelper()...
public int getCurrentFragment(String form, Context context){
...
context.getResources().getString(R.string.label_item1);
...
}
The trick being to add context in front of getResources(). Otherwise, my stack showed that the fragment was not attached to an activity.
Hope this helps someone.

How to extend AlertDialog.Builder result?

I need to show an AlertDialog with a ListView and a context menu for the ListView items. I prefer to use AlertDialog.Builder and call setItems(), so the Builder creates a ListView inside the AlertDialog with stylized layout for me. For the stylizing it uses internal Android resources, so I cannot reimplement it in my code.
The problem is that I cannot catch a context menu item click event because of default AlertDialog.onMenuItemSelected() implementation, which does not forward such events to the parent:
public boolean onMenuItemSelected(int featureId, MenuItem item) {
return false;
}
I cannot extend AlertDialog.Builder class and force it to create an instance of my own AlertDialog with onMenuItemSelected() overridden because I need to override AlertDialog.Builder.create() for that. But it uses a private P variable, which is not accessible from a derived class:
public AlertDialog create() {
final AlertDialog dialog = new AlertDialog(P.mContext, mTheme, false);
P.apply(dialog.mAlert);
dialog.setCancelable(P.mCancelable);
if (P.mCancelable) {
dialog.setCanceledOnTouchOutside(true);
}
dialog.setOnCancelListener(P.mOnCancelListener);
if (P.mOnKeyListener != null) {
dialog.setOnKeyListener(P.mOnKeyListener);
}
return dialog;
}
Is there a way to force AlertDialog.Builder to construct a custom AlertDialog (with onMenuItemSelected method overridden)?
I still found no solution for the question, but I found some problems, which makes the solution useless. For Android 2.1, built-in ListView items (android.R.layout.select_dialog_item) are displayed as black text on dark grey background, ListView items are not separated from the dialog message (setMessage()), etc.
I finally switched back to my own AlertDialog with custom layout for ListView and its items (AlertDialog.Builer not used). Context menu events can be easily catched this way.
Luksprog, thanks a lot for your comments. But the main idea was to use as many stylized layouts, as possible. AFAIK, no standard layouts (android.R.layout.*) offer the buttons you mentioned. Also, an item could be removed occasionally with the button. With a context menu, at least two click required to remove an item.

onClick attribute in XML linking to method in Activity class

There are quite a few questions about this subject, but could not find any with the specific problem I have...
In my layout.xml, I use the android:onClick tag for a Button to call the right onClickListener. I get the error :
java.lang.IllegalStateException: Could not find a method handle_cancel(View) in the activity class com.matthieu.HelloWorldApplication for onClick handler on view class android.widget.Button with id 'button_cancel'
I have that method implemented in the Activity, but it is looking for it in the class that extends Application... I don't understand why. The View and all that is setup only in the Activity.
If anyone needs, here is the declaration of that method (in my activity, NOT in HelloWorldApplication):
public void handle_cancel(View v) {
// do something useful here
}
Edit (from adamp request)... and probably answering my own question :
Here is part of the code where that layout is used...
public class AddVocabularyActivity extends Activity
{
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.top); // that layout contains an empty LinearLayout id/main_content
}
private some_other_function() {
LinearLayout main_content = (LinearLayout) findViewById(R.id.main_content);
main_content.removeAllViews();
View.inflate(getApplicationContext(), R.layout.hello, main_content); // layout.hello is the one containing the button
}
// some other stuff
}
While copy/paste this code, I am guessing the problem is that I used getApplicationContext to inflate the View with that Button...
As mentioned in my edit, changing the getApplicationContext() with the Activity context fixes it...
The convention works like this:
In the layout xml file, you give this attribute:
android:onClick:"methodname"
Then, inside a class, you define a method like this:
public void methodname(View v){
//your method code
}
Any other way of doing this is not documented. If you need parameters, just call another method inside that method.

Categories

Resources