I'm trying to migrated from Android SDK to Google Play Services for Admob. I'm having problems with adding in the java code on the fragment side.
It's an Activity that uses fragments as Tabs to navigate between XML layouts. In the past I was able to add all the admob information directly in the XML layout. Google Services requires you to have it linked on the java side.
It keeps on crashing, and I can't figure how to handle the AdView with the fragements. I was looking at adding it into the Main.java but unsure how TabListener will handle the AdView.
I need some help on this one.
I already done the following items:
1. Add Google Play services library into my project
2. I declared all permission in the manifest
<activity android:name="com.google.android.gms.ads.AdActivity" android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScr eenSize" />
<meta-data android:name="com.google.android.gms.version" android:value="#integer/google_play_services_version" />
I have a Main.java and TabListener to switch between the fragments but can't figure out how to link the Adview xml to the Fragments.
It can't see the views in the fragment, and it doesn't work in the Main.java.
AdView adView = (AdView)this.findViewById(R.id.adView);
AdRequest adRequest = new AdRequest.Builder().build();
adView.loadAd(adRequest)
Main.java is my main.
public class Main extends Activity {
// Declare Tab Variable
ActionBar.Tab Tab1, Tab2, Tab3;
Fragment fragmentTab1 = new FragmentTab1();
Fragment fragmentTab2 = new FragmentTab2();
Fragment fragmentTab3 = new FragmentTab3();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ActionBar actionBar = getActionBar();
// Hide Actionbar Icon
// Set to False, we are not using icons
actionBar.setDisplayShowHomeEnabled(false);
// Hide Actionbar Title
// Set to False, used up too much space on phones
actionBar.setDisplayShowTitleEnabled(false);
// Create Actionbar Tabs
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Set Tab Icon and Titles
// Titles are as follows below
Tab1 = actionBar.newTab().setText("Tab 1");
Tab2 = actionBar.newTab().setText("Tab 2");
Tab3 = actionBar.newTab().setText("Tab 3);
// Set Tab Listeners
Tab1.setTabListener(new TabListener(fragmentTab1));
Tab2.setTabListener(new TabListener(fragmentTab2));
Tab3.setTabListener(new TabListener(fragmentTab3));
// Add tabs to actionbar
actionBar.addTab(Tab1);
actionBar.addTab(Tab2);
actionBar.addTab(Tab3);
}
}
TabListener.java for switching between fragments.
public class TabListener implements ActionBar.TabListener {
Fragment fragment;
public TabListener(Fragment fragment) {
// TODO Auto-generated constructor stub
this.fragment = fragment;
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
ft.replace(R.id.fragment_container, fragment);
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
ft.remove(fragment);
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
}
}
My XML fragmentTab1 for example.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/LinearLayout1"
android:orientation="vertical"
android:background="#drawable/background1"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<com.google.android.gms.ads.AdView
xmlns:ads="http://schemas.android.com/apk/res-auto"
android:id="#+id/adView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
ads:adUnitId="#string/admob_string"
android:gravity="bottom"
ads:adSize="BANNER"/>
</LinearLayout>
Your AdView code needs to go in your Fragment.java class not your Main.java class. Also, a standard convention would be to name "Main" MainActivity.java rather than Main.java.
Related
I followed how to create tabs in the Action Bar using Fragments in Android from this site. While the tabs turned out fine, the TextView that's supposed to appear in the middle of the Fragments is nowhere to be seen. I've looked at other StackOverflow questions that relate to this but none solved my problem.
FragmentTab1.java:
public class FragmentTab1 extends Fragment {
final String TAG = "FRAGMENT_TAB_1";
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.tab, container, false);
TextView textview = (TextView) view.findViewById(R.id.txtvwTab);
textview.setText("one");
Log.i(TAG, "textview's text: " + textview.getText());
return view;
}
}
The strangest thing about this is that, while the TextView is not visible, when I look at the LogCat, it still says "textview's text: one". Clearly, the TextView is still getting created. There are no error messages at all.
tab.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="#+id/txtvwTab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true" //added later
android:textColor="#color/Black" //added later
android:textSize="40sp" //added later
android:alpha="1" //added later
android:text="DEFAULT" //added later
/>
</RelativeLayout>
In the original code, I couldn't see the "one" displayed, so I tried editing the XML file. I tried changing where it's displayed. I tried specifying its color, its text size, its alpha, and even its default text. Nothing worked!
So what am I still missing? Why is the TextView clearly present and is getting its text set while not actually being visible?
EDIT (more code):
Main.java:
public class Main extends Activity {
ActionBar.Tab tab1, tab2, tab3;
Fragment fragmentTab1 = new FragmentTab1();
Fragment fragmentTab2 = new FragmentTab2();
Fragment fragmentTab3 = new FragmentTab3();
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Remove status bar
View decorView = getWindow().getDecorView();
// Hide the status bar.
int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN;
decorView.setSystemUiVisibility(uiOptions);
setContentView(R.layout.activity_main);
ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
tab1 = actionBar.newTab().setText("1");
tab2 = actionBar.newTab().setText("2");
tab3 = actionBar.newTab().setText("3");
tab1.setTabListener(new TabListener(fragmentTab1));
tab2.setTabListener(new TabListener(fragmentTab2));
tab3.setTabListener(new TabListener(fragmentTab3));
actionBar.addTab(tab1);
actionBar.addTab(tab2);
actionBar.addTab(tab3);
}
activity_main.xml:
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.novoloc.upup2.Main" />
TabListener.java:
public class TabListener implements ActionBar.TabListener {
Fragment fragment;
public TabListener(Fragment fragment) {
this.fragment = fragment;
}
public void onTabSelected(Tab tab, FragmentTransaction ft) {
ft.replace(R.id.fragment_container, fragment);
}
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
ft.remove(fragment);
}
public void onTabReselected(Tab tab, FragmentTransaction ft) {
// nothing done here
}
}
I am facing the similar problem. But i have figured out that the textview is there but it is hiding under the extended toolbar/actionbar(because of including the tablayout in it). Give your textview a margintop of 100dp or 200dp and give it a background color and you will be able to see that it is there but hidden under the actionBar. Or you can even contract the ActionBar by sliding on it upward to reveal your textview.
See the question below for how to solve this :
Fragment from View Pager hiding behind Tab Bar
Been having a headache over this, finally found a simple solution. Set your ViewPager height to an absolute value instead of android:layout_height="match_parent" or android:layout_height="wrap_content"
Try android:layout_height="300dp or some preferred value.
I want to call an fragment method from my activity, describe like in this SO-question: FindByID
TestFragment testFrag = (TestFragment) getFragmentManager().getFragmentById(R.id.testfragment);
if(testFrag != null && testFrag.isAdded())
testFrag.testMethod("Test");
As seen they identify the fragment by ID which is set in the xml. As I only have a fragment container none of my fragment layouts have a ID.
So my seconds thought was using the function getFragmentByTag `like in Tags
fragmentTransaction.replace(R.id.frameTitle, casinodetailFragment, "fragmentTag");
but as I use an action bar with tabs I don't have any tags:
My activity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fragmentcontainer);
// ActionBar gets initiated
ActionBar actionbar = getActionBar();
actionbar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Define Tabs
ActionBar.Tab BasicInfoTab = actionbar.newTab().setText(
R.string.tab_BaseInfo);
..
// Define Fragments
PlantBasicInfoFragment BasicInfoFragment = new PlantBasicInfoFragment();
..
// Set TabListeners
BasicInfoTab.setTabListener(new TabListener(BasicInfoFragment));
..
// Add tabs to Actionbar
actionbar.addTab(BasicInfoTab);
..
// Icon clickable
actionbar.setDisplayHomeAsUpEnabled(true);
}
and its layout:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center">
<LinearLayout
android:orientation="horizontal"
android:id="#+id/LabeledObjectHeaderInfo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<!-- ... -->
</LinearLayout >
<!-- fragment container -->
<LinearLayout
android:orientation="horizontal"
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
</LinearLayout>
</LinearLayout>
One of my fragments:
<?xml version="1.0" encoding="utf-8"?>
<TableLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:id="#+id/table">
<TableRow>
<!-- ... -->
</TableRow>
<!-- ... -->
</TableLayout>
and finally my tab listener
public class TabListener implements ActionBar.TabListener {
public Fragment fragment;
public TabListener(Fragment fragment) {
this.fragment = fragment;
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
ft.replace(R.id.fragment_container, fragment);
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
ft.remove(fragment);
}
}
So how can I identify my current fragment?
Thanks in advance
P.S. The whole tab switching works perfectly, but now I want to build an addional feature inside the activity!
Add a tag while creating tabs.
ActionBar.Tab BasicInfoTab = actionbar.newTab().setText(R.string.tab_BaseInfo);
BasicInfoTab.setTag("tab1");
And in the listener class, retrieve the tag upon event.
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
String tabId = tab.getTag().toString();
}
This way you get the current tag. To identify the current fragment, you can keep a stack of fragments and pick the right one on tab change.
Edit
The tabId, aforementioned, identifies which tab is which. In order to set a fragment id/tag, there are many ways depending on your needs. One method is to replace your actual fragment layout with an intermediate layout.
For instance, A be the fragment you want to add to fragment container. Create another fragment class called IntermediateFragment with the following layout.
<?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="horizontal"
android:baselineAligned="false">
<fragment
android:id="#+id/fragmentId"
android:layout_width="match_parent"
android:layout_height="match_parent"
class="classA" />
</LinearLayout>
Now assign the layout you mentioned in the post (containing table) as a new one and add it to fragment class A. Now add Intermediate fragment to container which in turn pulls fragment A. Identify fragment A by id/tag added in the layout.
Hope it makes some sense!
Finally I got my solution by changing the TabListener, so I can add the fragment with an tag and then use the findFragmentByTag() function.
So my TabListener now looks like this (only constructor and onTabSelected changed)
public TabListener(Fragment fragment, String tag) {
this.fragment = fragment;
this.fragmentTag = tag;
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
ft.replace(R.id.fragment_container, fragment, fragmentTag);
}
With this I only need to add a string (as tag) when adding the TabListener to my fragments and don't have to do further changes.
I used ActionBarSherlock to get some Holo Themed Tabs and an ActionBar on my app and created a Fragment to handle the behavior on each tab. I wanted the tabs and a button along the bottom to "sandwich" the fragments do at the bottom of the screen there would be a button that would have one click listener across both fragments.
In my Activity I created the tabs like this.
public class InviteFriendsActivity extends SherlockFragmentActivity implements ActionBar.TabListener
{
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
ActionBar bar = getSupportActionBar();
bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
ActionBar.Tab tab1 = bar.newTab();
tab1.setText("Tab 1");
tab1.setTabListener(this);
ActionBar.Tab tab2 = bar.newTab();
tab2.setText("Tab 2");
tab2.setTabListener(this);
bar.addTab(tab1);
bar.addTab(tab2);
}
}
And then I created the onTabSelected
public void onTabSelected(Tab tab, FragmentTransaction ft)
{
if (tab.getPosition() == 0)
{
Fragment1 frag = new Fragment1();
ft.replace(android.R.id.content, frag);
}
else if (tab.getPosition() == 1)
{
Fragment2 frag = new Fragment2();
ft.replace(android.R.id.content, frag);
}
}
I have no problem getting the tabs to display or change, but I can't seem to figure out how to get a button the would line the bottom of the screen and stay static while inside this activity and still allow me to switch between the two fragments.
You want a button which is displayed through every fragment and each tab?
This can easily done by using a fragmentcontainer which displays your fragments.
For example use a layout like this:
<?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" >
<fragment
android:name="com.example.yourfragmentcontainer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="#+id/button1"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true" />
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:text="Button" />
</RelativeLayout>
For help how to setup a ActonBar using a fragmentcontainer take a look at this tutorial: http://arvid-g.de/12/android-4-actionbar-with-tabs-example
I'm trying to build an Android 4.0 App with the new fragments and action bar.
I'm doing well but I have a little problem now.
When I put a fragment inside a tab, and for example, a time picker in the fragment layout, in the emulator it will appear twice, one on top of the other.
Here is my code:
public class NetworksActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.networks);
// setup Action Bar for tabs
ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// instantiate fragment for the tab
Fragment networksFragment = new NetworksFragment();
// add a new tab and set its title text and tab listener
actionBar.addTab(actionBar.newTab().setText("Sensors")
.setTabListener(new ActionTabListener(networksFragment)));
}}
<?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:orientation="vertical" >
<fragment
android:id="#+id/net_frag"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:name="my.package.test.NetworksFragment" />
</FrameLayout>
public class NetworksFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.networks_fragment, container, false);
}
}
<?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:orientation="vertical" >
<TimePicker
android:id="#+id/timePicker1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</FrameLayout>
public class ActionTabListener implements ActionBar.TabListener {
private NetworksFragment frag;
// Called to create an instance of the listener when adding a new tab
public ActionTabListener(NetworksFragment fragment) {
frag = fragment;
}
#Override
public void onTabReselected(Tab arg0, FragmentTransaction arg1) {
// TODO Auto-generated method stub
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
ft.add(R.id.net_frag, frag, null);
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
ft.remove(frag);
}
}
It seems like its putting two fragments (two copies) in the same activity.
Do you know what are causing this?
Thanks in advance.
It looks like you are defining a fragment in XML, which will instantiate it when that layout is inflated (from NetworksActivity.setContentView(R.layout.networks)) then you are creating another instance of it just below that.
Unless I am missing something, that is your problem. No need to define it in XML if you are going to instantiate it manually and add it yourself in code.
I had a similar problem. The way i solved it was to remove this code from my Fragment-class:
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
CameraFragment cameraFragment = new CameraFragment();
fragmentTransaction.add(R.id.spinnerFragment, spinnerFragment);
fragmentTransaction.commit();
And left this code from my fragment-XML:
<fragment
android:id="#+id/spinnerFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
class="com.example.SpinnerFragment" />
I guess you can do it the oposite way also :)
I'm new on Android and I try to make an application on Android Honeycomb 3.0
Here is my problem: I have 2 tabs in my action bar. Tab 1 uses fragments A and B and Tab 2 uses fragments C and D. When I load the application, the tab 1 is selected and fragments A and B are displayed. Then I click on tab 2 and it also works fine. But when I go back to tab 1, the app crashes and the following error is shown:
android.view.InflateException: Binary XML file line #6: Error inflating class fragment.....
.....
Caused by:java.lang.IllegalArgumentException: Binary XML file line #6: Duplicate
id 0x7f............. tag null or parent id 0x.......
here is my code:
/** 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);
bar.setDisplayShowTitleEnabled(false);
ActionBar.Tab tab1 = bar.newTab().setText("tab 1");
ActionBar.Tab tab2 = bar.newTab().setText("tab 2");
Fragment frag1 = new FragmentOne();
Fragment frag2 = new FragmentTwo();
tab1.setTabListener(new MyTabListener(frag1));
tab2.setTabListener(new MyTabListener(frag2));
bar.addTab(tab1);
bar.addTab(tab2);
}
private class MyTabListener implements ActionBar.TabListener {
private Fragment mFragment;
// Called to create an instance of the listener when adding a new tab
public MyTabListener(Fragment fragment) {
mFragment = fragment;
}
public void onTabSelected(Tab tab, FragmentTransaction ft) {
ft.add(R.id.fragments, mFragment);
}
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
ft.remove(mFragment);
}
public void onTabReselected(Tab tab, FragmentTransaction ft) {
// do nothing
}
}
Fragment 1:
public class FragmentOne extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View mainView = inflater.inflate(R.layout.fragments, container, false);
return mainView;
}
}
fragments.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">
<fragment
xmlns:android="http://schemas.android.com/apk/res/android"
android:name="ch.comem.test.FragmentOneA"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/idFragment_one_a"
android:layout_weight="30">
</fragment>
<fragment
xmlns:android="http://schemas.android.com/apk/res/android"
android:name="ch.comem.test.FragmentOneB"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/idFragment_one_b"
android:layout_weight="70">
</fragment>
Thanks for your help.
The main issue I see is that your FragmentOne class inflates fragments.xml, which itself contains references to two further fragments FragmentOne and FragmentTwo. This is not valid as Fragments can not contain other Fragments.