How to use shared element transition between FirstFragment (including RecyclerView) and SecondFragment - android

I could implement shared element transition between two fragments WITHOUT RECYCLERVIEW!!!
This is FirstFragment:
public class FirstFragment extends Fragment {
ImageView img_small;
LinearLayout layout_ofc_cities;
LinearLayout layout;
public FirstFragment() {
// Required empty public constructor
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_first, container, false);
img_small = (ImageView) view.findViewById(R.id.img_small);
layout_ofc_cities = (LinearLayout) view.findViewById(R.id.layout_ofc_cities);
layout = (LinearLayout) view.findViewById(R.id.layout);
layout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
setSharedElementReturnTransition(TransitionInflater.from(getActivity()).inflateTransition(R.transition.change_image_trans));
setExitTransition(TransitionInflater.from(getActivity()).inflateTransition(android.R.transition.fade));
SecondFragment secondFragment = new SecondFragment();
secondFragment.setSharedElementEnterTransition(TransitionInflater.from(getActivity()).inflateTransition(R.transition.change_image_trans));
secondFragment.setEnterTransition(TransitionInflater.from(getActivity()).inflateTransition(android.R.transition.fade));
FragmentTransaction ft = getFragmentManager().beginTransaction()
.replace(R.id.container, secondFragment)
.addToBackStack(null)
.addSharedElement(layout_ofc_cities, "transitionTxt")
.addSharedElement(img_small, "transitionImg");
ft.commit();
}
}
});
return view;
}
}
and this is SecondFragment:
public class SecondFragment extends Fragment {
public SecondFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_second, container, false);
return view;
}
}
And it works!
but when I implements a RecyclerView in FirstFragment to use SharedElementTransition for a LinearLayout and an ImageView of RecyclerView to a LinearLayout and an ImageView in SecondFragment it doesn't work.
I want a sample code with two Fragments that the first one has RecyclerView in it, with animation between their shared elements. Can anyone help me?

I found the answer:
the solution is on this page:
http://jemsdevmobile.com/2016/02/11/lollipop-transition-between-activities/
just you need to change xml tags. for example change "imageview" to "ImageView"

Related

How can I replace fragment inside a fragment?

I have an Activity with a ViewPager, each page of the ViewPager has a Fragment.
Inside my Screen3Fragment I have a LinearLayout (lly_fragments) where I am showing some other fragments. I start by showing the fragment Screen3_1
public class Screen3Fragment extends Fragment {
private FragmentManager manager;
private FragmentTransaction transaction;
public static Screen3Fragment newInstance() {
final Screen3Fragment mf = new Screen3Fragment();
return mf;
}
public Screen3Fragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_screen3, container, false);
Screen3_1Fragment frag31 = new Screen3_1Fragment();
manager = getChildFragmentManager();
transaction = manager.beginTransaction();
transaction.add(R.id.lly_fragments,frag31,"frag31");
transaction.addToBackStack("frag31");
transaction.commit();
return v;
}
}
This works fine without problems. Problem comes when, from within frag31 (which is inside Screen3Fragment), I want to call fragt32, for that I do the following.
public class Screen3_1Fragment extends Fragment {
private ImageButton imgbt_timer;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_screen3_1,container,false);
imgbt_timer = (ImageButton) v.findViewById(R.id.bT_scr31_timer);
imgbt_timer.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getChildFragmentManager().beginTransaction()
.replace(R.id.lly_fragments, new Screen3_2Fragment(), "frag32")
.commit();
}
});
return v;
}
}
As I read in other answers, the line transaction.replaceshould do the trick and replace the existing frag31 by the given frag32 inside the same given container lly_fragments.
However, I get java.lang.IllegalArgumentException: No view found for id..... I am not sure why.
getFragmentManager() will return always attributes from parent, in most cases the activities. getChildFragmentManager() wil return parent attributes (in your case, Screen3Fragment attributes). It should be used when you add a fragment inside a fragment.
In your case, Screen3Fragment should be added using getFragmentManager() and Screen3_1Fragment should be added using getChildFragmentManager() because Screen3_1Fragment is Screen3Fragment child. Screen3Fragment is the parent.
I recomand you to use always getFragmentManager() with add method, not replace because your parent will be the same.
getChildFragmentManager() can be used when you add a ViewPager inside a fragment.
You can use the callback, as following :
that worked for me, I hope my answers helps you
1) create a interface
public interface ChangeFragmentListener {
void onChangeFragmentLicked(int fragment);
}
2) implement the interface and transaction methods in your activity:
public class MainActivity extends AppCompatActivity implements ChangeFragmentListener {
FragmentTransaction fragmentTransaction;
Fragment1 fragment1;
Fragment2 fragment2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
fragment1 = new Fragment1();
fragment1.setChangeFragmentListener(this);
fragment2 = new Fragment2();
fragment2.setChangeFragmentListener(this);
initListeners();
}
void changeToFrag1() {
fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.activity_main_fragment_container,fragment1, "");
fragmentTransaction.commit();
}
void changeToFrag2() {
fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.activity_main_fragment_container, fragment2, "");
fragmentTransaction.commit();
}
#Override
public void onChangeFragmentLicked(int fragment) {
switch (fragment){
case 1:
changeToFrag1();
break;
case 2:
changeToFrag2();
break;
}
}
3) Create object from the interface to handle the callback:
public class Fragment1 extends Fragment {
private ChangeFragmentListener changeFragmentListener;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_fragment1, container, false);
view.findViewById(R.id.fragment1_textView).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
changeFragmentListener.onChangeFragmentLicked(2);
}
});
return view;
}
public Fragment1 setChangeFragmentListener(ChangeFragmentListener changeFragmentListener) {
this.changeFragmentListener = changeFragmentListener;
return this;
}
}

