Android Fragments make duplicate TextView on orientation change - android

I am trying to make a very simple App, but there's an error I can't get rid of it. Maybe someone can help me.
I'm making an Activity with an ActionBar and 3 Tabs. Beneath the Tabs is a FrameLayout, where I put Fragments with a TextView in it. So when clicking on a tab the content of the TextView shoud change.
This works fine until I change the orientation. After the change there is a duplicate TextView and I have no idea where it cames from. Here's a picture for better understanding:
Overlapping TextViews
Here's my Activity:
package com.test;
import android.app.ActionBar;
import android.app.Activity;
import android.app.FragmentTransaction;
import android.app.ActionBar.Tab;
import android.os.Bundle;
import android.widget.Toast;
public class ProblemActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ActionBar bar = getActionBar();
bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
String tab1 = "First Tab";
bar.addTab(bar
.newTab()
.setText(tab1)
.setTabListener(
new TabListener(new First())));
String tab2 = "Second Tab";
bar.addTab(bar
.newTab()
.setText(tab2)
.setTabListener(
new TabListener(new Second())));
String tab3 = "Third Tab";
bar.addTab(bar
.newTab()
.setText(tab3)
.setTabListener(
new TabListener(new Third())));
}
private class TabListener implements ActionBar.TabListener {
private MyFragment mFragment;
public TabListener(MyFragment fragment) {
this.mFragment = fragment;
}
public void onTabSelected(Tab tab, FragmentTransaction ft) {
ft.add(R.id.fragment_content, mFragment, null);
}
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
ft.remove(mFragment);
}
public void onTabReselected(Tab tab, FragmentTransaction ft) {
Toast.makeText(ProblemActivity.this, "Reselected!", Toast.LENGTH_SHORT)
.show();
}
}
}
The Fragment's:
public class First extends MyFragment {
public First() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View fragView = inflater.inflate(R.layout.tab1, container, false);
TextView tv = (TextView) fragView.findViewById(R.id.textView1);
tv.setText("First Tab");
return fragView;
}
}
main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<FrameLayout
android:id="#+id/fragment_content"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
and the content of the Fragment's.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/textView1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="TextView"
android:textSize="35dp" />
</LinearLayout>
It would be amazing if some could show me what I'm making wrong.
Thank's in advance!
Edit: I tried already this proposed solution but I would like to work with class Objects, so that I can use their Methods.
Edit2: Solved the problem now. It was sufficient to add android:configChanges="keyboardHidden|orientation|screenSize" to my Activity.

Since the OP already solved his problem, but hasn't been active on SO for almost a year, here is an answer containing the solution:
Adding the following to the Activity solved the problem:
android:configChanges="keyboardHidden|orientation|screenSize"

You can get overlapping views if there is something wrong with one of your layouts. This seems to happen in particular if you have a fragment. For example, a View in the Fragment can overlap a View in the containing layout.
Sometimes this can be fixed by Cleaning your project (if you are using Eclipse).

Related

Fragments won't change on Android application

