Well , when I was trying to get a webView from a fragment in my activity,it doesn't works.My code below:
WebView webView;
webView = (WebView) getFragmentManager()
.findFragmentById(R.id.fragment_goods_details).getView()
.findViewById(R.id.goods_details);
Basically, this is a bad idea. Since a fragment has it own life-cycle.
In your activity, you can control your fragment to add it/replace it but you won't know exactly when your fragment is ready for manipulating.
Rather than that, you can have support from Event Bus or RxAndroid to dispatch event asyn to your Fragment from your activity. Within the fragment, then you can safely handle action/data/state of your webview
YourFragmentClass {
WebView webview;
public WebView getWebview(){ return webview;}
}
In your activtiy:
Fragment f = getFragmentManager().findFragmentById(xxxx);
if(f instanceOf YourFragmentClass) {
webView = (YourFragmentClass)f.getWebview();
}
Related
I have one Activity Called A. The activity has 1 Frame Layout in which Fragments are used. I have two Fragments, Fragment1 and Fragment2. When the Activity is launched, Fragment 1 fills the Frame Layout.
Fragment1 also contains a button that when clicked replaces it with Fragment2 within that same Frame Layout. My question is this, when I click that Button in Fragment1 should I implement that code so that
A) Activity A gets notified of the onClick in the Fragment through an interface using some type of Boolean value and then proceeds to replace it with Fragment2.
OR
B)Implement the code that replaces Fragment1 with Fragment2 within Fragment1 itself For example:
private FragmentTransaction ft;
private Button registerButton, resetButton;
private Fragment fragment;
public LoginFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_login, container, false);
registerButton = (Button)view.findViewById(R.id.register_button);
resetButton = (Button) view.findViewById(R.id.reset_button);
registerButton.setOnClickListener(this);
resetButton.setOnClickListener(this);
return view;
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.register_button: {
fragment = new RegisterFragment();
ft = getFragmentManager().beginTransaction();
ft.replace(R.id.content_frame, fragment);
ft.addToBackStack(null);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.commit();
break;
}
}
}
Could someone explain why one over the other? Thanks so much!
Generally, what I do is use an interface of some sort that lives in the fragment being replaced (in this case Fragment 1). Your parent activity then would implement this interface, and thus building a contract between the activities that are the parent of that particular fragment.
When you press your button (or whatever event happens to signal replace), you grab your activity casting it to that interface, and call the particular method.
e.g. Signaling event within the fragment
( (MyFragmentListener) getActivity()).onActionHappens();
Where MyFragmentListener is the inner class of your Fragment and onActionHappens() is the method that sends the signal. This effectively creates a contract between your fragment and any Activity that hosts the fragment. When your action happens, you let the activity know and the activity then overrides the appropriate method to handle the event.
There are other ways to do this, but at the simplest level this is how it can be done.
Why not option B
Option B creates a tight coupling between fragments, which you don't necessarily want. In practice you want the coupling to be between the fragment, and it's host (or parent) which is the Activity. Also, there could be many activities that use that fragment so you abstract away details about the particular activity that uses it by just calling getActivity(). In this case, coupling the fragment and the Activity is acceptable, since of course the two are coupled anyways. We know this because a fragment cannot live without an associated Activity, so it is okay to take advantage of the that tight coupling.
Summary
Pick option A. It is the cleanest route, and avoids assuming implementation details that you have to do in option B.
It is also the basic solution you have without any external libraries or details required. If you want a more advanced solution, checkout Otto (made by Square) Link to the library here
I'd like to know how to access a view (that is in an activity) from a fragment.
More specifically, a view starts in the activity and I want the same view to to end in the fragment. Thanks.
In Activity:
private View layoutProgress;
protected void onCreate(Bundle savedInstanceState){
layoutProgress = findViewById(R.id.layout_progress);
layoutProgress.setVisibility(View.GONE);
}
when the button is pressed:
fragment.getInstance().printScreen();(function in fragment)
layoutProgress.setVisibility(View.VISIBLE);
In Fragment:
Execute the code and i'd like to set layoutProgress visibility gone
In fragment:
Activity act = getActivity();
if (act == null) return;
View layoutProgress = findViewById(R.id.layout_progress);
But really, better design would be to call a method in your Activity that will hide the ProgressBar -- as to keep all interaction with that view in one place and not get entangled in all the states if you decide to do more stuff with that progress bar.
Read the guide on communication between Fragments for a proper (as in, future error-resistant) implementation of calling Activity's method from a Fragment.
make your progressview global in activity
and below to access progressview in fragment
((Youractivity) getActivity()).layoutProgress.setVisibility(View.GONE);
I'm working on an app that currently uses a content transition on an ImageView from one fragment to another on the same activity. It is working fine however I have realised that my destination fragment needs to have it's own activity.
So let's say i have Activity A which contains Fragment 1
And I have Activity B which contains Fragment 2.
I need to perform a shared element transition from Fragment 1 to Fragment 2.
Here is what i have done so far:
In the callback method from Fragment 1 to Activity A I'm passing the selected entity and also the imageview i want to transition from.
Activity A
#Override
public void OnPhotographSelected(Photograph selectedPhoto,ImageView image) {
Intent i= new Intent(this, PhotoDetailActivity.class);
i.putExtra("photo_OBJ", selectedPhoto);
i.putExtra("transitionName", image.getTransitionName());
startActivity(i, ActivityOptions.makeSceneTransitionAnimation(this, image, "mainPhoto").toBundle());
}
Activity B
#Override
protected void onCreate(Bundle savedInstanceState) {
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_photo_detail);
Photograph photoObj=new Photograph();
Bundle b = getIntent().getExtras();
String transitionName="";
if(b!=null)
{
photoObj=(Photograph)b.getSerializable("photo_OBJ");
transitionName=b.getString("transitionName");
}
PhotoDetailFragment pdf = PhotoDetailFragment.newInstance(photoObj);
pdf.setSharedElementReturnTransition(TransitionInflater.from(this).inflateTransition(R.transition.change_image_transform));
pdf.setSharedElementEnterTransition(TransitionInflater.from(this).inflateTransition(R.transition.change_image_transform));
pdf.setImageTransitionId(transitionName);
FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
trans.replace(R.id.photo_detail_content, pdf);
trans.commit();
}
Fragment 2
mainImg.setTransitionName(mImageTransitionID);
Activity Theme
<item name="android:windowActivityTransitions">true</item>
I'm not seeing any content transition occur at runtime. As i mentioned earlier I had this transition working correctly from fragment to fragment within the same activity.
Also worth noting is that Fragment 1 is a gridview so i have to maintain the transitionNames myself so they are all unique, that why you are seeing setTransitionName calls at runtime.
Any idea's why i'm not see the transition run?
Try to use postponeEnterTransition() in your second activity inside onCreate() and yourActivity.startPostponedEnterTransition() in your fragment after you created your view in onViewCreated().
If you're using AppCompat try supportPostponeEnterTransition() and supportStartPostponedEnterTransition() or ActivityCompat.postponeEnterTransition(yourActivity) and ActivityCompat.startPostponedEnterTransition(yourActivity).
Credits to:
http://www.androiddesignpatterns.com/2015/03/activity-postponed-shared-element-transitions-part3b.html
I have problem with sharedElementTransitions. I have one activity with fragment - from this fragment I start new activity with sharedElementTransitions, inside this activity I start fragment and inside this fragment is viewPager, now when I call setTransitionName in this fragment everything works very well, but when I move it to fragment that is inside my viewPager and call it inside onCreateView there is no smooth enter animation, back animation is working as intended. I was quite sure this might be resolved using postponeEnterTransition, so in my activity with fragment with viewPager I am calling postponeEnterTransition() and in my fragment getActivity().startPostponedEnterTransition() but it is still not working... Any ideas what might go wrong?
// Postpone the shared element enter transition in onCreate()
postponeEnterTransition();
// after the layout and data is ready, invoke startPostponedEnterTransition() to start the enter transition animation
// for example:
sharedElement.getViewTreeObserver().addOnPreDrawListener(
new ViewTreeObserver.OnPreDrawListener() {
#Override
public boolean onPreDraw() {
sharedElement.getViewTreeObserver().removeOnPreDrawListener(this);
startPostponedEnterTransition();
return true;
}
});
Please refer to : http://www.androiddesignpatterns.com/2015/03/activity-postponed-shared-element-transitions-part3b.html for more details
Hope it will be helpful!
i have extended a fragment named 'DetailFragment' from home activity.But i cannot access the functions of activity in fragment class,like animation,tablayout,and any other functions which i did in activity.But when i change fragment to fragment activity every error getting cleared,But i need fragment only.
Here is my code
public class DetailFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater,ViewGroup container, Bundle args) {
View view = inflater.inflate(R.layout.activity_detail, container, false);
getting error # 'loadanimation'
Animation animationFadeIn = AnimationUtils.loadAnimation(this,R.anim.fadein);
Animation animationFadeOut = AnimationUtils.loadAnimation(this,R.anim.fadeout);
getting error # 'onTouchEvent'
public boolean onTouchEvent(MotionEvent event) {
mGestureDetector.onTouchEvent(event);
return super.onTouchEvent(event);
return view;
}
}
i need to know that is it possible to work on fragment like we works on activity or is there any functions like 'getActivity' method to access activity class,and how i can implement it. that's enough. thank you in advance programmers..
Actually what you have to do is:
you have to replace all the "this" with "getActivity()"
In activity class pointing to "this" means pointing to the context of the activity.
But as your fragment is nothing but a part of the container of parent activity. In the fragment if you keep "this" it will point to the context of the fragment (not points to the parent activity). thats why you are getting error.
Your problem should be solved by:
Animation animationFadeIn = AnimationUtils.loadAnimation(getActivity(),R.anim.fadein);
Animation animationFadeOut = AnimationUtils.loadAnimation(getActivity(),R.anim.fadeout);
But i cannot access the functions of activity in fragment class,like animation,tablayout,and any other functions which i did in activity.
You can the activity method using getActivity() method
((MyActivityClassName)getActivity()).myPublicMethod();