I have the following activity
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity_layout);
TabHost mainTabHost = (TabHost) findViewById(R.id.mainTabHost);
mainTabHost.setup();
mainTabHost.addTab(mainTabHost.newTabSpec("Tab 1").setIndicator("", ContextCompat.getDrawable(this, R.drawable.d1)).setContent(new Intent(this, Activity1.class)));
mainTabHost.addTab(mainTabHost.newTabSpec("Tab 2").setIndicator("", ContextCompat.getDrawable(this, R.drawable.d2)).setContent(new Intent(this, Activity2.class)));
mainTabHost.addTab(mainTabHost.newTabSpec("Tab 3").setIndicator("", ContextCompat.getDrawable(this, R.drawable.d3)).setContent(new Intent(this, Activity3.class)));
}
}
And this is the XML
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#id/mainTabHost"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="#dimen/activityHorizontalMargin"
android:paddingRight="#dimen/activityHorizontalMargin"
android:paddingTop="#dimen/activityVerticalMargin"
tools:context=".MainActivity">
<RelativeLayout
android:id="#id/mainHomeLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<FrameLayout
android:id="#android:id/tabcontent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentTop="true" />
<TabWidget
android:id="#android:id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true" />
</RelativeLayout>
</TabHost>
There is another activity, in which tapping a button launches this activity. However, the activity doesn't launch and I get the following error:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.nirvanapass/com.nirvanapass.MainActivity}: java.lang.IllegalStateException: Did you forget to call 'public void setup(LocalActivityManager activityGroup)'?
I have searched online - but whatever solutions I could find use ActivityGroup or TabActivity - both of which are deprecated. How to tackle this error and solve this problem?
The best solution is to use a modern tab solution. TabHost has been obsolete for quite some time. Using an Intent for a tab content has been deprecated for five years, and it was never a good idea even before then.
Most modern tab implementations use a ViewPager with some sort of tabbed indicator. PagerTabStrip and TabLayout are both in the Android SDK, and the Android Arsenal lists many other tab indicators in their ViewPager category.
If you really want the retro styling of a TabWidget, either use FragmentTabHost, or use TabHost where the tabs are views.
Here are sample apps for:
using PagerTabStrip
using TabLayout
using a third-party tab indicator
using TabHost with widgets for tabs
Related
I have a navigation drawer using fragments created from the default "Navigation Drawer Activity" template in Android Studio. Inside a fragment A, I want to open another fragment B. So the fragment B must replace fragment A. I saw on google, that I should use FrameLayout to Dynamically change the current displayed fragment.
<FrameLayout
android:id="#+id/nav_host_frame_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="#+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="#navigation/mobile_navigation" />
</FrameLayout>
To change fragment, I am using the code below, when I am clicking on a button in the fragment that I want to be replaced
NewCalendarEvent newEventFrag = new NewCalendarEvent();
getActivity().getSupportFragmentManager().beginTransaction()
.replace(R.id.nav_host_frame_layout, newEventFrag)
.addToBackStack(null)
.commit();
Currently, when I click on the button, the two fragments are show. Is because I am using fragment and frameLayout together ? What I am doing wrong ?
If you are using a NavHostFragment and the Navigation Component, then you never use a FragmentTransaction. Instead you navigate to a screen by using the APIs on NavController.
I have a button in my MainActivity that opens FragmentA. FragmentA covers the whole screen, but I still see the button from MainActivity, and I can still click on it.
I've tried using clickable in my fragment layout but it's not working
MainActivty
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
button.setOnClickListener {
val fragmentManager = this#MainActivity.supportFragmentManager
fragmentManager.beginTransaction()
.add(R.id.fragment_container, AFragment())
.addToBackStack(null)
.commit()
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:id="#+id/fragment_container">
<Button
android:text="Button Main"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/button" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
</android.support.constraint.ConstraintLayout>
fragment_a.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:clickable="true"
android:focusable="true">
android:background="#color/colorPrimary"
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="A"/>
</LinearLayout>
This is happening because you placed your Button inside of the ConstraintLayout you're using as the container of your Fragment.
When you add a fragment into a container like what you're doing, it's simply adding it in the same manner as if it was a View.
Therefore, if you add a Fragment into a ConstraintLayout that already possesses a Button as a child, the Fragment will be shown alongside the Button due to ConstraintLayout allowing for overlapping Views.
This is also why, if your container was a LinearLayout, then adding a Fragment will place the fragment underneath your Button instead.
So, with that in mind, the solution would be to handle it as if they were Views.
If you added a View into a layout and you have another View overlapping, how would you get rid of it?
The most common solution would be to set the Button's visibility to INVISIBLE or GONE when the Fragment is added.
Another solution might be to raise the elevation of the Fragment, so it's now higher than your Button.
Of course, you may also remove the button from the Container and place it inside a Fragment too.
This way, you can use the replace() method in a FragmentManager to replace the Fragment containing your Button with the Fragment you want to show.
I am a beginner and I am asking this just to gain knowledge. so in my app, I have a MainActivity And its layout activity_main.xml.
here is the code of activity main
<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"
tools:context="com.testapp.myapp.MainActivity">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Button 1"
android:id="#+id/btn1"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/btn1"
android:text="Button 2"
android:id="#+id/btn2"/> </RelativeLayout>
And here is the MainActivity.java
package com.testapp.myapp;
import android.app.Activity;
import android.os.Bundle;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}}
I Have created Two Blank activities named By Button1PDF And Button2PDF And Each Has layout named button1_pdf.xml and button2_pdf.xml respectively.
So what i wanna do is, i want to set a pdf file against these New Activities and when I will click on btn1 or btn2 On MainActivity, I want it to display the new activity Button1PDF or Button2PDF activity which will be containing the pdfs.
I tried this online using webview and it works flawlessly. but now i want it to display offline(means complete offline)
i have done some research and i found some libraries like
compile 'com.github.barteksc:android-pdf-viewer:2.0.3'
but i don't know how to use it. hope someone can clear my doubts.
thanks.
You will need to download the files first and then display them to the user using that library.
Read this question on how to download file from internet
We're making an android app, and there is something we want to add.
Which is the effect the Gmail app has.
You can choose which account you want to view (and the rest of the app will behave accordingly).
EDIT:
I now already have a (working) navigation bar, but the things I want are the round icons in the header. I want someone to be able to choose the user they are viewing.
The effect you want can be achieved by using NavigationView from the com.android.support:design support lib.
You can find a full tutorial on that here. And you can download the full source code from that tutorial here.
And here's another nice tutorial that you could follow.
But long story short, that view is split between two main parts, a header and a menu part, and each one of those you'll have to define on XML.
As from that tutorial:
Header View
This View is basically the top part of the navigation
drawer, which holds the profile picture, name and email etc. You need
to define this in a separate layout file we would look into that in
just a moment.
Menu
This is the menu you want to show below your header, we define
menu in a menus folder, just like you define menu for your overflow
menu. So basically NavigationView is a container for the Header View
and Menu which you are going to use in your sliding drawer. So now
that you understand the NavigationView we can start building our
Navigation Drawer.
With that in mind, build your header as you would do with any other layout. And the Menu is defined somewhat like the Toolbar/ActionBar menu. e.g.:
navigation_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group
android:checkableBehavior="single">
<item
android:id="#+id/drawer_home"
android:checked="true"
android:icon="#drawable/icon_home"
android:title="#string/title_home"/>
<item
android:id="#+id/drawer_content"
android:icon="#drawable/icon_content"
android:title="#string/title_content"/>
<item
android:id="#+id/drawer_about"
android:icon="#drawable/icon_about"
android:title="#string/title_about"/>
<item
android:id="#+id/drawer_exit"
android:icon="#drawable/icon_exit"
android:title="#string/title_exit"/>
</group>
</menu>
Then, on your Activity you'll just have to make a layout like the one found in the tutorial, using the DrawerLayout along with NavigationView.
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/drawer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".MainActivity">
<LinearLayout
android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="vertical"
>
<include
android:id="#+id/toolbar"
layout="#layout/tool_bar"/>
<FrameLayout
android:id="#+id/frame"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
</LinearLayout>
<android.support.design.widget.NavigationView
android:id="#+id/navigation_view"
android:layout_height="match_parent"
android:layout_width="wrap_content"
android:layout_gravity="start"
app:headerLayout="#layout/header"
app:menu="#menu/navigation_menu"/>
</android.support.v4.widget.DrawerLayout>
You'll also have to create some Fragments for each screen you want to display with this NavigationView. After you've done that, on your Activity you can handle the selection events by implementing NavigationView.OnNavigationItemSelectedListener, like this:
public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
// Your Activity
#Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
Fragment fragment = null;
switch(menuItem.getItemId()) {
case R.id.drawer_home:
fragment = new YourFragment();
break;
case R.id.drawer_content:
fragment = new AnotherFragment();
break;
case R.id.drawer_about:
fragment = new AboutFragment();
break;
case R.id.drawer_exit:
// TODO - Prompt to exit.
finish();
break;
}
if (fragment == null) {
fragment = new YourFragment();
}
drawerLayout.closeDrawers();
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.frame, fragment)
.commit();
return true;
}
}
As for your edit, the icons could be represented by an ImageView. And to navigate between multiple profiles, it depends on how you've implemented that logic on your app, but as a "generic" answer, you could switch those profiles using something like a Spinner.
Those tutorials will help you through that step:
Android spinner (drop down list) example
Android - Spinner
Basic Spinner example (Stackoverflow question)
Spinners (Android dev guide)
Once you've set that up on your header, handle the item selection and change the user profile accordingly. (This last part depends ENTIRELY on how you've implemented user profiles on your app). But just as a head start, you could check the android training site, more specifically, this part.
You should use NavigationView
It provides the framework for easy to implement material navigation
drawer with the help of inflate navigation items through menu
resource. Befor Navigation View, we have hard way to make material
navigation drawer using listview or linearlayout with custom adapter,
but now we just need to add Navigation View in DrawerLayout,
everything else will be handled by Navigation View.
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<!-- Your contents -->
<android.support.design.widget.NavigationView
android:id="#+id/navigation"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:menu="#menu/my_navigation_items" />
</android.support.v4.widget.DrawerLayout>
For this requirement You can check sample
MaterialDrawer
How To Make Material Design Navigation Drawer
Playing with NavigationView
Hope this helps .
I think this MaterialDrawer is what you're looking for. This library has a lot of examples. You can either use this library directly or read the source code and implement your own drawer.
You can implement this Material Navigation drawer using MaterialNavigation library.
Article about implementation is here.
You will just have to import that library and you're done. See demo code on below site:.
https://github.com/PatilShreyas/MaterialNavigationView-Android
The Android Developers TabWidget tutorial says the following:
"You can implement your tab content in one of two ways: use the tabs to swap Views within the same Activity, or use the tabs to change between entirely separate activities."
The tutorial goes on to demonstrate how you can use tabs with separate Activities. I have been unable to find an example of using tabs with different Views within the same Activity. I would rather not re-invent this particular wheel, so I am hoping someone here knows how this is done and can clue me in. Thanks!
I think in the .setContent method of each tab you pass in the view you wish to use:
TabHost.TabSpec spec1 = tabs.newTabSpec("tag1");
spec1.setContent(R.id.AnalogClock01);
spec1.setIndicator("Analog Clock");
Here's an example I found awhile back:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TabHost android:id="#+id/TabHost01" android:layout_width="wrap_content" android:layout_height="wrap_content">
<TabWidget android:id="#android:id/tabs" android:layout_width="wrap_content" android:layout_height="wrap_content" />
<FrameLayout android:id="#android:id/tabcontent" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingTop="65px">
<AnalogClock android:id="#+id/AnalogClock01" android:layout_width="wrap_content" android:layout_height="wrap_content"></AnalogClock>
<DigitalClock android:text="DigitalClock01" android:id="#+id/DigitalClock01" android:layout_width="wrap_content" android:layout_height="wrap_content"></DigitalClock>
</FrameLayout>
</TabHost>
</LinearLayout>
And the Java code for this example is as follows:
import android.app.Activity;
import android.os.Bundle;
import android.widget.TabHost;
public class tabexample extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
TabHost tabs = (TabHost)findViewById(R.id.TabHost01);
tabs.setup();
TabHost.TabSpec spec1 = tabs.newTabSpec("tag1");
spec1.setContent(R.id.AnalogClock01);
spec1.setIndicator("Analog Clock");
tabs.addTab(spec1);
TabHost.TabSpec spec2 = tabs.newTabSpec("tag2");
spec2.setContent(R.id.DigitalClock01);
spec2.setIndicator("Digital Clock");
tabs.addTab(spec2);
}
}
I used this one and it was fine for me
http://www.codeproject.com/Articles/107693/Tabbed-Applications-in-Android