Respected programmers of stack overflow,
I am very new to the world of programming and am actually trying to build an app to help my fellow medical students.
In my app I can't seem to be able to change fragments after pressing buttons on the navigation bar. Only a single fragment loads at first (home fragment) and the rest do not change at all.
Since I am new to the programming world it may just be a small mistake on my part, but I do hope you all can guide me.
Here is my MainActivity java file
public class MainActivity extends AppCompatActivity {
BottomNavigationView bnView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bnView=findViewById(R.id.bnView);
bnView.setOnItemSelectedListener(new NavigationBarView.OnItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
int id=item.getItemId();
if (id==R.id.home) {
loadfrag(new Homefragment(), true);
}else if(id==R.id.subject_based) {
loadfrag(new subjectfragment(), false);
}else if(id==R.id.about) {
loadfrag(new aboutfragment(), false);
}else if(id==R.id.exam) {
loadfrag(new examfragment(), false);
}else {
loadfrag(new paperfragment(), false);
}
return true;
}
});
bnView.setSelectedItemId(R.id.home);
}
public void loadfrag(Fragment fragment, boolean flag){
FragmentManager fm=getSupportFragmentManager();
FragmentTransaction ft= fm.beginTransaction();
if (flag)
ft.add(R.id.container,fragment);
else
ft.replace(R.id.container,fragment);
ft.commit();
}
}
My main activity xml file is as follows;
<?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:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="#color/goojasto"
tools:context="com.cringyprithak.mcqrunch_3.MainActivity">
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="?attr/actionBarSize"/>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bnView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="#EFD115"
app:menu="#menu/nav_items" />
</RelativeLayout>
My menu is as follows
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/subject_based"
android:icon="#drawable/ic_sub"
android:title="Subject-wise"/>
<item
android:id="#+id/paper"
android:icon="#drawable/ic_paper"
android:title="Paper-wise"/>
<item
android:id="#+id/home"
android:icon="#drawable/ic_home"
android:title="Home"/>
<item
android:id="#+id/exam"
android:icon="#drawable/ic_exam"
android:title="Exam Practice"/>
<item
android:id="#+id/about"
android:icon="#drawable/ic_action_name"
android:title="About Me"/>
</menu>
and an example of the coding in my fragments would be
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class aboutfragment extends Fragment {
View view;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view= inflater.inflate(R.layout.fragment_homefragment, container, false);
return view;
}
}
I have been trying all day to make a bottom navigation bar and have fragments switch according to the buttons in the navigation bar but I haven't been able to.
I've watched countless videos and tried anything I could find. Please help me.
Your code is fine in general. It is the proper way to switch between Fragment by using BottomNavigationBar.
Just a small change for following function. You can directly use replace() when switching between Fragment:
// Removed the boolean flag and use replace() directly
public void loadfrag(Fragment fragment) {
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
// Can remove the add() function and just use replace()
ft.replace(R.id.container, fragment);
ft.commit();
}
So I guess the problem you encounter is when you try to load the view to your Fragment.
For your aboutfragment, you are trying to load R.layout.fragment_homefragment. And from the naming seems that it is a HomeFragment layout rather than your aboutfragment layout. You should have a your aboutfragment layout there:
public class aboutfragment extends Fragment {
View view;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Should replace R.layout.fragment_homefragment with your aboutfragment layout
view = inflater.inflate(R.layout.fragment_homefragment, container, false);
return view;
}
}
And for better practice, please follow Java Naming Convention when you are creating functions or classes.
For example:
Homefragment should be in HomeFragment
aboutfragment should be in AboutFragment

How to pass data between tabs?

