I am trying to invoke a method named "change_color()" in my one fragment "A" from another fragment "B" using an interface, implemented by the parent activity. When I try to cast my parent activity to the instance of my interface, I get this ClassCastException.
Here's the snippet of fragment "B",
Public class B extends Fragment implements View.onClickListener{
public attendance_to_history var;
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_attendance_take,
container, false);
return rootView;
}
public void onActivityCreated(Bundle savedInstanceState){
super.onActivityCreated(savedInstanceState);
var = (attendance_to_history) getActivity();
}
Here's the code of interface
interface attendance_to_history{
public void invoke();}
Here's code from my parent activity:
public class tabbed_activity extends AppCompatActivity implements attendance_to_history{
#Override
public void invoke() {
fragment_A frag = new fragment_A();
frag.change_color();
}
}
attendance_to_history connector;
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
connector=(attendance_to_history) activity;
}
replace instead for onActivityCreated
here is the solution:
1- in the activity that holds the fragment B, make it implements attendance_to_history and override the method invoke inside the activity.
then your code will work fine.
Related
I want to set the text of textview in activity from a fragment. This is how I do it.
MainActivity.java
public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
public TextView textViewNotification;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
NavigationView navigationView = findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
textViewNotification = (TextView) MenuItemCompat.getActionView(navigationView.getMenu().findItem(R.id.nav_notification));
}
}
HomeFragment.java
public class HomeFragment extends Fragment {
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
((MainActivity)getActivity()).getSupportActionBar().setTitle("PIT IAI & FIP Regional");
ViewGroup root = (ViewGroup) inflater.inflate(R.layout.fragment_home, container, false);
MainActivity activity = (MainActivity) getActivity();
activity.notification.setText("This is a test"); // => got error here.
return root;
}
}
But it didin't work. This is the error that I got:
android.content.res.Resources$NotFoundException: String resource ID #0x1
at android.content.res.Resources.getText(Resources.java:348)
at android.widget.TextView.setText(TextView.java:5846)
How is it exactly to get and set public attributes of activity from fragments? is it not possible? Please help.
Supposed you want to send the text to the activity based on some action.
You can use an interface, first create a public interface in your fragment and add one method inside it which takes one string parameter
public interface CommunicateWithActivity{
void onCommunicate(String s)
}
, declare a global variable mListener of type CommunicateWithActivity,
private CommunicateWithActivity mListener;
then override onAttach and inside try/catch block
#Override
public void onAttach(#NonNull Context context) {
super.onAttach(context);
try {
mListener = (CommunicateWithActivity) context;
} catch (ClassCastException e) {
throw new ClassCastException(context.toString() + "CommunicateWithActivity implementation in Activity is required");
}
}
then in the activity implement the interface an override "onComunicate(String s)" method in the activity and you will get your string inside the methd.
#Override
public void onCommunicate(String s) {
//do whatever you want
}
Henry Gunawan your MainActivity does not have any public field called notification you actually named it textViewNotification.
Moreover i am seeing some bad practices in your code
Avoid declaring public fields instead use getters and setters to access them
Your fragment assuming that it's host is always a MainActivity instance and it has a field called notification , which is not a good practice , fragments are meant to be a standalone unit, fragments should not depends on specifics of their host activity as they may be host by any activity hence this is a misuse of fragments, use should instead use callbacks if you want your host activity to do something for you as explained by Amr Sakr.
There are so many ways but i am using this one:
Activity:
public class Main2Activity extends AppCompatActivity{
private String myString = "hello";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
...
}
public String getMyData() {
return myString;
}
}
Fragment:
public class MyFragment extends android.support.v4.app.Fragment{
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Main2Activity activity = (Main2Activity ) getActivity();
String myDataFromActivity = activity.getMyData();
return view;
}
}
BUT its giving me class cast exception:
java.lang.ClassCastException: com.example.dev03.xyz.Activities.MainActivity cannot be cast to com.example.dev03.xyz.Fragments.MyActivity
java.lang.ClassCastException: com.example.dev03.xyz.Fragments.MainActivity cannot be cast to com.example.dev03.xyz.Fragments.Main2Activity
-- Package is same
Thanks
Create an object of MainActivity2 and simply access your method:
MainActivity2 mn2=new ManiActivity2();
mn2.getMyData();
You are opening your fragment in MainActivity and want to cast in MyActivity. That's why it is showing ClassCastException
Changing from android.app.Fragment to support.v4.app.Fragment this.
In your Activity
Bundle bundle = new Bundle();
bundle.putString("name", "StackOverFlow");
// set Fragmentclass Arguments
Fragmentclass stackOverflow = new Fragmentclass();
stackOverflow.setArguments(bundle);
In Fragments > onCreateView Method.
String strName = getArguments().getString("name");
I'm still trying to grasp the Dagger mindset of Dependency Injection, and am running into some trouble. I have a MyNavBar which is a View in a fragment. I can't figure out how to inject my app's MainWrapper class into it. Here's how my code is laid out:
I have a MainActivity in my app's Android module:
public class MainActivity extends Activity {
private MainWrapper mainWrapper;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Create the basic interface which will have parts swapped out with
// fragments in MainWrapper:
this.setContentView(R.layout.main);
ObjectGraph graph = ObjectGraph.create(new MyDaggerModule(this));
this.mainWrapper = new MainWrapper(graph);
}
Then, MainWrapper exists in the library which contains almost all of my app's code:
public class MainWrapper {
#Inject
protected MenuFragment menu;
#Inject
protected Activity activity;
private ObjectGraph objGraph;
public MainWrapper(ObjectGraph objGraph) {
this.objGraph = objGraph;
this.objGraph.inject(this); //populated this.menu and this.activity
Fragment mainFragment = new MainFragment();
this.objGraph.inject(mainFragment);
//Transaction to swap out blank fragment for mainFragment
// ...
}
}
MainFragment is a pretty standard fragment:
public class MainFragment extends Fragment {
protected MyNavBar navBar; //LinearLayout
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View mainContentView = inflater.inflate(R.layout.main_content, container, false);
this.navBar = (MyNavBar) mainContentView.findViewById(R.id.main_nav_bar);
return mainContentView;
}
}
Lastly, here's the MyNavBar fragment:
public class MyNavBar extends UILinearLayout {
#Inject
protected MainWrapper wrapper;
protected View menuButton;
//Constructors that call init() at the end
// ...
protected void init() {
this.setContentView(R.layout.navbar);
this.menuButton = this.findViewById(R.id.menuBtn);
this.menuButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
//I want to call methods on MainWrapper here.
}
});
}
}
How can I get MainWrapper to inject wrapper into that MyNavBar class using DI? I realize I could inject MainWrapper into MainFragment, then create a setter on MyNavBar, but that seems to defeat the purpose of DI in the first place.
I guess ultimately what I'm asking is this: If you have your main Activity, which creates a fragment, and that fragment has views, how can you inject into those fragment's views while keeping the ObjectGraph only in the main activity? At some point, won't you have to call objectGraph.inject() on the fragment's Views?
i am creating two java file 1st main activity.java file 2nd fragment.java file create button on fragment.java how to click listener written on activity.java help me
fragment.java
public class fragment extends fragment{
Button btn;
// some code
btn = (Button)layout.findviewbyid(R.id.btn1);
}
}
activity.java
public class activity extends Activity
{
// how to access the click action btn here
btn.setOnclicklistner(new View.OnClickLisitner(){
public OnClick(){
}
To use the button in activity from the fragment, you have to use getActivity()
In your fragment,
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_item_select, container, false);
btn = (Button) getActivity().findViewById(R.id.btn);
}
btn is the button in activity
getActivity() in a Fragment returns the Activity the Fragment is currently associated with. (see http://developer.android.com/reference/android/app/Fragment.html#getActivity()).
You can define custom clickListener class and create it's instance in fragment and set listener instance there. Now you can write code in that class. Hope it will help you.
public class MyCustomListener implements OnClickListener{
#override
public void onClick(View v){
// you stuff
}
}
then in your fragment call this
MyCustomListener listener=new MyCustomListener();
btn.setOnClickListener(listener);
Here is my take on the issue, both in Java and Kotlin.
Java:
public final class YourActivity extends AppCompatActivity {
/***/
public final void yourMethod() {
printIn("Printing from yourMethod!")
}
}
public final class YourFragment extends Fragment {
/***/
#Override
public void onViewCreated(View v, Bundle savedInstanceState) {
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
YourActivity yourActivity = (YourActivity) getActivity();
yourActivity.yourMethod();
}
}));
}
}
Kotlin:
class YourActivity : AppCompatActivity() {
/***/
fun yourMethod() {
print("Printing from yourMethod!")
}
}
class YourFragment: Fragment() {
/***/
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
button.setOnClickListener {
val yourActivity = activity as YourActivity
yourActivity.yourMethod()
}
}
}
I hope it helps someone out there =)
If I understand your problem correctly, you want to delegate a button click inside a fragment back to its parent activity.
Keep a reference to the parent activity inside your fragment. Then set the listener to your button in your fragment like this:
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
parentActivity.doStuff();
}
};
In your parent Activity, define method doStuff():
public void doStuff() {
// handle button click event here
}
I have this class here which calls the method setPoint
public class PointsList extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.listpoints, container, false);
public static class PointCreation extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.point_creation, container, false);
setPoint(view, CREATE);
return view;
}
}
static final void setPoint(View view, int goal) {
final EditText SerialField = (EditText) view.findViewById(R.id.Serial);
if(goal == CREATE) {
Button buttonGuardar = (Button) view.findViewById(R.id.buttonGuardar);
buttonGuardar.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String Serial = SerialField.getText().toString();
pointsList.add(new Serial);
//go back to R.layout.listpoints
}
});
}
}
My goal is after I click the button to add the new Serial to the List, I can go back to the previous menu from
R.layout.point_creation to R.layout.listpoints
To move around fragments I generally use something like this:
Fragment fragment = new PointsList();
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.container, fragment)
.commit();
But inside:
static final void setPoint(View view, int goal)
getActivity().getSupportFragmentManager();
cannot be referenced from a static context, and I don't know how to go around it with making the static class non-static? I've some global flags which I use in the static Classes (have 2 of them) that would be a bit painfull to export since
public class PointCreation(int something) extends Fragment
is something I can't do.
You can get the activity from view:
Activity activity = (Activity)view.getContext()
If you use FragmentActivity (it seems to be so), then cast Context to FragmentActivity (instead of regular Activity) and further you will able to call getSupportFragmentManager()
FragmentActivity activity = (FragmentActivity)view.getContext();
FragmentManager manager = activity.getSupportFragmentManager();
You can use by below code;
private static FragmentActivity myContext;
#Override
public void onAttach(Activity activity) {
myContext = (FragmentActivity) activity;
super.onAttach(activity);
}
You can use myContext as Context
You can't reference from a static to non-static objects. First thing, that comes to mind is to use singleton pattern for your fragment. In other words add to you fragment singleton snippet:
static PointsList instance;
public PointsList getInstace(){
if(instance == null){
instance = new PointsList ();
}
return instance;
}
and in your fragment onCreate method assign it to the instance:
instance = this;
after that you can remove static modifier from setPoint method. And call it from any part of your project like PointsList.getInstance().setPoint();
p.s. what goals from static you have to use? You should use static very carefully, many things can be done through singleton instead of using statics.