Android Fragment Null pointer exception

I am learning android developing(novice).I want to add a fragment to the mainActivity with a textview and change the text. This code works perfectly:
public class Fragment1 extends Fragment {
//#Nullable
//#Override
TextView textt;
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_fragment1, container, false);
((TextView)view.findViewById(R.id.textview)).setText("some text");
return view;
}
}
But this codes invokes null pointer exception:
public class Fragment1 extends Fragment {
//#Nullable
//#Override
TextView textt;
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_fragment1, container, false);
textt = (TextView)view.findViewById(R.id.textview);
return view;
}
public void updateText() {
textt.setText("some text");
}
}
and:
public class Fragment1 extends Fragment {
//#Nullable
//#Override
View view;
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_fragment1, container, false);
return view;
}
public void updateText() {
((TextView)view.findViewById(R.id.textview)).setText("some text");
}
}
MainActivity:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
Fragment1 frg1 = new Fragment1();
ft.replace(R.id.fragment_container, frg1);
ft.addToBackStack(null);
ft.commit();
frg1.updateText();
}
}
why these codes providing different outcome?
my project
frg1.updateText(); is called before the onCreateView lifecycle method of your fragment is called.. You should call the method after you set
textt = (TextView)view.findViewById(R.id.textview);
View view = inflater.inflate(R.layout.fragment_fragment1, container, false);
textt = (TextView)view.findViewById(R.id.textview);
this.updateText();//here
return view;
Check out fragment lifecycle docs regarding onCreateView
The system calls this when it's time for the fragment to draw its user interface for the first time.
This will happen when fragment is loaded not when it is created in your activity.
Here, the textview is not created when you call the updateText function.
Do such calls inside your fragment. Not on the activity which houses the fragment.

Change fragment and navigation drawer state from fragment class

I created an application with navigation drawer using this tutorial: http://www.androidhive.info/2013/11/android-sliding-menu-using-navigation-drawer/
And I have a button on the first fragment. So, I want to change fragment by clicking the button. This code can change fragment but not change navigation draver state (title, selected item):
public class FirstFragment extends Fragment {
public FirstFragment(){}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_today, container, false);
return rootView;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
ImageButton addButton = (ImageButton) getView().findViewById(R.id.add_button);
addButton.setOnClickListener(new addNewListener());
super.onActivityCreated(savedInstanceState);
}
private class addNewListener implements View.OnClickListener {
#Override
public void onClick(View v) {
final FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.frame_container, new NewFragment(), "NewFragmentTag");
ft.commit();
}
}
}
How can I fix it?
Thanks a lot!

