ViewPager shows views on top of each other - android

I am trying to implement a ViewPager, but currently it renders all the views on one screen, and when moving to the next it is empty it contains all the content. I have a feeling it has to do with the Fragment within Fragment or so, but I cannot figure it out.
In the screenshot below you can kind of see it:
This is (part) of the code. (ArticlePagerAdapter is just an implementation of the proto to look up that specific object type).
public abstract class PrototypePagerActivity<T extends GenericModel> extends BaseActivity {
PrototypePagerAdapter mAdapter;
ViewPager mPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_proto_pager);
long categoryId = -1;
int articlePos = 0;
Bundle extras = getIntent().getExtras();
if (extras != null) {
//if (extras.containsKey("articleId")) articleId = extras.getInt("articleId");
if (extras.containsKey("position")) articlePos = extras.getInt("position");
if (extras.containsKey("categoryId")) categoryId = extras.getLong("categoryId");
}
mAdapter = new ArticlePagerAdapter(categoryId,getSupportFragmentManager());
mPager = (ViewPager) findViewById(R.id.protoPager);
mPager.setAdapter(mAdapter);
mPager.setCurrentItem(articlePos);
}
}
public abstract class PrototypePagerAdapter<T extends GenericModel> extends FragmentPagerAdapter {
#Override
public Fragment getItem(int position) {
try {
T object = getObjectForPosition(position);
ArticleFragment articleFragment = new ArticleFragment();
Bundle args = new Bundle();
args.putLong("articleId", object.getId());
articleFragment.setArguments(args);
return articleFragment;
} catch (Exception e) {
Log.w(iDomsAndroidApp.TAG, "Problem getting the object instance for pages", e);
return null;
}
}
public abstract T getObjectForPosition(int position) throws Exception;
#Override
public int getCount() {
return requestObjectCount();
}
public abstract int requestObjectCount();
}
public class ArticleFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_article, container, false);
if (savedInstanceState == null) {
getFragmentManager().beginTransaction()
.add(R.id.content_fragment, new PlaceholderFragment())
.commit();
}
ArticleHeaderFragment articleHeaderFragment = new ArticleHeaderFragment();
articleHeaderFragment.setArguments(getArguments());
getFragmentManager().beginTransaction().add(R.id.header_fragment, articleHeaderFragment).commit();
ArticleContentFragment articleContentFragment = ArticleContentFragment.newInstance();
articleContentFragment.setArguments(getArguments());
getFragmentManager().beginTransaction().add(R.id.content_fragment, articleContentFragment).commit();
return view;
}
}
activity_proto_pager.xml:
<?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="match_parent">
<android.support.v4.view.ViewPager
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/protoPager" />
</LinearLayout>
fragment_article.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ImageView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/imageView"
android:src="#drawable/background"
android:scaleType="centerCrop"
android:contentDescription="#string/background_image"
android:alpha="0.6" />
<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scrollbars="vertical">
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<FrameLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/audio_control_fragment" />
<FrameLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/header_fragment" />
<FrameLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/content_fragment" />
</LinearLayout>
</ScrollView>
</RelativeLayout>
fragment_article_header.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/list_background_overlay"
android:layout_centerInParent="true"
tools:context="org.idoms.iDomsAndroid.fragments.ArticleHeaderFragment">
<org.idoms.iDomsAndroid.views.ResizableImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxHeight="200dp"
android:id="#+id/article_imageView"
android:layout_gravity="center_horizontal"
android:scaleType="centerCrop" />
</LinearLayout>

You should replace fragment instead of add.
So, instead of .add(...) use .replace(....)
Update:
You are adding fragment at two more places. Do above step with articleHeaderFragment and articleContentFragment. You can add second part of code in else part (If it is according to your logic)
Update 2
You should revisit your logic as well. Like in the code, below, you are adding two fragment in R.id.content_fragment. Replace can help here, but your code will be redundant
if (savedInstanceState == null) {
getFragmentManager().beginTransaction()
.add(R.id.content_fragment, new PlaceholderFragment())
.commit();
}
ArticleContentFragment articleContentFragment = ArticleContentFragment.newInstance();
articleContentFragment.setArguments(getArguments());
getFragmentManager().beginTransaction().add(R.id.content_fragment, articleContentFragment).commit();

Related

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.

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();
}

