I'm trying to load fragment after alert Dialog response but when i attempt to load logcat shows "IllegalStateException: Fragment not attached to Activity". Generally IllegalStateException comes when you try to perform work after the Fragment is no longer attached to the Activity. but in my case every thing is fine i don't understand why fragment is not attached to an activity.
this is my MainActivity:
using this class i call DilogCreate which extends DialogFragment.
public class MainActivity extends AppCompatActivity {
Button btn;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn= (Button) findViewById(R.id.button);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
new DilogCreate(view.getContext(),R.string.tilte,R.string.no,R.string.yes);
}
});
}
this is my DilogCreate class:
on the basis of dialog response decide fragment can be loaded or not if dialog response yes i call another activity name Second.java under this class i try to load fragment.
public class DilogCreate extends DialogFragment {
AlertDialog alertDialog;
public DilogCreate(final Context context, int tilte, int no, int yes) {
AlertDialog.Builder mAlertDilog = new AlertDialog.Builder(context);
mAlertDilog.setNegativeButton(yes, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
Intent intent = new Intent(context, second.class);
startActivity(intent);
}
});
alertDialog = mAlertDilog.create();
alertDialog.show();
}
}
this is my my Second.java class:
this class is appear because of dialog response and under this class i tried to load fragment.
public class Second extends AppCompatActivity {
FragmentManager fragmentManager;
FragmentTransaction fragmentTransaction;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.loadFragment);
fragmentManager=getSupportFragmentManager();
fragmentTransaction=fragmentManager.beginTransaction();
Myfragment myfragment=new Myfragment();
fragmentTransaction.replace(R.id.cont,myfragment);
fragmentTransaction.commit();
}
}
this is MyFragment.java extends Fragment :
public class Myfragment extends Fragment{
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.frag,container,false);
}
}
Logcat status:
java.lang.IllegalStateException: Fragment DilogCreate{8aea1d4} not attached to Activity
please help me guys i have no idea why this error is coming.
new DilogCreate(view.getContext(),R.string.tilte,R.string.no,R.string.yes);
pass MainActivity.this instead of view.getContext().You need to pass activity context here.
fragment is load on the activity and one activity switch to another by using base reference that's why i need to call startActivity() method using base Activity refrence.
so i change startActivit() method in the DilogCreate class like this:
Intent intent=new Intent(context,Second.class);
context.startActivity(intent);//make sure context is the refrence of the base context
Related
I wanted to test if a dialog Fragment is shown or not, with Roboelectric.
public class SomeDialogActivity extends FragmentActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
DialogFragment someDialogFragment = new SomeDialogFragment();
someDialogFragment.show(getSupportFragmentManager(), "some_dialog");
}
}
Now I wanted to test if this dialog is shown, something like this:
#Test
public void dialogFragmentIsShownToTheUser() {
DialogFragment dialog = new SomeDialogFragment();
DialogFragment someDialogFragment = new SomeDialogFragment();
startFragment(someDialogFragment);
SomeDialogActivity activity = Robolectric.setupActivity(SomeDialogActivity.class);
Dialog dialog = ShadowDialog.getLatestDialog();
assertNotNull(dialog);
assertEquals(.... , ....)
}
Treat it as normal fragment situation. So to check that fragment is shown you need to have next code:
#Test
public void dialogFragmentIsShownToTheUser() {
SomeDialogActivity activity = Robolectric.setupActivity(SomeDialogActivity.class);
DialogFragment dialogFragment = (DialogFragment) activity.getSupporFragmetManager()
.findFragmentByTag("some_dialog");
assertNotNull(dialogFragment);
}
I have an activity and a fragment inside it.inside fragment, there is a button, and on click of button a dialog shows.
Everything works, until user do a orientation change and click button after it.
IllegalStateException(cannot perform this action after onsaveinstancestate) occurs when user clicks button after orientation change. I'm using android support framework.
Anybody have any idea regarfing this?
Activity Code
public void openMoreDialog(String shareData, String link) {
DialogFragment dialog = new MoreDialog(shareData, link);
dialog.show(getSupportFragmentManager(), "MoreDialog");
}
Fragment Code
public void onAttach(Activity activity) {
super.onAttach(activity);
mControl = (ActivityControl)activity;
}
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
ImageButton moreButton = (ImageButton)v.findViewById(R.id.moreButton);
moreButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
mControl.openMoreDialog(shareData, link);
}
});
return rootView;
}
FragmentDialog code
public class MoreDialog extends DialogFragment {
private String mShareData;
private String mLink;
public MoreDialog(String shareData, String link){
mShareData = shareData;
mLink = link;
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// Get the layout inflater
LayoutInflater inflater = getActivity().getLayoutInflater();
View dialogView = inflater.inflate(R.layout.more_dialog, null);
Button openBtn = (Button)dialogView.findViewById(R.id.openBtn);
openBtn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
openLink(mLink);
}
});
Button shareBtn = (Button)dialogView.findViewById(R.id.shareBtn);
shareBtn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
shareNews(mShareData);
}
});
builder.setView(dialogView);
return builder.create();
}
private void openLink(String link){
}
private void shareNews(String data){
}
}
Helpful link & solution how to:
https://stackoverflow.com/a/17413324/619673 and btw, constructor in fragment must be empty! Documentation:
http://developer.android.com/reference/android/app/Fragment.html
public Fragment ()
Added in API level 11
Default constructor.
Every fragment must have an empty constructor, so
it can be instantiated when restoring its activity's state. It is
strongly recommended that subclasses do not have other constructors
with parameters, since these constructors will not be called when the
fragment is re-instantiated; instead, arguments can be supplied by the
caller with setArguments(Bundle) and later retrieved by the Fragment
with getArguments().
Applications should generally not implement a constructor. The first
place application code an run where the fragment is ready to be used
is in onAttach(Activity), the point where the fragment is actually
associated with its activity. Some applications may also want to
implement onInflate(Activity, AttributeSet, Bundle) to retrieve
attributes from a layout resource, though should take care here
because this happens for the fragment is attached to its activity.
Can I implement a Cordova WebView in a CustomDialog in android?
I want to click a button and this show me a dialog with the webview. I tried in this way but didn't work.
button = (Button) findViewById(R.id.buttonShowCustomDialog);
// add button click listener
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
// custom dialog
final Dialog dialog = new Dialog(context);
dialog.setContentView(R.layout.custom);
dialog.setTitle("Title...");
cwv = (CordovaWebView) findViewById(R.id.webview);
Config.init(this);
cwv.loadUrl("file:///android_asset/www/index.html");
dialog.show();
}
});
UPDATE2:
In fact, the extended Dialog doesn't event need to implement CordovaInterface. It just needs to override setContentView, and that's enough.
public class CordovaDialog extends Dialog {
private Context currentContext;
public CordovaDialog(Context context) {
super(context);
this.currentContext = context;
}
// we have to override this because we need to disable attaching to root when inflating (wtf cordova ??)
#Override public void setContentView(int layoutResID) {
final LayoutInflater inflater = LayoutInflater.from(this.currentContext);
View v = inflater.inflate(layoutResID, null, false);
super.setContentView(v);
};
}
I have the same issue. I have also tried to create a class which extends Dialog and implements CordovaInterface, but didn't have any luck witjh that either. It seems every time I call setContentView, Cordova just can't find the Activity associated to the Dialog, and logcat shows a warning saying that my Activity doesn't implement CordovaInterface but it does.
UPDATE:
Ok, I figured it out. So here's how I dit it. It's long but it works.
First of all, let's assume that the parent Activity, the one which is creating the dialog, is already implementing CordovaInterface. Also, let's say that your CordovaWebview is inside a layout.
Make a new class (CordovaDialog for example) which extends Dialog and implements CordovaInterface.
Make a new constructor for the CordovaDialog class which passes the context and the interface so you can set the CordovaInterface from parent activity (which should also implement CordovaInterface).
Override setContentView in the CordovaDialog so that it inflates the view without attaching to root (last params set to false).
In your main activity, create the dialog, call Config.init(), and call loadUrl for CordovaWebview.
public class CordovaDialog extends Dialog implements CordovaInterface {
CordovaInterface parentCordovaInterface;
Context currentContext;
public CordovaDialog(Context context, CordovaInterface ci) {
super(context);
this.parentCordovaInterface = ci;
this.currentContext = context;
}
#Override public void setContentView(int layoutResID) {
final LayoutInflater inflater = LayoutInflater.from(this.currentContext);
View v = inflater.inflate(layoutResID, null, false);
super.setContentView(v);
};
#Override
public Activity getActivity() {
return this.parentCordovaInterface.getActivity();
}
#Override
public ExecutorService getThreadPool() {
return this.parentCordovaInterface.getThreadPool();
}
#Override
public Object onMessage(String arg0, Object arg1) {
return this.parentCordovaInterface.onMessage(arg0, arg1);
}
#Override
public void setActivityResultCallback(CordovaPlugin plugin) {
this.parentCordovaInterface.setActivityResultCallback(plugin);
}
#Override
public void startActivityForResult(CordovaPlugin command, Intent intent, int requestCode) {
this.parentCordovaInterface.startActivityForResult(command, intent, requestCode);
}
}
And then in your the activity which implements CordovaInterface:
final CordovaDialog dialog = new CordovaDialog(this, this);
dialog.setOwnerActivity(this);
dialog.setContentView(R.layout.dialog_with_cordovawebview);
CordovaWebView cwv = (CordovaWebView) dialog.findViewById(R.id.webViewDialog);
Config.init();
cwv.loadUrl("file:///android_asset/www/index.html");
dialog.show();
From an activity, I can easily setup the onActivityResult() and call startActivityForResult() and everything works fine.
Now, I need to call startActivityForResult() from the Dialog. But I can't setup the onActivityResult(), I believe Dialog is not an Activity.
How do I get the result?
I try something like this inside a dialog but it failed.
//create new Intent
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, m_PicUri);
((Activity) getContext()).startActivityForResult(intent, Const.TAKE_PIC_ACTIVITY_RET_CODE);
You can declare your Activity to have a Dialog theme. Look into this SO question: Android Activity as a dialog
You would change this in your AndroidManifest.xml file:
<activity android:theme="#android:style/Theme.Dialog" />
You should be able to use startActivityForResult() like normal. I know the BluetoothChat example Android program uses something similar to return the Bluetooth device that you choose from a Dialog list.
if your dialog is a dialog fragment you can use
getActivity().startActivityForResult(intent);
in this way the result is sent to the activity that created the dialog
You can use DialogFragment instead of Dialog. Because The dialog is secondary to its activity. When you start the activity with startActivityForResult(), your dialog gets dismissed
Another Example Use Callback
Create Interface
public interface DialogCallback {
void getResults(String results);
}
Create DialogFragment
public class DialogFragment extends DialogFragment {
DialogCallback dialogCallback;
public DialogFragment setCallBack(DialogCallback dialogCallback){
this.dialogCallback = dialogCallback;
return this;
}
#NonNull
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
return super.onCreateDialog(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.your_layout, container, false);
return view;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public void onDismiss(DialogInterface dialog) {
super.onDismiss(dialog);
dialogCallback.getResults("hello");
}
}
In your Activity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
new DialogFragment().setCallBack(dialogCallback).show(getFragmentManager(),"");
}
DialogCallback dialogCallback = new DialogCallback() {
#Override
public void getResults(String results) {
if(results!=null){
Log.e(TAG,results);
}
}
};
Output
When you dismiss the DialogFragment you will see the "hello" Log in your Activity
Use the compatibility package then build your dialog using DialogFragment
On the dialog constructor pass the reference of parent Activity, then you can use in the dialog like this,
parentActivity.startActivityForResult(intent, CODE);
Okay i keep getting this error when i have a button click launch another Fragment..
07-30 20:54:05.950: ERROR/AndroidRuntime(7816): Caused by: java.lang.ClassCastException: com.fttech.gameIT.shopping_details_fragment cannot be cast to android.app.Activity
07-30 20:54:05.950: ERROR/AndroidRuntime(7816): at android.app.Instrumentation.newActivity(Instrumentation.java:1022)
07-30 20:54:05.950: ERROR/AndroidRuntime(7816): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1663)
Here is what i am trying to do, when the button findIt is clicked from this activity..
public class shoppingClass extends FragmentActivity{
Button findIT;
EditText game;
String item = null;
WebView browser;
RadioGroup site;
RadioGroup type;
String url;
String console;
shopping_details_fragment shopping;
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.shopping);
findIT = (Button)findViewById(R.id.findIT);
shop = (EditText)findViewById(R.id.item);
type = (RadioGroup)findViewById(R.id.console);
site = (RadioGroup)findViewById(R.id.shopping_group);
final Intent d = new Intent(this, shopping_details_fragment.class);
findIT.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getUserPreference();
shopping.loadUrl(url);
startActivity(d);
}
});
}
I am launching another this Fragment into the view...
public class shopping_details_fragment extends Fragment{
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
//Return the view for our WebView
return(inflater.inflate(R.id.browserFrag,container, false));
}
public void loadUrl(String url){
((WebView)getView().findViewById(R.id.browser)).loadUrl(url);
}
}
This uses the browser i have set up in the same xml that the first activitiy is set up in to launch a webbrowser and look up a URL in a fragment i have set..
Its getting the browser in loadUrl() from a webview layout i created and inflating it into the fragment.
But i keep getting the error above.
Fragment and Activity aren't directly related like that, you can't just cast between them. Use the getActivity() method on the fragment instead, to return its activity.