Depth Pager Transformer just like SnapChat - android

I'm trying to implement ViewPager with DepthPageTransformer just like Snapchat application. In SnapChat application, there is a Camera screen which always comes in center of ViewPager and swiping from left or right brings other fragments on top of camera screen.
I've found code for DepthPageTransformer from this link. But the problem with this demo is that it brings all the next screen views from behind. Just like SnapChat I've a Camera screen in center and 2 screens coming on top from left and two screens coming on top from right on Camera screen.
So, how can I create a PageTransformer which brings fragments from left or right on the top of my center screen which is Camera?

I think you should provide 5 fragments in your FragmentPagerAdapter, the third (index=2) fragment will be fragment with camera view,
viewPager.setCurrentItem(2); //2 is index of camera fragment
Then your ViewPager.PageTransformer should look like this:
#Override
public void transformPage(View page, float position) {
int pageIndex = (int) page.getTag(); //im stroing pageIndex of fragment in its tag
if(pageIndex == 2) { //2 is index of camera fragment
float currentTranslation = - position * page.getWidth();
ViewCompat.setTranslationX(page, currentTranslation);
ViewCompat.setTranslationZ(page, -1);
return;
}
I am stroing pageIndex while fragment's view is created in its tag.
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
...
view.setTag(pageIndex);
return view;
}
Here is gif with results:
https://media.giphy.com/media/OIwmXdr3nukq4/giphy.gif
Fragment with food is the one you should replace with your camera fragment.

This is what they have done, if you don't get the concept shoot a comment.
Basically what they are doing is they have a MainActivity which is showing the camera and it is holding those three buttons in the bottom plus its holding viewpager that viewpager is holding three fragments
1.LeftFragment (Fragment on the left side).
2.CenterFragment (This fragment is transparent so when it comes in center the mainactivity content is visible which is camera).
3.RightFragment(Fragment on the right side).
Now Comes the coding part.
MainActivity.java.
public class MainActivity extends AppCompatActivity {
private ViewPager mViewPager;
#RequiresApi(api = Build.VERSION_CODES.KITKAT_WATCH)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mViewPager = (ViewPager) findViewById(R.id.view_pager);
mViewPager.setAdapter(new PagerAdapter(getSupportFragmentManager()));
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
//Here calculate the amount by which the pages are scrolled and animate your buttons accordingly.
}
#Override
public void onPageSelected(int position) {
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
}
class PagerAdapter extends FragmentStatePagerAdapter {
public PagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new LeftFragment();
case 1:
return new CenterFragment();
case 2:
return new RightFragment();
}
return null;
}
#Override
public int getCount() {
return 3;
}
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="Here is your camera."
android:textAppearance="?android:attr/textAppearanceLarge"/>
<android.support.v4.view.ViewPager
android:id="#+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:text="Button"/>
</RelativeLayout>
Then comes the fragments
LeftFragment.java
public class LeftFragment extends BaseController {
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_sheet2, container, false);
return rootView;
}
}
fragment_left.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="2dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FFA726"
android:orientation="vertical"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_gravity="center"
android:fontFamily="sans-serif"
android:text="Left"
android:textColor="#fff"
android:textSize="30sp"/>
</RelativeLayout>
</android.support.v7.widget.CardView>
RightFragment.java
public class RightFragment extends BaseController {
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_sheet1, container, false);
return rootView;
}
}
fragment_right.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="2dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FFA726"
android:orientation="vertical"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_gravity="center"
android:fontFamily="sans-serif"
android:text="Right"
android:textColor="#fff"
android:textSize="30sp"/>
</RelativeLayout>
</android.support.v7.widget.CardView>
I have left the animation part which I think you can achieve with little bit of calculation in viewpager OnPageChangeListener.
Happy Coding.

Related

Image Swipe Using View Pager inside Fragment

