I'm trying return a String from the DialogFragment, following this instructions https://stackoverflow.com/a/14808425/2933117 , but I only get logcat error
java.lang.ClassCastException: com.example.testinterface.MainActivity cannot be cast to com.example.testinterface.InterDialog$EditNameDialogListener
I appreciate any help or explanation of why I get an error, thanks in advance.
Here is my code:
MainActivity
public class MainActivity extends FragmentActivity {
private Button Btn;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Btn=(Button)findViewById(R.id.button1);
Btn.setOnClickListener(new View.OnClickListener(){
public void onClick (View view) {
FragmentManager fm = getSupportFragmentManager();
InterDialog pruebafragment = new InterDialog();
pruebafragment.show(fm,"MyFragment");
}
});
}
public void onFinishEditDialog (String inputText) {
Toast.makeText(this, "Hi, " + inputText, Toast.LENGTH_SHORT).show();
}
}
and DialogFragment
public class InterDialog extends DialogFragment {
public interface EditNameDialogListener {
void onFinishEditDialog(String inputText);
}
public InterDialog() {
// Empty constructor required for DialogFragment
}
EditNameDialogListener activity;
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.new_layout, container);
activity = (EditNameDialogListener) getActivity();
Button button = (Button)view.findViewById(R.id.Btnreturn);
button.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
activity.onFinishEditDialog("errorrrr");
getDialog().dismiss();
}
});
return view;
}
}
The line:
activity = (EditNameDialogListener) getActivity();
is what is breaking it. Make sure your activity implements the EditNameDialogListener interface by doing
public class MainActivity extends FragmentActivity implements EditNameDialogListener {
Hope that helps
Related
I am having a fragment that contains for example one button, I want to allow the Activity containing the fragment to change this button view like for example color and title or src Image.
What's the best way to do that ?
Update : sorry If I wasn't clear enough but I want the activity to change the whole view as it's likes , like setting the padding, the color or anything.
It will create the view programmatically and the fragment should replace the old view by the new one and change the view's ID so that the fragment code isn't affected. And If i created methods in the fragment that takes these views when should the Main activity call them ? since the activity has to wait for the layout of the fragment to be created.
1. You must get you fragment from your activity
val fragment = supportFragmentManager.findFragmentByTag("tag")
or
val fragment = supportFragmentManager.findFragmentById(R.id.fragment)
2. Create a method that will do what you wants in you fragment and call this method from the activity
fragment.hideButton()
or you can use interface
Try this way according to your requirement
public abstract class BaseFragment extends Fragment {
BaseActivity yourActivity;
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
yourActivity = (BaseActivity) context;
}
#Override
public void onDetach() {
yourActivity = null;
super.onDetach();
}
public void refreshview(){}
public void setDada(Data data){}
#override
publicn void onStart(){
yourActivity.setCurrentOpenedFragment(this);
}
}
Create the BaseActivity class
public abstract class BaseActivity extends AppCompatActivity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
public void setCurrentOpenedFragment(BaseFragment currentFragment){}
}
Extends the BaseFragment in your fragment i.e.
public class YourFragment extends BaseFragment{
View view;
Button button;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment, container, false);
button = (Button)view.findViewById(R.id.button);
return view;
}
#override
publicn void onStart(){
super.onStart();
//yourActivity.setCurrentOpenedFragment(this);
}
Data data;
#override
public void setDada(Data data){
this.data = data;
}
#Override
public void refreshview() {
button.setcolor(data.getcolor());
}
}
Write the below line of code in your Activity class
public class YourActivity extends BaseActivity{
public static final byte NONE = -1;
public static final byte HOME = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.your_activity);
changeFragment(new YourFragment(), HOME);
initview();
}
public void initview(){
Button b = (Button)findViewById(R.id.button);
b.setOnClickListener(new OnClickListener(){
if(currentFragmentOnDrawer != null){
Data data = new Data();
data.setColor(getResource().getcolor(R.color.red));
currentFragmentOnDrawer.setDada(data);
currentFragmentOnDrawer.refreshview()
}
});
}
BaseFragment currentFragmentOnDrawer;
#Override
public void setCurrentOpenedFragment(BaseFragment currentFragment) {
super.setCurrentOpenedFragment(currentFragment);
this.currentFragmentOnDrawer = currentFragment;
}
public void changeFragment(Fragment targetFragment, byte state) {
FragmentTransaction ft = getSupportFragmentManager()
.beginTransaction();
ft.replace(R.id.main_fragment, targetFragment, "" + state);
ft.addToBackStack("" + state);
ft.commit();
}
}
Hope it will help for you
So basically, I have a dialog where the user inputs data. This dialog is launched from a recyclerView with a custom adapter. I need to call notifyDataSetChanged on the fragment from the dialog after the user clicks "finish".
How do I do this?
Code:
public class FoodListAdapter extends RecyclerView.Adapter<FoodListAdapter.ViewHolder>
implements View.OnClickListener {
//blabla
#Override
public void onClick(View v) {
int position = (int) v.getTag();
String foodItemTitle = mFoodItemList.get(position).getTitle();
FoodEditDietDialog dialog = new FoodEditDietDialog();
dialog.show(fm, mFoodItemList.get(position).getTimeStamp());
}
public class Fragment extends Fragment {
//blabla
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View fragment = inflater.inflate(R.layout.fragment, container, false);
foodList = databaseHelper.getList("somethingsomething");
recyclerView = Fragment.findViewById(R.id.list);
recyclerView.setHasFixedSize(false);
layoutManager = new LinearLayoutManager(this.getContext());
recyclerView.setLayoutManager(layoutManager);
adapter = new FoodListAdapter(fm, foodList);
recyclerView.setAdapter(adapter);
}
public class FoodEditDietDialog extends DialogFragment {
//blabla
button = dialog.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
databaseHelper.doSomething();
dismissDialog();
//TODO: call method in dietFragment to notify adapters
}
});
}
You need to do this through your hosting Activity.
public interface DataChangeListener {
void onDataChange();
}
public class YourActivity extends Activity implements DataChangeListener {
private List<DataChangeListener> dataChangeListeners = new ArrayList<>();
#Override
public void onDataChange() {
for(DataChangeListener listener in dataChangeListeners) {
listener.onDataChange();
}
}
public void addDataChangeListener(DataChangeListener listener) {
dataChangeListeners.add(listener);
}
public void removeDataChangeListener(DataChangeListener listener) {
dataChangeListeners.remove(listener);
}
}
public class Fragment extends Fragment implements DataChangeListener {
#Override
public void onAttach(Activity activity) {
if (activity instanceOf YourActivity) {
activity.addDataChangeListener(this)
}
}
#Override
public void onDetach() {
Activity activity = getActivity();
if (activity instanceOf YourActivity) {
activity.removeDataChangeListener(this)
}
}
#Override
public void onDataChange() {
adapter.notifyDataSetChanged();
}
}
public class FoodEditDietDialog extends DialogFragment {
//blabla
button = dialog.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
databaseHelper.doSomething();
dismissDialog();
//TODO: call method in dietFragment to notify adapters
Activity activity = getActivity();
if (activity instanceOf DataChangeListener) {
activity.onDataChange();
}
}
});
}
So basically, dialog will call activity, activity will notify fragment, fragment will notify adapters. Alternatively, you can pass your fragment (as DataChangeListener) to your adapter, and to your dialog. And call it from there.
I'm going from a Fragment -> Activity. In the activity I make an interface and when the user clicks a button I pass in a string to an interface object I create and call finish(). In the fragment I implement that interface and want to get that string. But in the activity I get a crash saying the listener is null.
public class SampleActivity extends AppCompatActivity
{
private Button button;
private MatchActivity.OnMatchCompleteListener onMatchCompleteListener;
public interface OnMatchCompleteListener
{
public void matchComplete(String matchID);
}
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.someButton);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
onMatchCompleteListener.matchComplete("finished");
finish();
}
});
}
}
Fragment
public class SampleFragment extends Fragment implements SampleActivity.OnMatchCompleteListener{
private View rootView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_login , container, false);
return rootView;
}
#Override
public void matchComplete(String matchID) {
Log.d("TEST",matchID);
}
}
if you have your fragment in the R.layout.activity_main and your fragment id is R.id.fragment use this:
onMatchCompleteListener =
((SampleFragment)getFragmentManager().findFragmentById(R.id.fragment))
otherwise use this solution:
SampleFragment fragment = new SampleFragment();
onMatchCompleteListener = fragment;
getFragmentManager().beginTransaction().add(R.layout.activity_main, fragment, "TAG_SIMPLE").commit();
I was able to create a single event callback from a fragment to the activity. However, I have problem with creating two event callbacks from the same fragment.
Basically, I have a button on the fragment1 layout, when click on it, it will execute something in mainactivity, and then, it changes hide the Button at fragment1 layout, and then I need to send a Boolean from the fragment to activity, then initiate fragment2.
How can I implement the 2nd callback interface in the mainacativity.
Here is my code:
at Fragment1:
public class Fragment1 extends Fragment{
private static final String TAG = "Fragment1";
Boolean in1, in2;
Button btn1;
ListenerA mListenerA;
public interface ListenerA{
public void methodA(Boolean in1);
};
ListenerB mListenerB;
public interface ListenerB{
public void methodB(Boolean in2);
};
#Override
public void onAttach(Context context) {
super.onAttach(context);
if(context instanceof ListenerA)
mListenerA = (ListenerA)context;
if(context instanceof ListenerB)
mListenerB = (ListenerB)context;
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View myView = inflater.inflate(R.layout.fragment1, container, false);
btn1 = (Button) myView.findViewById(R.id.btn1_ID);
btn1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mListenerA.methodA(true);
}
});
return myView;
}
public void showBtnMethod (Boolean showBtn){
if (showBtn==false) {
btn1.setVisibility(View.INVISIBLE);
mListenerB.methodB(true); //***** problematic line
}
}
}
and the code in the main activity is below. please note that on the first line I was able only to implement one method from the fragment.
public class MainActivity extends AppCompatActivity implements Fragment1.ListenerA {
private static final String TAG = "MainActivity";
public Fragment1 mFragment1;
public Fragment2 mFragment2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
FragmentTransaction transaction1 = getSupportFragmentManager().beginTransaction();
mFragment1 = new Fragment1();
transaction1.replace(R.id.content_fragment_ID, mFragment1);
transaction1.commit();
}
}
// this gets called by ListenerA when click on the button
public void methodA(Boolean in){
if (in==true){
Toast.makeText(MainActivity.this, "mMethodA Executed", Toast.LENGTH_SHORT).show();
triggerShowMethod();
}
};
private void triggerShowMethod(){
mFragment1.showBtnMethod(false);
};
// Problematic section is below
public void methodB(Boolean in){
if (in==true){
FragmentTransaction transaction2 = getSupportFragmentManager().beginTransaction();
mFragment2 = new Fragment2();
transaction2.replace(R.id.content_fragment_ID, mFragment2);
transaction2.commit();
Toast.makeText(MainActivity.this, "mMethodB Executed", Toast.LENGTH_LONG).show();
}
};
}
You can simply consolidate both interfaces into one:
public interface Listener{
public void methodA(Boolean in1);
public void methodB(Boolean in2);
};
and in your MainActivity:
public class MainActivity extends AppCompatActivity implements Fragment1.Listener
Your activity doesn't implement ListenerB.
public class MainActivity extends AppCompatActivity implements Fragment1.ListenerA, Fragment1.ListenerB {
}
I have a main activity class, and a private inner class within the main activity. The private inner class has methods that when called will display fragments. This inner class implements an interface defined in the Fragment's class, to be used as a sort of callback. It is probably easiest to show through code.
public class MainActivity extends FragmentActivity {
//on a button clicked
EditItemManger em = new EditItemManager();
em.begin();
private class EditItemManager implements on EditItemFragment.EditedItemClickedListener{
//consructor, other stuff. no onCreate method because this inner class does not (explicity??) extend activty
public void begin(){
EditItemFragment editItemFrag = new EditItemFragment();
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.add(editItemFrag, EDIT_FRAG_TAG)
fragmentTransaction.commit();
}
#Override
public void onEditItemClicked() {
editFinish();
}
public void editFinish()
{
// other stuff
}
}
}
My EditItemFragment class, where the onAttach method always has a null activity parameter
public class EditItemFragment extends DialogFragment {
protected EditedItemClickedListener editedItemClickedListener;
protected ImageButton button;
public EditItemFragment(){}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
final Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.edit_name_fragment, container, false);
button = (ImageButton) view.findViewById(R.id.submit_new_item_button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
editedItemClickedListener.onEditedItemButtonClicked();
}
});
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
editedItemClickedListener= (EditedItemClickedListener) activity;
} catch (ClassCastException e) {
e.printStackTrace();
}
}
public interface OnEditNameButtonClickedListener {
public void onEditNameButtonClicked();
}
So because the parameter in onAttach() in my Fragment class is always null, it eventually causes a null pointer exception. I am wondering if it is because the fragment is called from a class that is not extending activity. The problem is that if this class extends activity, there will be an issue with trying to commit the Fragment Transaction
I guest your onAttach returns nullpointer exception. Its because your parent Activity the main activity doesnt implement your custom interface so it return null. See the code below let me know if it help you:
public class MainActivity extends FragmentActivity implements EditItemFragment.EditedItemClickedListener{
private DialogFragment editItemDialog;
//Do your code here
#Override
public void onEditItemClicked() {
editFinish();
}
public void showDialog(){
//this is for showing your custom dialog fragment
editItemDialog = EditItemFragment.newInstance();
editItemDialog.show(getSupportFragmentManager(),"editItemDialog");
}
}
this is for your EditItemFragment:
public class EditItemFragment extends DialogFragment{
//Do your code here
public static EditItemFragment newInstance(){
EditItemFragment editItemDialog = new EditItemFragment();
return editItemDialog;
}
}