I am using a ViewPager to show 9 fragments. In each of these fragments, I want to just show a different picture. I want to use one single fragment layout, but dynamically add in the picture. Also, would like add a "Continue" button on the last fragment that when pressed will go to another activity.
How do I go about making a fragment layout dynamic?
Main Activity
public class StoryboardPageActivity extends FragmentActivity {
// The number of pages (wizard steps) to show in this demo.
private static final int NUM_PAGES = 9;
// The pager widget, which handles animation and allows swiping horizontally to access previous and next wizard steps.
private ViewPager mPager;
// The pager adapter, which provides the pages to the view pager widget.
private PagerAdapter mPagerAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_storyboard_page);
// Instantiate a ViewPager and a PagerAdapter.
mPager = (ViewPager) findViewById(R.id.storyboardPager);
mPagerAdapter = new StoryboardPagerAdapter(getSupportFragmentManager());
mPager.setAdapter(mPagerAdapter);
}
#Override
public void onBackPressed() {
if (mPager.getCurrentItem() == 0) {
// If the user is currently looking at the first step, allow the system to handle the
// Back button. This calls finish() on this activity and pops the back stack.
super.onBackPressed();
} else {
// Otherwise, select the previous step.
mPager.setCurrentItem(mPager.getCurrentItem() - 1);
}
}
// A simple pager adapter that represents 5 fragment objects, in sequence.
private class StoryboardPagerAdapter extends FragmentStatePagerAdapter {
public StoryboardPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
return StoryboardFragment.newInstance(position);
}
#Override
public int getCount() {
return NUM_PAGES;
}
}
}
Fragment
public class StoryboardFragment extends Fragment {
private static final String KEY_POSITION = "position";
static StoryboardFragment newInstance(int position) {
StoryboardFragment frag = new StoryboardFragment();
Bundle args = new Bundle();
args.putInt(KEY_POSITION, position);
frag.setArguments(args);
return(frag);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.fragment_storyboard_page, container, false);
ImageView image = (ImageView)rootView.findViewById(R.id.imgStoryboard);
int position = getArguments().getInt(KEY_POSITION, -1);
int[] images = {R.drawable.storyboard1, R.drawable.storyboard2, R.drawable.storyboard3,
R.drawable.storyboard4, R.drawable.storyboard5, R.drawable.storyboard6,
R.drawable.storyboard7, R.drawable.storyboard8, R.drawable.storyboard9};
image.setImageResource(images[position]);
return rootView;
}
}
Fragment XML
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#fff" >
<ImageView
android:id="#+id/imgStoryboard"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:contentDescription="#string/storyboardSlide" />
</RelativeLayout>
How do I go about making a fragment layout dynamic?
The same way you make any other "layout dynamic". If you want to put an image in an ImageView, call setImageBitmap() or setImageDrawable() or whatever. For example, the PagerAdapter could supply the position to the fragment (via a factory method), and the fragment could then know what image to load.
This sample project demonstrates populating the hint of an EditText with a custom value based upon the page's position.
With respect to the "Continue" button, either have a separate fragment class for that (and appropriate smarts in your PagerAdapter, or always have the button in your layout, but set to android:visibility="gone" by default, toggling it via setVisibility(View.VISIBLE) for the fragment that needs it.
Related
I have 3 fragments (totally different from each other) and one activity (MainActivity). What I would like to do is to be able to swipe between them (with finger, not with buttons) with a transition like a TabLayout.
According to what I saw, I can do it using ViewPager. But the problem is that ViewPager uses TabLayout.
There is a way to swipe betweens fragments, using Viewpager, without TabLayout ?
This code will help you
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.view.ViewPager
android:id="#+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
Set up the child Fragments you would like to display. I made 3 child Fragments, calling them ChildFragment1, ChildFragment2, and ChildFragment3. Remember to have them extend support.v4.app.fragment. Now make layouts for all three of the Fragments. I call them child_fragment_1_layout, child_fragment_2_layout, and child_fragment_3_layout.
public class ChildFragment1 extends Fragment {
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View rootView = inflater.inflate(R.layout.child_fragment_1_layout, container, false);
Button buttonInFragment1 = rootView.findViewById(R.id.button_1);
buttonInFragment1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(getContext(), "button in fragment 1", Toast.LENGTH_SHORT).show();
}
});
return rootView;
}
}
Make an adapter for the ViewPager. You will have to extend either theFragmentPagerAdapter or the FragmentStatePagerAdapter. For this tutorial we will use the FragmentPagerAdapter . The difference between the two can be found here. After extending the FragmentPagerAdapter, you will need to call super(FragmentManager) in your constructor and implement the methods getItem(position) and getCount(). The getItem(position)method is used to return the fragment at the corresponding position, ordered from left to right. So ChildFragment1 would be at position 0, ChildFragment2 would be at position 1, and ChildFragment3 would be at position 2. The getCount() method is to count how many Fragments there are to display, and in this case, there are 3.
public class ViewPagerAdapter extends FragmentPagerAdapter {
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position)
{
case 0:
return new ChildFragment1(); //ChildFragment1 at position 0
case 1:
return new ChildFragment2(); //ChildFragment2 at position 1
case 2:
return new ChildFragment3(); //ChildFragment3 at position 2
}
return null; //does not happen
}
#Override
public int getCount() {
return 3; //three fragments
}
}
Now find your ViewPager in MainActivity and call the setAdapter() method and pass in your custom adapter. If you are doing this in another Fragment (Nested Fragments), you will have to pass in getChildFragmentManager() in the argument of your adapter instead. Now your ViewPager is all set
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewPager viewPager = findViewById(R.id.view_pager);
viewPager.setAdapter(new ViewPagerAdapter(getSupportFragmentManager()));
}
}
I am trying to add dot indicators to my view pager, I tried different types and none work, for some reason it doesn't appear on the fragment. It doesn't crash... Just doesn't appear.
I am trying to use this library
View pager XML file:
<LinearLayout android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android">
<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.pixelcan.inkpageindicator.InkPageIndicator
android:id="#+id/indicator"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:dotDiameter="8dp"
app:dotGap="8dp"
app:animationDuration="320"
app:pageIndicatorColor="#a3a0a0"
app:currentPageIndicatorColor="#000000" />
</android.support.v4.view.ViewPager>
</LinearLayout>
the fragment activity file:
public class HighScoreScreenSlide extends FragmentActivity {
/**
* The number of pages (wizard steps) to show in this demo.
*/
private static final int NUM_PAGES = 3;
/**
* The pager widget, which handles animation and allows swiping horizontally to access previous
* and next wizard steps.
*/
private ViewPager mPager;
private int countDownInd;
Bundle bundle;
/**
* The pager adapter, which provides the pages to the view pager widget.
*/
private PagerAdapter mPagerAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.high_score_view_pager);
countDownInd = getIntent().getIntExtra("gameType", 0);
// Instantiate a ViewPager and a PagerAdapter.
mPager = (ViewPager) findViewById(R.id.pager);
mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager());
mPager.setAdapter(mPagerAdapter);
mPager.setCurrentItem(countDownInd);
InkPageIndicator inkPageIndicator = (InkPageIndicator) findViewById(R.id.indicator);
inkPageIndicator.setViewPager(mPager);
}
#Override
public void onBackPressed() {
if (mPager.getCurrentItem() == 0) {
// If the user is currently looking at the first step, allow the system to handle the
// Back button. This calls finish() on this activity and pops the back stack.
super.onBackPressed();
} else {
// Otherwise, select the previous step.
mPager.setCurrentItem(mPager.getCurrentItem() - 1);
}
}
/**
* A simple pager adapter that represents 5 ScreenSlidePageFragment objects, in
* sequence.
*/
private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {
public ScreenSlidePagerAdapter( FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) { //use position
HighScoreFragment fragment = new HighScoreFragment();
bundle=new Bundle();
bundle.putInt("gameType",position);
fragment.setArguments(bundle);
return fragment;
}
#Override
public int getCount() {
return NUM_PAGES;
}
}
}
Also this library didn't work.
If there is more code needed to understand I'll be happy to provide it
Thanks!
Try to put InkPageIndicator view not inside ViewPager but on the same level with it, like shown in the sample. In this particular case, InkPageIndicator and ViewPager should be the children of LinearLayout. If you want indicator dots to be on top of the view pager, consider replacing LinearLayout with FrameLayout.
I have been trying to implement a ViewPager with different fragments.
And the problem is when i run the app, in the ViewPager, out of all the pages, only one page is visible and that page only gets changed when I slide over to the other pages in the ViewPager.
Take a look at my code,(although I checked it many times referring it with online resources).
This is what each of my fragments look like:
public class fragment1 extends Fragment {
/* Variable to store reference to the ACtivity */
Activity mCurrentActivity;
/* Variable storing reference to the ArrayList */
private ArrayList<Word> mDefaultWords;
/**
* THe empty public Constructor
*/
public fragment1(){
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
/** Getting reference to the Activity */
mCurrentActivity = getActivity();
// Populating the ArrayList here
// And later in the onActivityCreated callback I set an adapter on the ArrayList
return inflater.inflate(R.layout.activity_others, container, false);
}
#Override
public void onActivityCreated(Bundle savedStateInstance){
super .onActivityCreated(savedStateInstance);
/**
* Creating {#link ArrayAdapter} to link the {#link String}
* from {#link ArrayList} {#param
*/
MyAdapter adaptItems = new MyAdapter(mCurrentActivity, mDefaultWords);
// Getting the id of the ListView in numberActivity.xml
ListView myList = (ListView) mCurrentActivity.findViewById(R.id.theList);
//Chaning background color
myList.setBackgroundColor(ContextCompat.getColor(getContext(), android.R.color.holo_purple));
// Setting the adapter with the {#link ListView}
myList.setAdapter(adaptItems);
}
}
}
My Activity setting the adapter class extending FragmentPagerAdapter as a private inner class and setting the adapter on the ViewPager.
public class Main2Activity extends AppCompatActivity {
private ViewPager mViewPager;
private FragmentPagerAdapter mFragmentStatePagerAdapter;
private FragmentManager mFragmentManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
mFragmentManager = getSupportFragmentManager();
mViewPager = (ViewPager) findViewById(R.id.theViewPager);
mFragmentStatePagerAdapter = new MyFragmentStatePagerAdapter(mFragmentManager);
/* Setting the apdapter on the pager */
mViewPager.setAdapter(mFragmentStatePagerAdapter);
}
public class MyFragmentStatePagerAdapter extends FragmentPagerAdapter {
public MyFragmentStatePagerAdapter(FragmentManager fragmentManager){
super(fragmentManager);
}
#Override
public int getCount(){
return 4;
}
#Override
public Fragment getItem(int position) {
if (position == 0) {
return new fragment1();
} else if (position == 1){
return new fragment2();
} else if (position == 2) {
return new fragment3();
} else {
return new fragment4();
}
}
}
}
And here is the layout with the ViewPager
<android.support.v4.view.ViewPager
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/theViewPager"
android:visibility="visible" />
As I said, when I run the app only one page gets displayed, other pages are present in the ViewPager but they are blank and displays the default background color,
And the one page that is displayed is the one that gets changed when I swipe left or right in the ViewPager.
So what's the issue?
dont downvote the question, its a genuine problem.
So, I worked my way around, let me say how.
What happened is, I was working on a cloned project that had a old gradle version and sdktools version was also not updated and was quite old.
and the min API targetted was API 15
And I was testing my application on API 21.
So, what I did is I used a different layouts for each of my fragments.
That is for each fragment I created its own XML layout.
And that worked perfectly.
Odd problem, so I updated the gradle and sdktools, to avoid such weird problems.
I have two fragments, fragment_one (fragmentOne.class) and fragment_two (fragmentTwo.class). These fragments are being displayed inside ActivityMain.class.
When fragment_one is being displayed I want to set Image A as the background for ActivityMain.class.
When fragment_two is being displayed I want to set Image B as the background for ActivityMain.class
I can swap and set the background of ActivityMain.class when I am not using fragments (i use buttons as a test)....But, when I modify this for fragments I cannot get it to work.
Listed here you will see my ActivityMain.class
public class ActivityMain extends FragmentActivity {
//set variables for use of pageradapter and swipe screen
MyPageAdapter adapter;
ViewPager pager;
Context context = this;
LinearLayout swipeHomeScreen;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.content_activity_nav);
//Implement the adapater for the swipe screen on launch page and circle indicator
adapter = new MyPageAdapter(getSupportFragmentManager());
pager = (ViewPager) findViewById(R.id.pager);
pager.setAdapter(adapter);
swipeHomeScreen = (LinearLayout) findViewById(R.id.swipeHomeScreen);
}
}
Here I have listed the code of one of my fragments where I am trying to share/pass the set the background image of ActivityMain.class...
public class ActivityNavSwipeTwo extends Fragment {
ActivityMain main;
public void onAttach(Activity activity) {
main = (ActivityMain) activity;
};
public static ActivityNavSwipeTwo newInstance() {
ActivityNavSwipeTwo fragment = new ActivityNavSwipeTwo();
return fragment;
}
public ActivityNavSwipeTwo() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_two, null);
main.swipeHomeScreen.setBackgroundResource(R.drawable.Image2);
return root;
}
}
My activity inflates the fragments fine, but the background image does not change.
How could I implement this for target api 23??
Thanks for your support.
Implement viewpager.onpagechangedlistener in your activity. Then add view.setonpageselecterlistener(this) in oncreated method. You can control selected fragment in implemented on pageselected method
Definitely you have any parent layout(Relative/Linear) for your activity. So you have to do following:
Create id of parent layout if not created.
access from fragment and change the background color of that parent layout.
Write this in Fragment's onCreateView() method.
relativeLayout = (RelativeLayout)getActivity().findViewById(R.id.relativelayout);
relativeLayout.setBackground(background);
I want to add an introduction to my Android application, to inform the user about how the app works. This intro will be displayed only, if the preferred settings intro will be false. So in this intro, there will be 3 images and at the end, there will be a page, with some text and two buttons, to enable the user to access the application, by making a login. The change between each image, will be made with a swipe movement, (so right to left +, left to right -). How Can I do ?
This can be done via the use of Fragments and ViewPager and FragmentPagerAdapter. Look at this documentation:
FragmentPagerAdapter: http://developer.android.com/reference/android/support/v4/app/FragmentPagerAdapter.html
ViewPager:
http://developer.android.com/reference/android/support/v4/view/ViewPager.html
You can have one fragment that is instantiated based on the id in the ViewPager, and that id will indicate which image to show in your image fragment. So for three images, you instantiate a new fragment that sets the image in the fragment based on the current page in the FragmentPagerAdapter. The second fragment can be one for the login buttons and text you want at the end.
Ex for adapter defined in your FragmentActivity (or AppCompatActivity)
public class MyAdapter extends FragmentPagerAdapter {
public MyAdapter(FragmentManager fm) {
super(fm);
}
#Override
public int getCount() {
return NUM_ITEMS;
}
#Override
public Fragment getItem(int position) {
if(position < 3)
return ImageFragment.newInstance(position);
else
return new LoginFragment();
}
}
Ex for the image fragment for the various images in your introduction:
public static class ImageFragment extends Fragment{
private int mPosition;
public ImageFragment(){
}
public static ImageFragment newInstance(int pos){
ImageFragment frag = new ImageFragment();
Bundle args = new Bundle();
args.putInt("pos", pos);
frag.setArguments(args);
return frag;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPosition = getArguments().getInt("pos");
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_image, container, false);
ImageView backgroundView = (ImageView) v.findViewById(R.id.background_image);
switch(mPosition){
case 0:
//set background view image 1
case 1:
//set background view image 2
default:
//set background view image 3
}
return v;
}
}
I would recommend using a ViewPager. Check out this tutorial from the Developer Guide
http://developer.android.com/training/animation/screen-slide.html
If you want to add functionality to each of these pages instead of having just images then perhaps you can implement a fragmentStatePagerAdapter and then put all the functionality in each fragment. Here is a tutorial to implement one.
http://www.truiton.com/2013/05/android-fragmentstatepageradapter-example/
I think we can do it by using recycler view itself.
Using PagerSnapHelper layout manager in recycler view, we can implement swipe to change images.
recyclerView.setLayoutManager(new LinearLayoutManager(this,
LinearLayoutManager.HORIZONTAL, false));
// add pager behavior
PagerSnapHelper snapHelper = new PagerSnapHelper();
snapHelper.attachToRecyclerView(recyclerView);