AsyncTask is re-executing while switching between fragments

I have a MainActivity.class which extends from Activity . I created a tab like structure . on clicking any of the image . new fragment is displayed. My first fragment is Article. it has a AsyncTask associate with it.
when i go to another fragment and comeback to it .asyncTask call again. And the whole listView is recreated . I simply want to disable AsyncTask for calling again and save the previous state of the fragment.
I have addToBackStack(null); while adding fragments.
getFragmentManager().beginTransaction().replace(R.id.container, new Article()).addToBackStack(null).commit();
where Article is a fragment and container is the frameLayout in the mainActivity.xml
I want to show the fragment where i left off. Like we do in Activities by setting LaunchMode+"Single" or something . I am not clearing backStack.
I simply need to switch between Activities like we do in TabActivity. in TabActivity if we want to repeat the AsyncTask we have to specify it in onResume(). otherwise it will not called
Article Fragment
public class Article extends Fragment
{
ListView listView;
Activity context;
ArrayList<HashMap<String,String>> art_list;
ArticleAdapter adapter;
String url="http://tabletennisdaily.co.uk/webservices/view_articles.php";
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
View V = inflater.inflate(R.layout.article, container, false);
context = getActivity();
listView = (ListView) V.findViewById(R.id.art_listview);
new ArticleTask(getActivity(), url, listView).execute(url);
return V;
}
}
MainActivity
public class MainActivity extends Activity //implements FragmentDelegate,FragmentManager.OnBackStackChangedListener
{
public LinearLayout Tab1,Tab2,Tab3,Tab4;
public ImageView img1,img2,img3,img4;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.practicing);
init();
}
private void init()
{
Tab1 = (LinearLayout) findViewById(R.id.tab1);
Tab2 = (LinearLayout) findViewById(R.id.tab2);
Tab3 = (LinearLayout) findViewById(R.id.tab3);
Tab4 = (LinearLayout) findViewById(R.id.tab4);
img1 = (ImageView)findViewById(R.id.tab_img1);
img2 = (ImageView)findViewById(R.id.tab_img2);
img3 = (ImageView)findViewById(R.id.tab_img3);
img4 = (ImageView)findViewById(R.id.tab_img4);
getFragmentManager().beginTransaction().replace(R.id.container, new Article()).addToBackStack(null).commit();
}
public void selectFrag(View view) {
Fragment fr = null;
if (view == findViewById(R.id.tab1))
{
img1.setBackgroundResource(R.drawable.articles_on);
img2.setBackgroundResource(R.drawable.forum_off);
img3.setBackgroundResource(R.drawable.video_off);
img4.setBackgroundResource(R.drawable.profile_off);
fr = new Article();
}
else if(view == findViewById(R.id.tab2))
{
img1.setBackgroundResource(R.drawable.articles_off);
img2.setBackgroundResource(R.drawable.forum_on);
img3.setBackgroundResource(R.drawable.video_off);
img4.setBackgroundResource(R.drawable.profile_off);
fr = new Forum();
}
else if(view == findViewById(R.id.tab3))
{
img1.setBackgroundResource(R.drawable.articles_off);
img2.setBackgroundResource(R.drawable.forum_off);
img3.setBackgroundResource(R.drawable.video_on);
img4.setBackgroundResource(R.drawable.profile_off);
fr = new Medias();
}
else if(view == findViewById(R.id.tab4))
{
img1.setBackgroundResource(R.drawable.articles_off);
img2.setBackgroundResource(R.drawable.forum_off);
img3.setBackgroundResource(R.drawable.video_off);
img4.setBackgroundResource(R.drawable.profile_on);
fr = new Profile();
}
FragmentManager fm = getFragmentManager();
FragmentTransaction fragmentTransaction = fm.beginTransaction();
fragmentTransaction.replace(R.id.container, fr);
fragmentTransaction.addToBackStack(null);//MainActivity.TAG);//.addToBackStack(null);
fragmentTransaction.commit();
}
}
and practicing.xml is
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/mainlayout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#+id/bottom" />
<LinearLayout
android:id="#+id/bottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:baselineAligned="false"
android:layout_alignParentBottom="true"
android:orientation="horizontal" >
<LinearLayout
android:id="#+id/tab1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="1"
android:onClick="selectFrag"
android:gravity="center"
android:orientation="vertical" >
<ImageView
android:id="#+id/tab_img1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:background="#drawable/articles_on"
android:padding="10dp"
android:scaleType="center" />
</LinearLayout>
<LinearLayout
android:id="#+id/tab2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="1"
android:onClick="selectFrag"
android:gravity="center"
android:orientation="vertical" >
<ImageView
android:id="#+id/tab_img2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:background="#drawable/forum_off"
android:padding="10dp"
android:scaleType="center" />
</LinearLayout>
<LinearLayout
android:id="#+id/tab3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="1"
android:onClick="selectFrag"
android:gravity="center"
android:orientation="vertical" >
<ImageView
android:id="#+id/tab_img3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:background="#drawable/video_off"
android:padding="10dp"
android:scaleType="fitXY" />
</LinearLayout>
<LinearLayout
android:id="#+id/tab4"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="1"
android:onClick="selectFrag"
android:gravity="center"
android:orientation="vertical" >
<ImageView
android:id="#+id/tab_img4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:background="#drawable/profile_off"
android:padding="10dp"
android:scaleType="fitXY" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>
Try adding your fragment instead of replacing.
What addToBackStack() does is: it adds the fragment transaction to its stack, so it knows that when you press back, it should show your first fragment. So t does exactly that, and shows your first fragment again and the fragment's onCreatView() is called again. Here in your onCreateView, all initialization occurs and the AsyncTask is called. This is why it happens everytime you change between fragments.
The solution I implemented for this problem is:
1) Keep view of fragment as a class variable.
2) Perform all actions in onCreateView() only if the view is null.
So you should change:
public class Article extends Fragment
{
ListView listView;
Activity context;
ArrayList<HashMap<String,String>> art_list;
ArticleAdapter adapter;
String url="http://tabletennisdaily.co.uk/webservices/view_articles.php";
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
View V = inflater.inflate(R.layout.article, container, false);
context = getActivity();
listView = (ListView) V.findViewById(R.id.art_listview);
new ArticleTask(getActivity(), url, listView).execute(url);
return V;
}
}
to:
public class Article extends Fragment
{
ListView listView;
Activity context;
ArrayList<HashMap<String,String>> art_list;
ArticleAdapter adapter;
String url="http://tabletennisdaily.co.uk/webservices/view_articles.php";
View V; //SET THE FRAGMENTS VIEW AS A CLASS VARIABLE HERE
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{ //CHECK IF FRAGMENT IS INSTANTIATED BEFORE. IF IT IS NOT, CREATE NEW VIEW
if(V == null){
V = inflater.inflate(R.layout.article, container, false);
context = getActivity();
listView = (ListView) V.findViewById(R.id.art_listview);
new ArticleTask(getActivity(), url, listView).execute(url);
}
else{ //IF ALREADY INSTANTIATED USE SAME OLD V
((ViewGroup)V.getParent()).removeView(V);
}
return V;
}
}
Here, we move View V outside and make it a class variable. So if it is the first time the fragment is called, it is null and the initialization occurs, otherwise it goes to else black. Else block is required because onCreateView() adds whatever it returns as a child of the view's parent, so since V is already there, we remove it and onCreateView automatically adds it again.

