Calas
Calas

Reputation: 73

How can I put a fragment inside of a tab?

In my Android Studio project I have a fragment that I created to display the profile page of a dating app. I also have a signUpActivity that is used in place of the mainActivity that leads to another activity called secondActivity. My fragment is called profileFragment. What I am trying to do is put the profileFragment into the first tab of my secondActivity. Right now when I run the project and create a valid dating profile I get the fragment in the background with the second activity with its tabs in the foreground. What is the easiest way to add my fragment to a tab with what I have right now? I attatched the code for the xml code and java code for the secondActivity and the profileFragment. I will also attatch a link to my github if it helps to answer my question:

https://github.com/alasali1/Form

Below is the code for my secondActivity:

package com.example.form;

import android.os.Bundle;

import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;
import com.google.android.material.tabs.TabLayout;

import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import androidx.viewpager.widget.ViewPager;
import androidx.appcompat.app.AppCompatActivity;

import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;

import com.example.form.ui.main.SectionsPagerAdapter;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;

public class SecondActivity extends AppCompatActivity {

private static final String TAG = SecondActivity.class.getSimpleName();
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_second);
    SectionsPagerAdapter sectionsPagerAdapter = new SectionsPagerAdapter(this, getSupportFragmentManager());
    ViewPager viewPager = findViewById(R.id.view_pager);
    viewPager.setAdapter(sectionsPagerAdapter);
    TabLayout tabs = findViewById(R.id.tabs);
    tabs.setupWithViewPager(viewPager);
    FloatingActionButton fab = findViewById(R.id.fab);

    //fragment
    ProfileFragment profileFragment = new ProfileFragment();
    FragmentManager manager = getSupportFragmentManager();
    FragmentTransaction transaction = manager.beginTransaction();
    transaction.add(R.id.fragment_profile, profileFragment, "profileFragment");
    transaction.commit();
    Log.i(TAG, "onCreate()");

    //Get the bundle
    Bundle bundle = getIntent().getExtras();
    String stringDate = bundle.getString("date");
    String stringName = bundle.getString("name");
    String stringJob = bundle.getString("job");
    String stringDescription = bundle.getString("description");
    //set arguments
    profileFragment.setArguments(bundle);

    fab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                    .setAction("Action", null).show();
        }
    });
}
//turn date string into date object
public static Calendar convertDate(String stringDate) throws ParseException {
    SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");

    Calendar date = Calendar.getInstance();
    date.setTime(sdf.parse(stringDate));
    return date;
}

public static boolean checkAge(Calendar date){
    Calendar today = Calendar.getInstance();
    int checkYear = today.get(Calendar.YEAR) -18;
    int yob = date.get(Calendar.YEAR);
    int mob = date.get(Calendar.MONTH);
    int dob = date.get(Calendar.DAY_OF_MONTH);
    if(date.after(today)){
        return false;
    }
    if(yob > checkYear){
        return false;
    } else if(mob > today.get(Calendar.MONTH)){
        return false;
    } else if(dob > today.get(Calendar.DAY_OF_MONTH)){
        return false;
    } else{
        return true;
    }

}


@Override
protected void onRestart() {
    super.onRestart();
    Log.i(TAG, "onRestart()");
}

@Override
protected void onStart() {
    super.onStart();
    Log.i(TAG, "onStart()");
}

@Override
protected void onResume() {
    super.onResume();
    Log.i(TAG, "onResume()");
}

@Override
protected void onPause() {
    super.onPause();
    Log.i(TAG, "onPause()");
}

@Override
protected void onStop() {
    super.onStop();
    Log.i(TAG, "onStop()");
}

@Override
protected void onDestroy() {
    super.onDestroy();
    Log.i(TAG, "onDestroy()");
}
}

While the java code for my fragment is :

package com.example.form;

import android.os.Bundle;

import androidx.fragment.app.Fragment;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import java.text.ParseException;
import java.util.Calendar;


public class ProfileFragment extends Fragment {
TextView textView, jobView, ageView, descriptionView;
ImageView imageView;

public ProfileFragment() {
    // Required empty public constructor
}



@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.fragment_profile, container, false);

    String stringDate = getArguments().getString("date");
    String stringName = getArguments().getString("name");
    String stringJob = getArguments().getString("job");
    String stringDescription = getArguments().getString("description");

    //make imageView
    imageView = v.findViewById(R.id.imageView);
    //make textview
    textView = v.findViewById(R.id.textView);
    //make job textview
    jobView = v.findViewById(R.id.job);
    //add input to jobView
    if(stringJob.equals("")){
        jobView.append("N/A");
    } else{
        jobView.setText(stringJob);
    }
    //make descriptionView
    descriptionView = v.findViewById(R.id.description);
    //add input to descriptionView
    descriptionView.append(" " +stringDescription);
    //make ageView
    ageView= v.findViewById(R.id.age);
    //make age variable
    int age = 0;
    //Get age
    try {
        Calendar birth = ConfirmActivity.convertDate(stringDate);
        Calendar today = Calendar.getInstance();
        if(today.get(Calendar.DAY_OF_YEAR) < birth.get(Calendar.DAY_OF_YEAR)){
            age= today.get(Calendar.YEAR) - birth.get(Calendar.YEAR) - 1;
        }
        else{
            age= today.get(Calendar.YEAR) - birth.get(Calendar.YEAR);
        }
    } catch (ParseException e) {
        e.printStackTrace();
    }
    //set age
    ageView.append(String.valueOf(age));
    //convert date
    try {
        Calendar date = ConfirmActivity.convertDate(stringDate);
        //compare date
        if(ConfirmActivity.checkAge(date)){
            textView.setText(" "+ stringName +" Thank you for signing up");
        }
        else{
            imageView.equals(null);
            textView.append(" Please try again when you're older");
            jobView.equals("");
            ageView.equals("");
        }
    } catch (ParseException e) {
        e.printStackTrace();
    }
    return v;


}
}