I have one activity and two tabs in that activity Tab1 and Tab2. These are the two fragments. In my Tab1 have an EditText field and a Button field and Tab2 have only one TextView Field.I want to get the value in EditText field in the Tab1 in to TextView field in Tab2 when I click the button in the Tab1 and also get value when swipe Tab1 to Tab2. I also check many websites but did't get any solution. If anyone know it please help me.
MainActivity.java
package reubro.com.fragment;
import android.support.design.widget.TabLayout;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.widget.EditText;
public class MainActivity extends AppCompatActivity implements TabLayout.OnTabSelectedListener {
TabLayout tabLayout;
ViewPager viewPager;
Tab1 t2;
EditText ed1;
Tab1 t1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
t1 = new Tab1();
ed1 = (EditText) findViewById(R.id.ed1);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
tabLayout = (TabLayout) findViewById(R.id.tab);
viewPager = (ViewPager) findViewById(R.id.pager);
tabLayout.addTab(tabLayout.newTab().setText("Tab1"));
tabLayout.addTab(tabLayout.newTab().setText("Tab2"));
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
Pager pager = new Pager(getSupportFragmentManager(),tabLayout.getTabCount());
viewPager.setAdapter(pager);
tabLayout.setOnTabSelectedListener(this);
}
public void onTabSelected(TabLayout.Tab tab){
viewPager.setCurrentItem(tab.getPosition());
// ed1.setText(t1.ed.getText());
// Log.d("cccccc",ed1.getText().toString());
}
public void onTabUnselected(TabLayout.Tab tab) {
}
public void onTabReselected(TabLayout.Tab tab) {
}
}
Tab1.java
package reubro.com.fragment;
import android.support.v4.app.Fragment;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
/**
* Created by pc84 on 20/1/17.
*/
public class Tab1 extends Fragment {
Button b1;
EditText ed;
String val;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup viewGroup, final Bundle bundle){
View view = inflater.inflate(R.layout.tab1,viewGroup,false);
b1 = (Button) view.findViewById(R.id.btn1);
ed = (EditText) view.findViewById(R.id.ed1);
b1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
val = ed.getText().toString().trim();
if(!(val.isEmpty())){
Log.d("inner",val);
Tab2 tab2 = new Tab2();
Bundle bundle = new Bundle();
bundle.putString("val",val);
tab2.setArguments(bundle);
Toast.makeText(getActivity(),"This is value: "+val,Toast.LENGTH_LONG).show();
}
}
});
return view;
}
}
Tab2.java
package reubro.com.fragment;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
/**
* Created by pc84 on 20/1/17.
*/
public class Tab2 extends Fragment {
TextView tv;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup viewGroup, Bundle bundle){
View view = inflater.inflate(R.layout.tab2,viewGroup,false);
tv = (TextView) view.findViewById(R.id.tv1);
Bundle bundle1 = this.getArguments();
if (bundle1 != null){
String val = bundle1.getString("val");
tv.setText(val);
Log.d("tttttt",val);
}
return view;
}
}
Pager.java
package reubro.com.fragment;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
/**
* Created by pc84 on 20/1/17.
*/
public class Pager extends FragmentStatePagerAdapter {
int tabCount;
public Pager(FragmentManager fm, int tabCount) {
super(fm);
this.tabCount = tabCount;
}
#Override
public Fragment getItem(int position) {
switch (position){
case 0:
Tab1 tab1 = new Tab1();
return tab1;
case 1:
Tab2 tab2 = new Tab2();
return tab2;
default:
return null;
}
}
#Override
public int getCount() {
return tabCount;
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"/>
<android.support.design.widget.TabLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/colorPrimary"
android:minHeight="?attr/actionBarSize"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
android:id="#+id/tab"
/>
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
</android.support.design.widget.CoordinatorLayout>
tab1.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/ed1"
android:hint="Enter something"
android:layout_margin="20dp"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:id="#+id/btn1"
android:layout_below="#+id/ed1"
android:text="Send to Next Fragment"
android:textAllCaps="false"/>
</RelativeLayout>
tab2.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/tv1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="Tab2"
android:gravity="center"/>
</RelativeLayout>
You can place your data into a Singleton referenced both into Tab1 and Tab2.
A Singleton is a programming pattern that let you to use always the same and the only one instance of a class.
This is an example:
public class ClassicSingleton {
private static ClassicSingleton instance = null;
protected ClassicSingleton() {
// Exists only to defeat instantiation.
}
public static ClassicSingleton getInstance() {
if(instance == null) {
instance = new ClassicSingleton();
}
return instance;
}
}
Take a look here to have a more detailed description:
Use ViewModel as a parent data sharing in the parent activity so you can use the same context as viewLifeCycleOwner so you can easily handle the data view and data
To pass data from one tab to another, you can either send a broadcast or if you don't want to broadcast then first pass it to activity through callback then from activity to tab2.
You try to use BroadcastReceiver.
In Tab1 : you send broadcast with data
In Tab2 : you get data from broadcast and set page index
You Can use Live Data object with View Model You can Implement it easily with new Android Architecture.
Doc : https://developer.android.com/topic/libraries/architecture/livedata
No need to EventBus Anymore and Interface for getting LiveData.
I've encountered a similar scenario and came up with the following:
Have the MainActivityViewModel hold any data you may need, and set
it accordingly when the event you are interested in is triggered.
You can then trigger the navigation to the destination tab
programmatically(even if you are using the multiple-stack workaround
used here
https://github.com/googlesamples/android-architecture-components/tree/master/NavigationAdvancedSample),
and have it get any information it may need from the
MainActivityViewModel.
As soon as the information is read, set it to null so it won't be
used again by mistake. You should also have a default behavior, for
when the tab comes up for other reasons, and that variable is null.
Honestly, I'm not sure if by doing this I've gone against some best practices or something, but it has proven useful, and doesn't feel too "hacky".
if your willing to wait until the tab is resumed:
it can be done like this: in your main activity navigation host have a function like this:
fun moveToTabPosition(tabPosition: Int, bundle: Bundle?) {
myFragment?.arguments?.let { it.putAll(bundle) } ?: run { myfragment?.arguments = bundle }
binding.tablayout.setSelectedTab(tabPosition)
binding.yourViewPager.currentItem = tabPosition
}
then just call that with your new bundle updates.
important: in onResume of each tab fragment have a function called updateBundle() and parse the arguments you want again.
the key here is the the arguments have a method called putAll
UPDATE: I want to avoid putAll now ...i notice after Android N it cannot allow to add values to the arguments after the fragment is attached. During QA testing it passed but some users had this issue so had to remove this call.
i got an error on some devices of: java.lang.UnsupportedOperationException : ArrayMap is immutable
Now im in favor of a common interface to call to update the set the arguments data. it would take a bundle as param.

Open Fragment From Activity

Im working on a small google maps app that lets users find places close to them, I want to add functionality that lets the user add a place to a list of favourites, So far ive created classes that may do the functionality.
My main activity is my home page which opens other activities, code below:
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ImageButton;
public class MainActivity extends AppCompatActivity {
ImageButton btnNearBy;
ImageButton btnFavourites;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnNearBy = (ImageButton) findViewById(R.id.btnNearby);
btnNearBy.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent mapIntent = new Intent(getBaseContext(), MapsActivity.class);
startActivity(mapIntent);
}
});
btnFavourites = (ImageButton) findViewById(R.id.btnFavourites);
btnFavourites.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FragmentManager fragmentManager = MainActivity.this.getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
FavouriteListFragment fragment = new FavouriteListFragment();
fragmentTransaction.add(R.id.fragment_container, fragment); //ERROR ON THIS LINE
fragmentTransaction.commit();
}
});
}
}
Ive created a button that should open up the fragment that holds the list of favourites ,My fragment is declared like this:
public class FavouriteListFragment extends Fragment { ... }
Im a little unsure how to open the fragment from the MainActivity when clicking a button.
Any ideas?
Thanks!
There are two ways of displaying fragments:
1- First you need to define a fragment container in your code like the following:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/main_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="do something"
android:onClick="openFragment" />
<FrameLayout
android:id="#+id/fragment_container"
android:layout_height="wrap_content"
android:layout_width="match_content" />
</LinearLayout>
and then you need to create a function called openFragment in your activity and use the following code in openFragment:
getSupportFragmentManager().beginTransaction().add(R.id_fragment_container,new FavouriteListFragment()).commit();
2- You can define the fragment in your activity xml file like:
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/my_fragment"
android:name="com.example.android.something.FavouriteListFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.android.something.FavouriteListFragment"
tools:layout="#android:layout/fragment_layout" />
The first one is called dynamic fragment creation and the second one is called static. You have more freedom with the first one but if your fragment doesn't change throughout the activity it is simpler to use the second one
Since you are using android.support.v4.app.Fragment and there has been a lot of confusion in importing correct version. Try like this:
android.support.v4.app.FragmentManager fragmentManager = MainActivity.this.getSupportFragmentManager();
android.support.v4.app.FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
FavouriteListFragment fragment = new FavouriteListFragment();
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.commit();
Where fragment_container is FrameLayout inside activity_main.
<FrameLayout
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
Reference