Android: Fragment

When frButton is clicked FragmentOne should open and MainActivity should be hidden but Components of MainActivity is still accessible in FragmentOne, which is unwanted.
How to fix it?
code for MainActivity:
public void gofag1(View v) {
// TODO Auto-generated method stub
FragmentOne frag = new FragmentOne();
FragmentManager fm = getFragmentManager(); // import
FragmentTransaction ftr = fm.beginTransaction(); // import
ftr.add(R.id.mainlayout, frag, "keyFrag");
ftr.addToBackStack(null);
ftr.commit();
}
code for FragmentOne:
public class FragmentOne extends Fragment {
public FragmentOne() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.fragment_one, container,
false);
return v;
}
}
code for FragmentOne layout... R.layout.fragment_one
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
tools:context="com.megavb.le.FragmentOne" >
<!-- TODO: Update blank fragment layout -->
<TextView
android:id="#+id/tOnOff"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="22dp"
android:text="#string/a1" />
<ToggleButton
android:id="#+id/toggleButton1"
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:onClick="reedToggleValue"
android:text="ToggleButton"
android:textSize="30sp" />
code for MainActivity layout.... R.id.mainlayout
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/mainlayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:orientation="vertical" >
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:onClick="gofag1"
android:text="fOne" />
</RelativeLayout>
Please see the picture for better understanding...
So, you should be using ftr.replace instead of ftr.add
public void gofag1(View v) {
// TODO Auto-generated method stub
FragmentOne frag = new FragmentOne();
FragmentManager fm = getFragmentManager(); // import
FragmentTransaction ftr = fm.beginTransaction(); // import
//Notice the change here
ftr.replace(R.id.mainlayout, frag, "keyFrag");
ftr.addToBackStack(null);
ftr.commit();
}
Hope this helps!
EDIT: Well, without more information I'm going to take another stab at this.
In your mainlayout.xml you need to define a Fragment Container a simple method of doing this would be to use a layout file like the one that follows as a base for your Activity.
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/fragment_container">
</FrameLayout>
after defining this new fragment container you can programmatically add fragments to it by referencing it's ID.
The next step is to move your original MainActivty code into a new fragment!
This is the code for fragment_main
<?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">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="New Button"
android:id="#+id/button"
android:onClick="gofag1"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true" />
</RelativeLayout>
Here we create a new layout that simply contains a button.
Next we create the actual fragment
public class FragmentMain extends Fragment {
public FragmentMain() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.fragment_main, container,
false);
}
From here we can change our Main activity OnCreate code to
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mainlayout);
FragmentMain frag = new FragmentMain();
FragmentManager fm = getFragmentManager(); // import
FragmentTransaction ftr = fm.beginTransaction(); // import
ftr.add(R.id.fragment_container, frag, "keyFrag");
ftr.addToBackStack(null);
ftr.commit();
}

