I have a class called MainGamePanel that extends SurfaceView where I run a thread that handles my updating and drawing code. Then I have an activity which runs editor.xml file which contains a Relative layout which runs my MainGamePanel and a FrameLayout which I am using as a container to hold a fragment. So I have the MainGamePanel taking up 2/3 of the screen and the fragment is on the right taking the remaining 1/3 of the screen.
The fragment contains a button that I want to use to reset objects that are located within my MainGamePanel. How can I access a member of MainGamePanel from my fragment or vice versa?
Here is the code for my fragment where I check for the button click
Button button = (Button) view.findViewById(R.id.resetGrid_button);
// A simple OnClickListener for our button. You can see here how a Fragment can encapsulate
// logic and views to build out re-usable Activity components.
button.setOnClickListener(new OnClickListener()
{
public void onClick(View v)
{
Activity activity = getActivity();
if (activity != null)
Toast.makeText(activity, R.string.reset_button, Toast.LENGTH_LONG).show();
}
});
Instead of just doing the toast I would like to have it reset some objects located in my MainGamePanel surfaceView class. Thank you for your time and any information you can send my way.
Answered:
I figured out that I have to get a handle to my view inside of my activity and have the activity access the information. Then when the user clicks the button in my fragment, I let the activity know and update the information.
you need to create an interface to communicate between the Activity and Fragment,
follow this example -
http://developer.android.com/training/basics/fragments/communicating.html
once your Activity knows about the pressed button you should call a public method within your custom class that will handle the desired logic.
Related
I have an activity like this:
There are 2 buttons A and B on toolbar and a frame for fragment to take over. Say I have a string variable named button_type in fragment.
I want to have a system so that when I click button A in activity, the button_type in fragment sets to A and when I click button B in activity, the button_type in fragment sets to B.
How to do this?
Please note that I may click the buttons (A,B) when the fragment is already active (its not like after I click one button, the fragment comes.)
Thanks in advance.
Edit:
Currently I am trying this:
In MainActivity I get similar string button_type and set it as A or B according as button click and use the method:
public String getData(){return button_type;}
And in fragment I use: button_type= activity.getData(); in onViewCreated.
But it only seems to have the initial set value of A and B (which is A) and does not change when another button is clicked.
I think the best way if you use an interface for managing text in the fragment. the fragment will implement the interface. When the button click call the function in the fragment which is implemented by fragment.
Another way you can create an object of the fragment using findFragmentByTag() or findFragmentById() and then call the function in the fragment which handles the text.
Create an interface with methods onClickA(String buttonType) and onClickB(String buttonType).
Then create an object that implements this interface (or make fragment implement this interface by itself). I'll call this object listener.
call setButtonType(String buttonType) in listener methods implementation.
Then pass your listener to activity (you can get an instance of parent activity in fragment with getActivity() and cast it to your activity class) and in onClickListener of button A (in activity) call listener.onClickA(yourString) and do the same thing for button B.
im creating redirect to some view on object method. this method doesn't use the parent view.
it works but when i click back navigation it doesn't showing the previous page (previous page is object oncreate() method itself), it return to the top parent activity. here is my code :
Object method on create :
public class FormDatabase extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.form_database);
method member of object method :
public void showArrayResult(View view)
{
setContentView(R.layout.profile_listview);
how can when i click back navigation i would return to previous object onCreate() method NOT the parent method (MAIN_ACTIVITY).
Hope my description is clear enough. Thanks.
To switch between different views in the same activity, and still maintain the ability to use the back stack (back button), you should probably use Fragments.
If the two views are completely independent then you should consider moving it into its own separate Activity.
You can override the onBackPressed() callback method to interrupt killing the activity and instead SetContentView as you did in onCreate()
EDIT
But Nic is right about moving to a fragment or another activity.
A component such as an activity should manage one task. Otherwise it is considered as bad practice.
I'm wondering why are the Fragments communicating through the container Activity are called reusable.
From: http://developer.android.com/guide/components/fragments.html I know that:
You should design each fragment as a modular and reusable activity
component. That is, because each fragment defines its own layout and
its own behavior with its own lifecycle callbacks, you can include one
fragment in multiple activities, so you should design for reuse and
avoid directly manipulating one fragment from another fragment.
Let's take an example; I have a DateSetFragment which contains two buttons; first button fires TimePickerDialog (FragmentDialog) which allows user to pick an hour and the second one DatePickerDialog (FragmentDialog) which allows user to pick a day. At the end gathered data should be sent back to the DateSetFragment.
According the: http://developer.android.com/training/basics/fragments/communicating.html:
All Fragment-to-Fragment communication is done through the associated
Activity. Two Fragments should never communicate directly.
communication between fragments should be done via interfaces through the container activity. Given that I should send my collected data from both Fragment Dialogs to the container activity and then from the Activity back to the DateSetFragment. I don't see how this make my DateSetFragment reusable and modular in any way. Doing so I have to implement fragment interfaces and some crucial logic in my container Activity which makes it connected with it.
The question is; Is it wrong in this situation if Fragment Dialogs will communicate directly with the DateSetFragment ?
It is "modular" because those interfaces are well defined and explicitly implemented by the hosting activity.
Anywhere you drop that fragment in, if the activity implements the callback interface defined by the fragment events the activity can choose what to do depending on what environment the fragment is attached in.
Example,
DatePickerFragment extends Fragment {
public interface DatePickerFragmentEventListener {
public void onDateSelected(DateTime dt);
}
}
Activity1 extends Activity implements DatePickerFragmentEventListener {
DatePickerFragment mDatePickerFragment;
OtherFragment mFragment2;
#Override
public void onDateSelected(DateTime dt) {
mFragment2.setSomeViewsText(dt.toString());
}
}
Activity2 extends Activity implements DatePickerFragmentEventListener {
DatePickerFragment mDatePickerFragment;
#Override
public void onDateSelected(DateTime dt) {
SharedPrefClient c = SharedPrefClient.getInstance();
c.setExpirationDateTime(dt);
}
}
I have a dateTimePickerFragment (or whatever), in one activity I have 2 fragments, when you change the date on the picker I want to update the other fragment's text view to display that date. In another activity I might use that exact same callback to write the chosen date to SharedPreferences.
The point is that the Fragment is a contained piece of UI interaction, and certain events it will notify the enclosing Activity of what just happened to it, so that the activity dictates that the result of an action on the fragment does to either other fragment or the application itself. There is no reason to implement a custom fragment for each and every situation.
Imagine this situation:
Activity.
Activity contains layout with 2 fragments. FragmentA and FragmentB
FragmentA has a layout with a button that should print a toast "Hello".
FragmentB has a layout with a button that should print a toast "Bye".
Both buttons have a onClick attribute set. First one with "sayHello" and second one with "SayBye".
So which is the correct way of finally displaying the toast?
Case A:
public class ActivityCustom extends FragmentActivity{
[...]
public void sayHello(View v){
//SHOW TOAST HERE
}
public void sayBye(View v){
//SHOW TOAST HERE
}
}
Case B:
public class ActivityCustom extends FragmentActivity{
[...]
public void sayHello(View v){
((FragmentA)this.findFragmentById(R.id.fragmentA)).showToast();
}
public void sayBye(View v){
((FragmentB)this.findFragmentById(R.id.fragmentB)).showToast();
}
}
I'm a bit confused about that.
Because if we delegate all the work on the fragments, I guess Activity will be kinda clear of code. It will just have the code to "connect" the two fragments, right?
I think this is a matter of OOP principles specifically "encapsulation", i don't think activity should contain code that do not care about, hence the proper way taking on count your example would be having each toast message in the Fragment because is their behavior and in case of modifications you actually know where to go, unlike having everything in the activity becoming the single point for every single functionality losing maintainability and extensibility, since there will be a point where all your code will rely on your activity. By the way there's nothing wrong on having Activities with just a few code, is actually good to keep code out of activity if it doesn't have to do with the activity life cycle itself...
Regards!
I believe you should show the toasts in each fragment. In FragmentA's onCreateView method, you get the button, add the listener and show the toast in the onCLick() method there. Same on FragmentB.
No problem for the activity to have less code.
This is a problem I didn't forsee when designing the structure of my applicaton.
Basically i have 3 classes.
ProfileActivity //The main activity for the application.
ProfileView //Which extends Linear Layout so that I can tinker with my own view. Note that this is just part of the whole activity and not the main layout
ProfileData //This is just a class for storing data.
The activity contains multiple ProfileViews which each contain one profileData.
Heres where I'm stuck. My profile View has an on click method assigned which needs to call a populate method in the activity. Unfortunately ````
//I'm inside the activity
public void populateProfileDataForm(ProfileData pd)
{
//edit some text fields and other widgets from here
}
Is there any way to call the activity method from the profileView class?
If not, then the error is in my design and can anyone point me towards a better solution for binding data, view and activitys?
When you create a view, you always need a context, and always pass a activity to it.
So try use below code:
If(m_context instanceof ProfileActivity)
{
ProfileActivity activity = (ProfileActivity)m_context;
// Then call the method in the activity.
}
Or write an interface onProfileViewClickListener such as view.onclickListener. then the ProfileActivity implements it and set it to the ProfileView.
What about if you assign an OnClickListener or OnTouchListener in your ProfileActivity Class and in this Listener you cann call the populate Method. In the OnTouchListener you can get the Position of the TouchEvent so you can assign it to a specific Profile.