I am trying to create a swiping images inside fragment. I had created tabbed activity using view pager and this is working fine. In one of the tab I am trying to create Image swipe.
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view= inflater.inflate(R.layout.fragment_collection_fragment1, container, false);
ViewPager viewPager= (ViewPager)view.findViewById(R.id.collection1_viewPager);
ImageSwipeAdapter imageSwipeAdapter= new ImageSwipeAdapter(getActivity().getSupportFragmentManager());
viewPager.setAdapter(imageSwipeAdapter);
return view;
}
After deploying this the app stops working.
In some internet content it was mention to use
getChildFragmentManager()
but it was also not working. What is the issue with the code?
Adapter code for Image Swipe
public class ImageSwipeAdapter extends FragmentStatePagerAdapter {
public ImageSwipeAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
Fragment f= new ImageSwipe();
Bundle args= new Bundle();
args.putInt("count", position + 1);
f.setArguments(args);
return f;
}
#Override
public int getCount() {
return 3;
}
}
Fragment XML-
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com">
<android.support.v4.view.ViewPager
android:layout_width="match_parent"
android:layout_height="500dp"
android:id="#+id/collection1_viewPager">
</android.support.v4.view.ViewPager>
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginStart="160dp"
android:layout_marginTop="203dp"
android:text="TextView" />

Fragment inside ViewPager inside ViewGroup

Problem
As shown in the figure below, I have two tabs called "température" which are created in the same way (see mainFragment). In this two tabs, I have a viewpager to get previous graphics ( 05 august, 04 august,...).
The first tab works well but in the second, nothing appears. When debugging, I can see that the fragment is created in both cases. It's only on the second tab where the problem is. Even more, I can see the viewpager working when sliding to the left or right end.
I'm seeking since hours now and I don't understand where the problem is. Why the fragments don't appear ?
I'm using android.support.v13.app.FragmentStatePagerAdapter for the adapter.
Here is a short movie to show the problem :
https://www.dropbox.com/s/vf8qlrd75mdwijp/device-2017-08-06-214510.mp4?dl=0
Code
MainFragment
public class MainFragment extends Fragment implements BTListener {
// the different ID for the views.
private final static int ID_TEMPERATURE = 1;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.main,container,false);
final ViewGroup mainContainer = (ViewGroup) rootView.findViewById(R.id.main_container);
createTemperatureTab(mainContainer);
createTemperatureTab(mainContainer);
return rootView;
}
private void createTemperatureTab(ViewGroup mainContainer){
//inflate the view
ViewGroup view = (ViewGroup) LayoutInflater.from(getActivity()).inflate(R.layout.main_list,mainContainer,false);
((TextView)view.findViewById(R.id.title_main_list)).setText("Température");
((TextView)view.findViewById(R.id.information_main_list)).setText("°C");
final ExpandableLayout expandableLayout = (ExpandableLayout) view.findViewById(R.id.expandable_layout);
CustomPager viewPager = (CustomPager) view.findViewById(R.id.viewpager);
LinearGraphAdapter linearGraphAdapter = new LinearGraphAdapter(getChildFragmentManager());
viewPager.setAdapter(linearGraphAdapter);
viewPager.setCurrentItem(linearGraphAdapter.getCount());
expandableLayout.setExpanded(false);
expandableLayout.setDuration(500);
expandableLayout.setInterpolator(new DecelerateInterpolator());
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(expandableLayout.isExpanded()) {
expandableLayout.collapse();
}
else {
expandableLayout.expand();
}
}
});
mainContainer.addView(view);
}
}
main_list
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="#+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:src="#mipmap/ic_launcher" />
<TextView
android:id="#+id/title_main_list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="10dp"
android:textSize="20sp" />
<TextView
android:id="#+id/information_main_list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="80dp"
android:textSize="20sp" />
</LinearLayout>
<net.cachapa.expandablelayout.ExpandableLayout
android:id="#+id/expandable_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.example.renaud.aquariumslinding.adapter.CustomPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</com.example.renaud.aquariumslinding.adapter.CustomPager>
</net.cachapa.expandablelayout.ExpandableLayout>
</LinearLayout>
LineGraphFragment
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.linear_graph_layout,container,false);
lineChart = (LineChart) rootView.findViewById(R.id.linear_graph);
initiateChart(lineChart); // not important for this case
drawChart(lineChart,dayOfYear); // not important for this case
return rootView;
}
linear_graph_layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/linear_graph_date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:elevation="4dp"
android:textColor="#fff" />
<com.github.mikephil.charting.charts.LineChart
android:id="#+id/linear_graph"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
LinearGraphAdapter
public class LinearGraphAdapter extends FragmentStatePagerAdapter {
public static int MAXIMUM_COUNT_PAGER = 7;
private int mCurrentPosition = -1;
public LinearGraphAdapter(FragmentManager fragmentManager){
super(fragmentManager);
}
#Override
public Fragment getItem(int position) {
Bundle bundle = new Bundle();
bundle.putInt(Constant.CUSTOM_PAGER_NUMBER,MAXIMUM_COUNT_PAGER-position);
Fragment fragment = new LinearGraphFragment();
fragment.setArguments(bundle);
return fragment;
}
#Override
public int getCount() {
return MAXIMUM_COUNT_PAGER;
}
#Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
super.setPrimaryItem(container, position, object);
if (position != mCurrentPosition) {
Fragment fragment = (Fragment) object;
CustomPager pager = (CustomPager) container;
if (fragment != null && fragment.getView() != null) {
mCurrentPosition = position;
pager.measureCurrentView(fragment.getView());
}
}
}
}
Ok, after a night of research and reading the API I figured it out. I don't understand everything but it seems the v13 and v4 library have a conflict.
To override it, firstly :
Make sure that you called getChildFragmentManager() instead of getFragmentManager()
Create a different ID for all the different viewpageryou have. Those IDs must have at least 4 digits. Of course, it is better to have those in R.String
Set your ID in every viewpager by calling setID()
If it doesn't work, please clean and rebuild your project.
And finally, the reward :
I hope that it will help.