Must ViewPagers have a unique id within their Activity? (If they're backed by a FragmentStatePagerAdapter)

I have an activity with two ViewPagers both working with a FragmentStatePagerAdapter. But when the ViewPagers have no id, or both have the same id, they will not work correctly.
Activity layout (activity.xml):
<LinearLayout 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"
android:orientation="vertical"
tools:context="com.example.app.MainActivity">
<FrameLayout
android:id="#+id/frame1"
android:layout_width="match_parent"
android:layout_weight="1"
android:layout_height="0dp">
<include layout="#layout/merge_pager" />
</FrameLayout>
<FrameLayout
android:id="#+id/frame2"
android:layout_width="match_parent"
android:layout_weight="1"
android:layout_height="0dp">
<include layout="#layout/merge_pager" />
</FrameLayout>
</LinearLayout>
Merge layout (merge_pager.xml):
<merge xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.view.ViewPager
android:id="#+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</merge>
Activity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity);
FrameLayout frame1 = (FrameLayout) findViewById(R.id.frame1);
FrameLayout frame2 = (FrameLayout) findViewById(R.id.frame2);
ViewPager vp1 = (ViewPager) frame1.getChildAt(0);
ViewPager vp2 = (ViewPager) frame2.getChildAt(0);
if (vp1 == null | vp2 == null) {
throw new NullPointerException();
}
vp1.setAdapter(new ColorAdapter(getSupportFragmentManager()));
vp2.setAdapter(new ColorAdapter(getSupportFragmentManager()));
}
private class ColorAdapter extends FragmentStatePagerAdapter {
public ColorAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
}
#Override
public Fragment getItem(int i) {
return new ColorFragment();
}
#Override
public int getCount() {
return Integer.MAX_VALUE;
}
}
public static class ColorFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
TextView tv = new TextView(container.getContext());
Drawable d = new ColorDrawable(randomColor());
tv.setBackgroundDrawable(d);
return tv;
}
public static int randomColor() {
return Color.rgb(random255(), random255(), random255());
}
public static int random255() {
return
(int) (Math.random() * (double) 255);
}
Using this code, the second ViewPager won't work. I suspected it might be due to clashing ids (R.id.view_pager), so I removed the id from the merge file. However, this results in a fatal exception:
FATAL EXCEPTION: main
android.content.res.Resources$NotFoundException: Unable to find resource ID #0xffffffff
What is up with this?
It says in the docs:
When using FragmentPagerAdapter the host ViewPager must have a valid ID set.
So at least it's documented that the adapter won't work without an id for its pager. I suppose you can then take 'valid' to mean 'unique in the activity view hierarchy'.

Categories

Resources