The XML for my second activity is :

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".SecondActivity">

<FrameLayout
    android:id="@+id/fragment_profile"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    />

<com.google.android.material.appbar.AppBarLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:theme="@style/Theme.Form.AppBarOverlay">


    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:minHeight="?actionBarSize"
        android:padding="@dimen/appbar_padding"
        android:text="@string/app_name"
        android:textAppearance="@style/TextAppearance.Widget.AppCompat.Toolbar.Title" />

    <com.google.android.material.tabs.TabLayout
        android:id="@+id/tabs"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="?attr/colorPrimary">

    </com.google.android.material.tabs.TabLayout>
</com.google.android.material.appbar.AppBarLayout>

<androidx.viewpager.widget.ViewPager
    android:id="@+id/view_pager"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior" />

<com.google.android.material.floatingactionbutton.FloatingActionButton
    android:id="@+id/fab"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="bottom|end"
    android:layout_margin="@dimen/fab_margin"
    app:srcCompat="@android:drawable/ic_dialog_email" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

While the xml for the fragment is :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ConfirmActivity"
android:orientation="vertical"
android:weightSum="4">



    <ImageView
    android:id="@+id/imageView"
    android:layout_width="203dp"
    android:layout_height="100dp"
    android:layout_gravity="center_horizontal"
    android:layout_weight="1"
    android:src="@drawable/blank_pic"
    />
    <TextView
    android:id="@+id/textView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/hi"
    android:layout_gravity="center_horizontal"
    />

    <TextView
    android:id="@+id/job"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/job"
    android:layout_gravity="center_horizontal"
    />

    <TextView
    android:id="@+id/age"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/age"
    android:layout_gravity="center_horizontal"
    android:layout_weight="1"
    />

    <TextView
    android:id="@+id/description"
    android:layout_height="wrap_content"
    android:layout_width="wrap_content"
    android:text="@string/description"
    android:layout_weight="1"
    />
 </LinearLayout>

Here is a screenshot indicating my problem. The fragment that Iwant to put into the tab is static in the background whereas the hello world string in the foreground is inside of the tabs so they change when I click on a new tab. I want to put my fragment inside of the first tab instead of it being in the background if that makes sense: enter image description here

enter image description here

Upvotes: 0

Views: 260

Answers (2)

Code-Apprentice
Code-Apprentice

Reputation: 83517

The problem is here:

    ProfileFragment profileFragment = new ProfileFragment();
    FragmentManager manager = getSupportFragmentManager();
    FragmentTransaction transaction = manager.beginTransaction();
    transaction.add(R.id.fragment_profile, profileFragment, "profileFragment");
    transaction.commit();

This code creates an instance of ProfileFragment and adds it directly to the activity. Instead, you should create fragments that belong in a tab in the SectionsPagerAdapter and use it to manage which fragment is shown according to which tab is selected.

Upvotes: 1

Dam
Dam

Reputation: 320

Hum, if i understood you want to use the view-pager to sweep the pages of each tab.

You don't need a "FrameLayout", because the Adapter of the ViewPager2 switch the fragment by giving the FragmentManager to the Adapter of the ViewPager2.

in the xml switch the ViewPager to ViewPager2.

<androidx.viewpager2.widget.ViewPager2
    android:id="@+id/view_pager"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

Create a new class that extends the FragmentStateAdapter, in this class you will be giving the number of the fragments that the ViewPager2 will be using to sweep between them.

public class FragmentAdapter_ViewPager extends FragmentStateAdapter {


    public FragmentStateAdapter_ViewPager(@NonNull FragmentManager fragmentManager, @NonNull Lifecycle lifecycle) {

        super(fragmentManager, lifecycle);

    }

    @NonNull
    @Override
    public Fragment createFragment(int position) {
        switch (position) {
            case 0://FIRST TAB
                return new Fragment_Two();
            case 1://SECOND TAB
                return new Fragment_Three();
            default:
                return new Profile_Fragment();

        }

        return null;
    }

    @Override
    public int getItemCount() {
        return 3;
    }
}

If you have more than one fragment to show in the tabs you can increment in the "createFragment()" method, just don't forget to say how many fragments will show in the method "getItemCount()".

Now in the SecoundActivity you can configure the new ViewPager2 with the Adapter and a new the LayoutMediator that synchronize them together.

//The Adapter of ViewPager2 that will switch the Fragments

viewPager2.setAdapter(new FragmentStateAdapter_ViewPager(getChildFragmentManager(), getLifecycle()));

//The LayoutMediator that will synchronize with the tabs

new TabLayoutMediator(tabLayout, viewPager2, new TabLayoutMediator.TabConfigurationStrategy() {
            @Override
            public void onConfigureTab(@NonNull TabLayout.Tab tab, int position) {
                tab.setText("TAB NAME"[position]);
            }
        }).attach();

Try to take a look int the GUIDE PAGE in: Create swipe views with tabs using ViewPager2

Upvotes: 1

Related Questions