Viewpager with different menu and common toolbar not working

I have tabs in my app. Each tab is of different fragments and has different menu. Below is the layout which I am using
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/background">
<include
layout="#layout/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|enterAlways" />
</android.support.design.widget.AppBarLayout>
<com.CustomViewPager
android:id="#+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
<android.support.design.widget.TabLayout
android:id="#+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:background="#color/background"
app:layout_anchor="#id/view_pager"
app:layout_anchorGravity="bottom|center_horizontal"
app:layout_behavior="com.widget.ScrollTabBehavior"
app:tabBackground="#color/background"
app:tabIndicatorColor="#color/toolbar"
app:tabIndicatorHeight="0dp"
app:tabMode="fixed"
app:tabPaddingEnd="0dp"
app:tabPaddingStart="0dp" />
</android.support.design.widget.CoordinatorLayout>
<RelativeLayout
android:id="#+id/left_drawer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"
android:layout_marginLeft="-64dp"
android:layout_marginStart="-64dp"
android:background="#color/toolbar"
android:choiceMode="singleChoice"
android:divider="#android:color/transparent"
android:dividerHeight="0dp">
<ImageButton
android:id="#+id/close_btn"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:background="#android:color/transparent"
android:padding="5dp"
android:src="#drawable/close_icon" />
<view
android:id="#+id/drawerlist"
class="android.support.v7.widget.RecyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/close_btn" />
</RelativeLayout>
</android.support.v4.widget.DrawerLayout>
Now with every Fragment in onCreate() I have mentioned setHasOptionsMenu(true); further more. I have overriden the function onCreateOptionsMenu() in each fragment which has menu.clear(); at first then calling it's super constructor then inflating fragment's own menu xml. But result I am getting is something like this -
Suppose there are 5 tabs. 2nd and 3rd tab has viewpager within each consist of two more fragments within
1st tab has no menu
2nd tab has menu_2 (only for 2nd child fragment)
3rd tab again has no menu
4th tab has menu_4 (only for 1st child fragment)
5th tab has menu_5
Initially, there should be no menu for tab 1 which is ok. Then moving to 3rd tab directly it shows menu_4 which by default should show no menu. Then sliding to tab 4, it will show proper menu_4 then sliding back to 3rd tab it will show no menu (which is as required).
This same thing happens for tab 5. If I am switching to 2nd child fragment within 2nd tab then the same behavior is observed with 1st tab.
In short, according to my observation it is showing the menu of adjacent tabs which is actually getting executed after the current fragment and therefore such behavior is occurring.
So how to avoid this?
I have written small test-application to check the behaviour.
Let's go through the sample and see, if something wrong with your fragments (as you see above, ViewPager with different menus works like a charm)
Activity's XML:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.TabLayout
android:id="#+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<android.support.v4.view.ViewPager
android:id="#+id/viewPager"
android:layout_below="#+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
Activity class. Important part is invalidateOptionsMenu() every time ViewPager has PageSelected event. Then, we setting setHasOptionsMenu to all fragments and subfragments(from the nested ViewPagers) to false if they out of screen.
public class MainActivity extends AppCompatActivity {
PagerAdapter pagerAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Fragment[] fragments = {
Fragment.instantiate(this, FragmentNoMenu.class.getName()),
Fragment.instantiate(this, FragmentA.class.getName()),
Fragment.instantiate(this, FragmentNoMenu.class.getName()),
Fragment.instantiate(this, FragmentB.class.getName()),
};
TabLayout tabLayout = (TabLayout)findViewById(R.id.tabLayout);
ViewPager viewPager = (ViewPager)findViewById(R.id.viewPager);
pagerAdapter = new PagerAdapter(getSupportFragmentManager(), fragments);
viewPager.setAdapter(pagerAdapter);
viewPager.setOffscreenPageLimit(0);
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}
#Override
public void onPageSelected(int position) {
invalidateOptionsMenu(position);
}
#Override
public void onPageScrollStateChanged(int state) {}
});
invalidateOptionsMenu(0);
tabLayout.setupWithViewPager(viewPager);
}
private void invalidateOptionsMenu(int position) {
for(int i = 0; i < pagerAdapter.getCount(); i++) {
Fragment fragment = pagerAdapter.getItem(i);
fragment.setHasOptionsMenu(i == position);
if (fragment instanceof FragmentWithViewPager) {
FragmentWithViewPager fragmentWithViewPager = (FragmentWithViewPager)fragment;
if (fragmentWithViewPager.pagerAdapter != null) {
for (int j = 0; j < fragmentWithViewPager.pagerAdapter.getCount(); j++) {
fragmentWithViewPager.pagerAdapter.getItem(j).setHasOptionsMenu(i == position);
}
}
}
}
invalidateOptionsMenu();
}
}
PagerAdapter class:
public class PagerAdapter extends FragmentPagerAdapter {
private final Fragment[] fragments;
public PagerAdapter(FragmentManager fragmentManager, Fragment[] fragments) {
super(fragmentManager);
this.fragments = fragments;
}
#Override
public CharSequence getPageTitle(int position) {
return fragments[position].getClass().getSimpleName();
}
#Override
public Fragment getItem(int position) {
return fragments[position];
}
#Override
public int getCount() {
return fragments.length;
}
}
Here're my test fragments I used:
FragmentNoMenu class:
public class FragmentNoMenu extends android.support.v4.app.Fragment {
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_no_menu, container, false);
}
}
FragmentNoMenu layout:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:background="#0F0F50"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
FragmentA class is a Fragment with nested ViewPager:
public class FragmentA extends FragmentWithViewPager {
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_a, container, false);
Fragment[] fragments = {
Fragment.instantiate(getContext(), SubFragmentA.class.getName()),
Fragment.instantiate(getContext(), SubFragmentB.class.getName()),
Fragment.instantiate(getContext(), SubFragmentC.class.getName()),
};
if (pagerAdapter == null) {
pagerAdapter = new PagerAdapter(getChildFragmentManager(), fragments);
}
viewPager = (ViewPager)rootView.findViewById(R.id.viewPager);
viewPager.setAdapter(pagerAdapter);
return rootView;
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.fragment_a, menu);
super.onCreateOptionsMenu(menu, inflater);
}
}
FragmentA's layout:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:background="#B0B0B0"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.view.ViewPager
android:id="#+id/viewPager"
android:layout_marginTop="80dp"
android:layout_width="match_parent"
android:layout_height="200dp"/>
</FrameLayout>
FragmentA's menu:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/action_item_1"
android:title="Item 1"
android:orderInCategory="250"
app:showAsAction="never" />
<item
android:id="#+id/action_item_2"
android:title="Item 2"
android:orderInCategory="300"
app:showAsAction="never" />
</menu>
NB! FragmentA extends FragmentWithViewPager - it's a small extension of Fragment to make it easier to distinguish Fragments with nested fragments in MainActivity:
public class FragmentWithViewPager extends Fragment {
PagerAdapter pagerAdapter;
ViewPager viewPager;
}
FragmentB:
public class FragmentB extends Fragment {
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_b, container, false);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.fragment_b, menu);
super.onCreateOptionsMenu(menu, inflater);
}
}
It's layout & menu:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:background="#999999"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
.....
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/action_item3"
android:title="Item 3"
android:icon="#drawable/ic_triage_star"
android:orderInCategory="250"
app:showAsAction="always" />
</menu>
Subfragments (they are all look the same from the code perspective):
Layouts:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:background="#AA0000"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:text="SubFragment C (with icon Menu)"
android:textSize="24sp"
android:textColor="#00BB00"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
Code:
public class SubFragmentB extends Fragment {
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.subfragment_b, container, false);
}
}
That's it! I've uploaded the project to my dropbox - feel free to check it out!
I hope, it helps