TextView doesn't show inside Fragment

I have a Fragment class, called from by FragmentTabHost, which does not display nothing.
This is my ArticulosFragment class:
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class ArticulosFragment extends Fragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d("App", "asdasdasd");
return inflater.inflate(R.layout.fragment_articulos, container, false);
}
}
I have a simple TextView in the XML file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Articulos"
android:textAppearance="?android:attr/textAppearanceLarge" />
</LinearLayout>
When I run the app, the log added shows correctly, but the text Articulos doesn't.
Edit: This is my TabHost class which displays (or should displays) the ArticulosFragment class:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tabHost = (FragmentTabHost) findViewById(android.R.id.tabhost);
tabHost.setup(this, getSupportFragmentManager(),
android.R.id.tabcontent);
inicializarTabs();
}
public void inicializarTabs() {
TabHost.TabSpec spec = tabHost.newTabSpec("Articulos");
spec.setContent(new TabContentFactory() {
#Override
public View createTabContent(String tag) {
// TODO Auto-generated method stub
return findViewById(R.id.realtabcontent);
}
});
spec.setIndicator("Articulos");
tabHost.addTab(spec, ArticulosFragment.class, null);
}
Two Things That Might Cause That:
Check If The Container coming is null for view
Check you Code For Fragment that show Fragment
Try Removing onCreate method from Fragment
TabContentFactory
Makes the content of a tab when it is selected. Use this if your tab
content needs to be created on demand, i.e. you are not showing an
existing view or starting an activity.
Please notice this line:
you are not showing an existing view or starting an activity.
public abstract View createTabContent (String tag)
Callback to make the tab contents
Parameters
tag Which tab was selected.
Returns
The view to display the contents of the selected tab.
So because you have a fragment and it is already have a view you do not need createTabContent and the interesting part is:
https://github.com/android/platform_frameworks_support/blob/master/v13/java/android/support/v13/app/FragmentTabHost.java#L219
as you see fragmentTabHost overwrites your TabContentFactory.
anyway your problem is:
tabHost.setup(this, getSupportFragmentManager(),android.R.id.tabcontent);
change it to:
tabHost.setup(this, getSupportFragmentManager(),R.id.realtabcontent);