how to switch between two fragments by clicking on one of them?

suppose we have two fragments Frag1 and Frag2, now my question is how to switch between them by clicking on one of them using "FragmentTransaction Replace"
this is my codes:
public class Frags extends Fragment{
private boolean mShowingBack = false;
CardFrontFragment fr=new CardFrontFragment();
CardBackFragment bk=new CardBackFragment();
static View view;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (!mShowingBack)
{
return fr.onCreateView(inflater, container, savedInstanceState);
}
else
{
return bk.onCreateView(inflater, container, savedInstanceState);
}
}
public static class CardFrontFragment extends Fragment {
public CardFrontFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view=inflater.inflate(R.layout.fragment_card_front, container, false);
view.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View arg0) {
}
});
return view;
}
}
public static class CardBackFragment extends Fragment {
public CardBackFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view= inflater.inflate(R.layout.fragment_card_back, container, false);
view.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View arg0) {
}
});
return view;
}
}
public void flipCard() {
if (mShowingBack) {
getChildFragmentManager().popBackStack();
mShowingBack = !true;
return;
}
mShowingBack = true;
getChildFragmentManager()
.beginTransaction()
.setCustomAnimations(
R.animator.card_flip_right_in, R.animator.card_flip_right_out,
R.animator.card_flip_right_in, R.animator.card_flip_right_out)
.replace(R.id.container, this.bk)
.addToBackStack(null)
.commit();
}
and the problem: container can not be found
logcat: No View found for id 0x7f600054(id/container)
so where i am wrong?
is there any better way to do this?
It usually means that you have not define fragment with id container in your layout file.
In fragment layout
<LinearLayout
android:layout_width = "fill_parent"
android:layout_height = "fill_parent">
<FrameLayout
android:id="#+id/container" <!-- this part is missing that is why view cannot find -->
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
Also it seems like you did not inflate your layout in fragment onCreateView. This may also cause problem as system may not not which view it wants to create.

Dynamically add elements to fragment

Hi I'm new to android and was trying to dynamically add content to a Fragment.
I've two Fragments inside an Activity. The first point to the second like this:
public static class PlaceholderFragment extends Fragment {
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_welcome,
container, false);
Button searchActivityBtn = (Button) rootView.findViewById(R.id.SearchActivityBtn);
searchActivityBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d("##SecondActivity", "search btn click");
getFragmentManager().beginTransaction()
.replace(R.id.welcome_fragment, new searchAnnouncementsFragment()).addToBackStack(null).commit();
}
});
return rootView;
}
}
the second Fragment class is
public static class searchAnnouncementsFragment extends Fragment {
public searchAnnouncementsFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_search,
container, false);
return rootView;
}
//public void onStart(){
// super.onStart();
// RelativeLayout root = (RelativeLayout) getActivity().findViewById(R.id.annunciContainer);
// Log.d("##onstart", "root:" + (root == null));
//}
}
As you can see i tried to do something in onStart method but I've always a bunch of errors, the R.id.annunciContainer is the id of the fragment_search.xml layout
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id ="#+id/annunciContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/white" >
What I'm trying to achieve is to dynamically add elements like other FrameLayout to my Fragment ( represented by the above RelativeLayout ).
Any thought?
You didn't mention the name of the activity, lets say the name as Activity1,
First create a linear layout or frame layout in the Activity1
Second add the following lines of code to your Activity1 for inflating PlaceholderFragment into your layout in Activity1
PlaceholderFragment pf = new PlaceholderFragment();
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.annunciContainer, pf,"place_holder");
ft.commit();
For inflating searchAnnouncementsFragment replace PlaceholderFragment with searchAnnouncementsFragment.
What I was searching for are ListView

Categories

Resources