I am developing an android application. What I am want to achieve in this app is, I want to make a custom progress bar which has to be available to all the activities. So I created BaseActivity and I added one custom gif in BaseActivity's layout then I created SecondActivity which extends BaseActivity.
BaseActivity(By default gif is invisible) has two methods called showProgressBar and hideProgressBar I am calling this method from SecondActivity but it is not showing a progress bar. Then I make a BaseActivity launcher activity and to check the gif it is showing.
How should I achieve this?
You can override the setContentView in your BaseActivity and add your base layout there, that way when the child activities call the setContentView, the base layout is also set. You'll need to set a FrameLayout that will 'hold' the child activity's layout. Something along the following lines should work.
//In BaseActivity
#Override
public void setContentView(int layoutResID)
{
DrawerLayout fullView = (DrawerLayout) getLayoutInflater().inflate(R.layout.activity_base, null);
FrameLayout activityContainer = (FrameLayout) fullView.findViewById(R.id.activity_content);
getLayoutInflater().inflate(layoutResID, activityContainer, true);
super.setContentView(fullView);
}
P.S - In my above example, I used a DrawerLayout, you should be able to use it with any ViewGroup. Just replace that line with the base ViewGroup in your base activity layout.
Edit - Added xml for clarity
//activity_base.xml
<android.support.v4.widget.DrawerLayout
android:id="#+id/activity_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
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="?actionBarSize"
android:background="#color/background_material_dark"
/>
<FrameLayout
android:id="#+id/activity_content"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<android.support.design.widget.NavigationView
android:id="#+id/navigationView"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:menu="#menu/menu_base"/>
</android.support.v4.widget.DrawerLayout>
You can create a custom dialog class so it will be available for every Activity in your project
Create dialogClass:
public class ProgressDialog extends Dialog {
public ProgressDialog(#NonNull Context context) {
super(context);
setContentView(R.layout.progress_dialog); //this is your layout for the dialog
}
}
And all you need to do is to create dialog instant and call it like this:
ProgressDialog progressDialog = new ProgressDialog(getContext());
progressDialog.show(); // this line shows your dialog
And in your dialog class, you can put your logic, change the way your layout will look and do anything that you need to.
Related
I have two activities with same bottom bar.
The problem is when i call to startActivity from Activity A to Activity B has some blink and is not looking so smooth.
for example what I want is like Activity with a container with two fragments and the activity has the bottom bar so this will not change the bottom bar.
I know Activity with Fragments can help me with that but is too complicated to change it on my project so is the last option for me.
I find one more option to do it with SharedElements transition but is supported only from api 21 (Lollipop).
This is my activities and I need the LinearLayout on bottom stay sticky when i change it to Activity B.
You can set up activity animations:
startActivity();
overridePendingTransition(R.anim.hold, R.anim.fade_in);
Please, refer to this answer: stackoverflow
you can remove the defulat transtion between activites.
try this under yourProject/res/values/styles.xml:
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowAnimationStyle">#null</item>
</style>
If you want the same instance you will have to use fragments.
If not you could just put that LinearLayout to both layout files.
Which one do you want?
You need create a layout and include ex. bottombar.xml in layout folder and create the layout.
<include layout="#layout/bottombar"/>
if you dont want look delay in change you need use fragments.
To manage fragment, i recommended use FragNav
With this library manage fragments its very easy, remove animation is not solution to your problem
I have made an Activity with two fragments.
In Activity class ,I have write this code for commonBottomSheet :-
BottomSheetBehavior mBottomSheetBehavior = BottomSheetBehavior.from(findViewById(R.id.bottom_pannel_layout));
mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
mBottomSheetBehavior.setBottomSheetCallback(mBottomSheetCallback);
In Activity xml file in Co-ordinator layout I have included below layout :-
<include layout="#layout/bottom_sheet_pannel"/>
In CommonBottomSheetFragment, you can create your layout .
And my xml file (bottom_sheet_pannel) for bottomSheet is like this :-
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/bottom_pannel_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:behavior_peekHeight="45dp"
app:layout_behavior="android.support.design.widget.BottomSheetBehavior">
<ImageView
android:id="#+id/grabber_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:src="#drawable/ic_vector_slider_grabber"
android:tint="#color/colorTint" />
<fragment
android:id="#+id/rf_common_details_fragment"
android:layout_marginTop="#dimen/margin_10"
android:name="com.fragment.CommonBottomSheetFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
you can change state of bottomSheet with below callBack :-
private BottomSheetBehavior.BottomSheetCallback mBottomSheetCallback = new BottomSheetBehavior.BottomSheetCallback() {
#Override
public void onStateChanged(View bottomSheet, int newState) {
// do what you want on state change
}
#Override
public void onSlide(View bottomSheet, float slideOffset) {
}
};
I am creating a BaseActivity.java class to contain a navigation view and toolbar.
BaseActivity.java
public class BaseActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener{
private Toolbar toolbar;
private DrawerLayout drawerLayout;
private ActionBarDrawerToggle actionBarDrawerToggle;
private NavigationView navigationView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_base);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
//OTHER CODES TO SET UP NAVIGATION VIEW...
}
}
I am creating a activity_base.xml file that contains DrawerLayout
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:orientation="vertical"
tools:context="com.example.sumit.movie.MovieActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="#style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/fragment_container"> ***MY PLACEHOLDER FRAGMENT***
</FrameLayout>
</LinearLayout>
<android.support.design.widget.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="#layout/nav_header_movie"
app:menu="#menu/activity_movie_drawer" />
</android.support.v4.widget.DrawerLayout>
As you can see, I have a fragment_container inside this file, which I thought I would use to plug the views from another activites. For every activity, I would create a corresponding fragment and plug that fragment into this fragment_container.
But then what would I do with the xml file of the activity itself ?
I have read other answers on how to do this.
They say to create a BaseActivity.java class and extend this class to create other activities.
But do we have to create a xml file for this activity too, which would create the navigation view and the toolbar which would remain consistent across all activities ?
And if i don't create activity_base.xml, and merely create the class, Won't I have to write REDUNDENT codes for setting the navigation drawer and toolbar in every activity's xml file ?
Please help me on how this is done. I am new to android.
For this use case you might not need to have an activity xml for every page you can just have an activity class that extends BaseActivity that customises the activity / toolbar / nav draw and then you can pull common functions up to the base activity. so the BaseActivity does the setup in it on create then customisation happen per activity class.
I faced the similar problem. But, in my case there was custom NavigationDrawer and ActivityLayout used databinding. The solution is to use the same viewModel for NavigationDrawer and create layout for each Activity. Create abstract BaseDrawerActivity, which has abstract method for getting layout resource Id. Every derived Activity will specify its own resource.
Just create one activity which will going to extend NavigationDrawerActivity and setup all functionalities to that activity like onclick listener setting textviews and all.. now If you want a activity to have Navigation Drawer You just Need to extend that activity which extended The NavigationDrawerActivity and instead of using setContentView instead You have to use
addview()
with the inflated View.. Thats all..
Hope it helps!!!
I have this situation: when launching the app, the first fragment (A) displayed has a list of some users. When clicking a user, another fragment (B)is displayed and, together, the drawer menu will be different for each user.
As you can see, I can NOT set up the DrawerLayout when launching the app (the main activity or Launcher) since I don't have the data for the listView yet, but have to set it up when clicking a user in the list in fragment A after the app finishes launching (That's when I can retrieve the data for the listView of the drawer menu, which is indicated by the id: fragment_drawer in below xml file).
Here's the xml file for "MainActivity":
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<!-- The main content view -->
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- The navigation drawer, listView is inside MyDrawerFragment's layout-->
<fragment android:id="#+id/fragment_drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:name="mypackage.com.MyDrawerFragment"
tools:layout="#layout/drawer_layout" />
</android.support.v4.widget.DrawerLayout>
How can I achieve the goal in fragment B? Is this achievable at all in fragment B?
If not possible doing this in fragment B, I am thinking to launch a second activity, say Activity2, and the above xml layout file will be applied to this new activity, when clicking the user in fragment A, I just keeps doing this: closing the existing Acitvity2 by calling finish() and create a new Activity2 instance with new data for drawer menu? Is this approach feasible at all?
Any hints are highly appreciated!
Thanks,
Shawn
I had to do an app where I had to make an Activity with 4 fragments and a ViewPager, where only in 2 I would open a different Drawer.
The Activity's layout must contain the DrawerLayout*, but since the Drawer itself depends on which Fragment I'm on, I figured that it should be the Fragment the one in charge of rendering (or not) the Drawer.
*If the Activity doesn't contain the DrawerLayout, it wouldn't be displayed filling the whole screen!
I did something like this, though it does need some refactoring and clean up :)
Working on the idea that the Fragment is in charge of rendering the Drawer, but it is the Activity the one that has access to it, I made two interfaces to communicate Fragment and Activity:
/**
* should be implemented by any fragment interested in communicating
* with a {#link FragmentListener} Activity
*/
public interface ActivityListener {
/**
* called from {#link FragmentListener} requestOpenDrawer
* the fragment is in charge of rendering its drawer's layout
*/
public void renderDrawer(DrawerLayout mDrawerLayout,
NavigationView viewById, Activity activity);
}
-
/**
* used to communicate FROM fragments, to its parent Activity
* implemented by {#link MainTabbedActivity}
*/
public interface FragmentListener {
/**
* call from a fragment to request opening the drawer
* note that if the drawer isn't opened by the activity,
* it wouldn't cover the whole screen
*/
void requestOpenDrawer(Fragment requester);
void requestCloseDrawer();
DrawerLayout getDrawerLayout();
}
Implementation
#Override
public void requestOpenDrawer(Fragment requester) {
mDrawerLayout.openDrawer(Gravity.RIGHT); //Edit Gravity.End need API 14
if (requester instanceof ActivityListener) {
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
//let fragment render the drawer
((ActivityListener) requester).renderDrawer(mDrawerLayout, navigationView, this);
}
}
-
#Override
public void renderDrawer(DrawerLayout mDrawerLayout, NavigationView viewById, Activity activity) {
View child = activity.getLayoutInflater().inflate(R.layout.credit_fragment_drawer, null);
navigationView.addView(child);
}
Layouts
Both the Activity layout and the Fragments layout don't have anything more than the standard Drawer implementation:
Activity layout with Drawer:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/main_tabbed_drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:openDrawer="right">
<include
layout="#layout/activity_main_tabbed_content"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<android.support.design.widget.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="right"
android:fitsSystemWindows="true" />
</android.support.v4.widget.DrawerLayout>
Where activity_main_tabbed_content is whatever the content you want to put in the Activity.
The fragments really don't have anything more than a common Fragment.
Example:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- whatever views you want -->
</RelativeLayout>
Is there any possible way to share layout(part) between activities? For example, in my app, all activities have similar layout, the top part is long operation indicator (a progress bar, hidden when no operation is being executed), the bottom part is for showing errors. Only the middle part is different for all activities. See the picture below.
so my question is, is it possible to reuse the common layout(loading and error part) for all activities in my app? (currently I don't want to use fragment to do it for some reasons)
maybe the layout resources should like this:
layoutfolder
activity_common.xml
activity_one_content.xml
activity_two_content.xml
thanks
You can create an abstract 'base' activity that all your activities extend from, overriding setContentView to merge the base, and sub activity layouts.
This way you can handle all the loading/error code in the base activity, and simply toggle between hiding and showing the views in the sub activities.
The abstract activity:
public abstract class BaseActivity extends Activity {
protected RelativeLayout fullLayout;
protected FrameLayout subActivityContent;
#Override
public void setContentView(int layoutResID) {
fullLayout = (RelativeLayout) getLayoutInflater().inflate(R.layout.activity_base, null); // The base layout
subActivityContent = (FrameLayout) fullLayout.findViewById(R.id.content_frame); // The frame layout where the activity content is placed.
getLayoutInflater().inflate(layoutResID, subActivityContent, true); // Places the activity layout inside the activity content frame.
super.setContentView(fullLayout); // Sets the content view as the merged layouts.
}
}
the layout file:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- The main content view -->
<FrameLayout
android:id="#+id/loading_frame"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<!-- The main content view -->
<FrameLayout
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<FrameLayout
android:id="#+id/error_frame"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</RelativeLayout>
You could use include in XML to, well.. include the re-useable part of your layout code.
As an example, here's my layout file for the Toolbar I used in my app:
// /res/layout/component_toolbar.xml
<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:taggr="http://schemas.android.com/apk/res-auto"
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/primary"
android:minHeight="?attr/actionBarSize"
taggr:popupTheme="#style/ThemeOverlay.AppCompat.Light"
taggr:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar" />
Now, say if I want to use that Toolbar again in a different Activity, this is all I'd have to write:
// /res/layout/whatever_layout_this_might_be.xml
<include layout="#layout/component_toolbar" />
Bear in mind that this would only copy the layout - not the actual behavior of said widget/component.
If you want to actually copy all of the aspects (layout, behaviour) I'm afraid Fragment is the only way to go.
Although ActivityGroup is deprecated fro API 13 but if you don't wish to go with fragments then this can be your best choice.
According to documentation, an ActivityGroup is:
A screen that contains and runs multiple embedded activities.
You can find a tutorial here and here Although the mentioned tutorial uses a Tablayout you can replace that with your common layout in XML.
A second Approach could be Reuse the layout with include tag, in this approach you could just reuse your once created common layout everywhere in the app.
I want to place a common banner and menu on each Activity with footer too.
Can anyone guide me how can I implement master and child page like asp.net in Android???
Any help would be appreciated.
You could have each of your Activities extend a common base class which has a onCreateOptionsMenu method which inflates the menu from the same XML each time. Though as you can't have multiple inheritance, this may be tricky when you want to have plain activities and list activities, for example.
Another way would be to have a Util class where you have a method like setupMenu(Menu) which each of your Activities can call if you're doing some more complex menu setup.
In terms of the XML UI layout for each of your Activities, you can include a common banner by using the <include/> tag.
The solution was pretty easy.
You need to extends "Activity" Class,in onCreate function SetContentView to your base xml layout and also need to override setContentView in base Activity Class
For Example:
1.Create "base_layout.xml" with the below code
<?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"
android:background="#000000"
android:padding="15dp" >
<LinearLayout android:orientation="horizontal" android:background="#000000"
android:layout_width="fill_parent" android:layout_height="wrap_content"
android:minHeight="50dp" android:paddingLeft="10dp">
<ImageView android:layout_width="wrap_content" android:id="#+id/ImageView01"
android:adjustViewBounds="true" android:layout_height="wrap_content"
android:scaleType="fitCenter" android:maxHeight="50dp" />
</LinearLayout>
<LinearLayout android:id="#+id/linBase"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
</LinearLayout>
</LinearLayout>
2.Create "BaseActivity.java"
public class BaseActivity extends Activity {
ImageView image;
LinearLayout linBase;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.base_layout);
linBase = (LinearLayout)findViewById(R.id.linBase);
}
#Override
public void setContentView(int id) {
LayoutInflater inflater = (LayoutInflater)getBaseContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(id, linBase);
}
}
and
public class SomeActivity extends BaseActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.some_layout);
//rest of code
}
}
The only thing I noticed so far was that when requesting a progress bar (requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS)) this needs to be done before calling super.onCreate. I think this is because nothing can be drawn yet before calling this function.
This worked great for me and hopefully you will find this useful in your own coding.
I've had the same problem and solved it using ActivityGroup.
I suppose that menu items will move user to another activity, so with the same menu in every activity closing application with BACK button can be almost impossible (after some time user will have to go back through all activities he had ever seen).
I haven't found any good tutorials in english so have written mine some time ago (it's somewhat too short and in polish only, but Google Tranlslated version should be understandable) check this
You can also check how the TabHost works
ViewStub is the solution
activity_masterpage.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ViewStub android:id="#+id/stub_content"
android:inflatedId="#+id/subTree"
android:layout_width="match_parent"
android:layout_height="match_parent" />
stub = (ViewStub) findViewById(R.id.stub_content);
stub.setLayoutResource(R.layout.content_layout);
stub.inflate();