Android ActionBarSherlock tabbed action bar with a mapview

I have 4 views, two of which contain mapviews. What I really want in the end is a tabbed navigation between these 4 views.
After some research, it seams like the best idea would be to use ActionBarSherlock and make each one of these views a "Fragment" inside a master "Main" Activity. This seams like a very easy to do thing but is causing me massive amounts of trouble (indeed, seams to be a pain for everyone from what I can find online).
First, my code.
ActivityMain.java
public class ActivityMain extends SherlockFragmentActivity
{
static String CLASS_NAME = "ActivityMain";
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
Log.v(CLASS_NAME, "here");
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
this.createMenu();
}
public void createMenu()
{
this.getSupportActionBar().setDisplayShowHomeEnabled(false);
this.getSupportActionBar().setDisplayShowTitleEnabled(false);
this.getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
Tab tab1 = getSupportActionBar()
.newTab()
.setText("First tab")
.setTabListener(new MyTabListener<FragmentOne>(this, FragmentOne.class));
getSupportActionBar().addTab(tab1);
Tab tab2 = getSupportActionBar()
.newTab()
.setText("Second tab")
.setTabListener(new MyTabListener<FragmentTwo>(this, FragmentTwo.class));
getSupportActionBar().addTab(tab2);
}
public class MyTabListener<T extends Fragment> implements TabListener
{
private ActivityMain mActivity;
private Fragment mFragment;
private Class<T> mClass;
public MyTabListener(ActivityMain activity, Class<T> fragmentClass)
{
mActivity = activity;
mClass = fragmentClass;
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft)
{
if (mFragment == null)
{
mFragment = Fragment.instantiate(mActivity, mClass.getName());
ft.add(android.R.id.content, mFragment, null);
}
else
{
//ft.setCustomAnimations(android.R.animator.fade_in, android.R.animator.animationtest);
ft.attach(mFragment);
}
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft)
{
if (mFragment != null)
{
ft.detach(mFragment);
}
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft)
{
}
}
}
FragmentOne loads just fine, no problems on that one. FragmentTwo is where the trouble begins. Here is the files:
FragmentTwo.java
package com.test;
import com.actionbarsherlock.app.SherlockFragment;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class FragmentTwo extends SherlockFragment
{
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
Log.v("Test", "Two!");
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View view = inflater.inflate(R.layout.two, container, false);
return view;
}
}
and the corresponding layout looks like this:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<com.google.android.maps.MapView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/mapMapView"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="0.40"
android:clickable="true"
android:apiKey="MY_KEY"
/>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
style="#android:style/ButtonBar"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<Button
android:id="#+id/refreshButton"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:onClick="refreshSightings"
android:text="#string/A_MAP_REFRESH_BUTTON" />
</LinearLayout>
</LinearLayout>
Now of course this is giving me the error Binary XML file line #7: Error inflating class com.google.android.maps.MapView
I have tried importing the https://github.com/petedoyle/android-support-v4-googlemaps package and replacing the already existing android-support-v4 package but when I try to run my app, it dies with the error that it can't find the ActivityMain class.
First question, am I even going about this in the right way? Should I be using this 1 main activity and loading all the other things in Fragments?
Next, if I am doing this in a correct way, is there a good tutorial for how to get this to work in a decent way? I can't find anything online except for other people asking the same questions and a few tutorials that haven't worked for me.
Basically, how can I have tabbed navigation with 2 maps in 2 different tabs?

Categories

Resources