Switching 2 fragments within one activity - Android

I'm trying to replace one fragment with another following a button click (onClick) event. I'm new to fragments so if I'm going about this the wrong way please let me know.
At run time a frame layout (container) is loaded. A fragment is then added to it dynamically. This works fine. If I add in the setOnClickListener I get a NullPointerException. Here's the Java:
public class WelcomeActivity extends ActionBarActivity {
FrameLayout container;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_welcome);
//setContentView(R.layout.welcome_fragment);
container = (FrameLayout)findViewById(R.id.mainContainer);
// Check that the activity is using the layout version with
// the fragment_container FrameLayout
if (findViewById(R.id.mainContainer) != null) {
// However, if we're being restored from a previous state,
// then we don't need to do anything and should return or else
// we could end up with overlapping fragments.
if (savedInstanceState != null) {
return;
}
addWelcomeFragment();
}
//NPE at the below line
Button submitUser = (Button) findViewById(R.id.submitUser);
submitUser.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View view){
addExpedFragment();
}
});
}
Through researching fragments I'm using static class within the WelcomeActivity class to load the fragments. They are here:
public static class WelcomeFragment extends Fragment {
public static Fragment newInstance(){
Fragment wFrag = new WelcomeFragment();
return wFrag;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View v = inflater.inflate(R.layout.welcome_fragment, null);
return v;
}
}
//-----------------------------------------------------------------------------------------------------//
public static class ExpedFragment extends Fragment {
public static Fragment secondInstance(){
Fragment eFrag = new ExpedFragment();
return eFrag;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View v = inflater.inflate(R.layout.exped_fragment, null);
return v;
}
}
And the methods to invoke these are also with WelcomeActivity here:
private void addWelcomeFragment(){
Fragment welcome = WelcomeFragment.newInstance();
FragmentTransaction fTrans = getSupportFragmentManager().beginTransaction();
fTrans.add(R.id.mainContainer, welcome);
fTrans.addToBackStack(null);
fTrans.commit();
}
private void addExpedFragment(){
Fragment exped = ExpedFragment.secondInstance();
getSupportFragmentManager().beginTransaction().replace(R.id.mainContainer, exped).commit();
}
I have a feeling that the problem is to do with trying to find the button view id "submitUser" from the first fragment. My xmls look like this.
The first empty FrameLayout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<FrameLayout
android:id="#+id/mainContainer"
android:layout_width="wrap_content"
android:layout_height="match_parent" >
</FrameLayout>
</RelativeLayout>
The first fragment loaded in at runtime:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/welcome_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="10dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
tools:context=".WelcomeActivity" >
<TextView
android:id="#+id/welcome"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/welcome1"
android:textAppearance="?android:attr/textAppearanceLarge" />
<EditText
android:id="#+id/userName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/welcome"
android:layout_alignRight="#+id/welcome"
android:layout_below="#+id/welcome"
android:layout_marginTop="32dp"
android:ems="10"
android:hint="#string/userHint"
android:inputType="textPersonName" >
<requestFocus />
</EditText>
<Button
android:id="#+id/submitUser"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/userName"
android:layout_alignRight="#+id/userName"
android:layout_below="#+id/userName"
android:layout_marginTop="16dp"
android:text="#string/Done" />
<FrameLayout
android:id="#+id/mainContainer"
android:layout_width="wrap_content"
android:layout_height="match_parent" >
</FrameLayout>
</RelativeLayout>
The second fragment to replace the first with the onClick event:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/exped_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="10dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
tools:context=".WelcomeActivity" >
<TextView
android:id="#+id/expedText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/exped"
android:textAppearance="?android:attr/textAppearanceLarge">
</TextView>
<FrameLayout
android:id="#+id/mainContainer"
android:layout_width="wrap_content"
android:layout_height="match_parent" >
</FrameLayout>
</RelativeLayout>
IF I forget loading the first fragment at runtime and setContentView(first fragment) there is no NullPointerException but the two fragments overlay each other when the button is pressed rather than replacing.
So my question is, how do I reference the active fragment to properly set the OnClickListener and avoid the NullPointerException?
Button submitUser = (Button) findViewById(R.id.submitUser);
gives the NPE
Problem:
Button submitUser = (Button) findViewById(R.id.submitUser);
The submitUser is located in your WelcomeFragment's layout not in your Activity's layout that is why it is null.
solution:
Instead of initializing it in your activity class you need to initialize it within your Welcome fragment view.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View v = inflater.inflate(R.layout.welcome_fragment, null);
Button submitUser = (Button) v.findViewById(R.id.submitUser);
submitUser.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View view){
addExpedFragment();
}
});
return v;
}
EDIT:
private void addExpedFragment(){
Fragment exped = ExpedFragment.secondInstance();
getActivity().getSupportFragmentManager().beginTransaction().replace(R.id.mainContainer, exped).commit();
}

Custom Adapter within a Nested Fragment

I have a ViewPager which holds multiple base fragments, each base fragment have four more nested fragments and each nested fragment is a combination of 5 imageViews and textView.
(This is what I intended to do)
I have created a sample application but I am not able to implement that properly. I cannot see any view in the nested fragment or the base fragment.
Here's the code for the sample application
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<fragment android:name="com.example.nestedfragments.BaseFragment"
android:id="#+id/left_fragment"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent"/>
</LinearLayout>
MainActivity.java
package com.example.nestedfragments;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
public class MainActivity extends FragmentActivity {
/**
* Called when the activity is first created.
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
base_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center">
<Button
android:id="#+id/button1"
android:text="Launch Nested Fragment"
android:gravity="center"
android:layout_alignParentBottom="true"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:paddingBottom="10dp"/>
</RelativeLayout>
BaseFragment.java
public class BaseFragment extends Fragment {
Button doNestingButton;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// set the view
View root = inflater.inflate(R.layout.base_fragment, container, false);
doNestingButton = (Button) root.findViewById(R.id.button1);
doNestingButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Fragment videoFragment = new NestedFragment();
// we get the 'childFragmentManager' for our transaction
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
// make the back button return to the main screen
// and supply the tag 'left' to the backstack
transaction.addToBackStack("left");
// add our new nested fragment
transaction.add(getId(), videoFragment, "left");
// commit the transaction
transaction.commit();
}
});
return root;
}
}
nested_fragment.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="154dp"
android:layout_height="154dp"
android:id="#+id/imageView" android:layout_gravity="left|center_vertical"
android:src="#drawable/ic_splash"/>
</LinearLayout>
NestedFragment.java
public class NestedFragment extends Fragment {
public NestedFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.nested_fragment, container, false);
ImageView doNestingButton = (ImageView) root.findViewById(R.id.imageView);
return root;
}
Once again this is a sample application, please guide me.
From your above code, you have not used the fragment container layout such as FrameLayout in base_fragment.xml .So add the frame layout for nested fragment inbase_fragment.xml

Categories

Resources