Android Button that stays always above the all activities for standby - android

I am trying to make a Button which will always be on standby like Floating Action button despite whatever context it may be in but shall sustain all above my activities, How could I achieve this please refer me a link or give me an idea.

One solution is to create a single activity with the button and then use fragments instead of the current activities.

class ActivityOne extends BaseActivity{
#Override
protected View childView(){
return getLayoutInflator().inflate(R.layout.activity_one, null);
}
}
class ActivityTwo extends BaseActivity{
#Override
protected View childView(){
return getLayoutInflator().inflate(R.layout.activity_two, null);
}
}
public abstract class BaseActivity extends Activity{
protected abstract View childView();
#Override
protected void onCreate(SavedInstanceState savedInstanceState){
super.onCreate(savedInstanceState);
RelativeLayout baseLayout;
ViewStub stub;
baseLayout = (RelativeLayout)
this.getLayoutInflater().inflate(R.layout.layout_base, null);
stub = (ViewStub) baseLayout.findViewById(R.id.base_content_stub);
// Replace viewstub with content.
baseLayout.removeView(stub);
baseLayout.addView(childView(), stub.getLayoutParams());
super.setContentView(baseLayout);
}
}
layout_base.xml
<RelativeLayout
....
>
<ViewStub
android:layout_width = "match_parent"
android:layout_height = "match_parent"
android:id="#+id/base_content_stub"/>
<Button
.... // <---- common to all activities
/>
</RelativeLayout>

Your best bet would probably be to make an abstract activity that contains that button and adds it to the layouts of all activity that inherit from it. That way you don't have to duplicate the code in every activity.

It's not possible to use the same button for every activity. You could use the same layout, but you'd have to create the button anew every time you created a new activity. You might be able to avoid that if you did some fancy stuff with the action bar that is frankly not worth it. I suggest you look at using fragments instead of activities, in which case you can have your layout file for you activity look something like this:
<LinearLayout android:id="#+id/fragment_container"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="coop.nisc.intern2016.ui.MainActivity">
<Button
android:id="#+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="#string/button_text" />
<RelativeLayout
android:id="fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
Then, you can use a FragmentManager to put the fragment into the fragment_container. The code could look something like this:
private void showCustomFragment() {
FragmentManager fragmentManager = getSupportFragmentManager();
customFragment = new customFragment();
fragmentManager.beginTransaction()
.replace(R.id.fragment_container, customFragment, customFragment.TAG)
.commit();
}

Create a BaseActivity class as a usual activity and a corresponding xml layout file with any layout you want. Add your button inside this layout, and a FrameLayout below the button. Code your button inside the onCreate() of the above activity. Your button's done.
Now, make all your other activities extend the BaseActivity, the super.onCreate() will take care of the button. Instead of setContentView() use:
FrameLayout contentFrameLayout = (FrameLayout) findViewById(R.id.content_frame); //Remember this is the FrameLayout area within your base activity xml
getLayoutInflater().inflate(R.layout.the_layout_you_want_to_load, contentFrameLayout);
'the_layout_you_want_to_load'
is the layout xml of your current activity.

Related

Android: Fragment is added below childview

I have a FrameLayout with a few buttons, and some ImageViews. When I add a fragment, it shows on top of the ImageViews as expected but below the buttons but I don't know why.
I searched through a lot of the SO posts but couldn't find problems similar to mine.
I have a custom onClickListener that adds the fragment
Custom clickListener class:
public void onClick(View v) {
// a context is passed to the listener
// this gets rootview id
int id= ((ViewGroup)((Activity)context).getWindow().getDecorView().findViewById(android.R.id.content)).getChildAt(0).getId();
MyFragment myFragment = new MyFragment();
FragmentTransaction ft = ((Activity) context).getFragmentManager().beginTransaction();
ft.add(id, myFragment, "F1");
ft.commit();
}
The View I am adding the fragment to:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/startscreen"
>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/gamelogo"
android:id="#+id/logo"
android:scaleType="fitStart"
android:adjustViewBounds="true"
/>
</FrameLayout>
Activity:
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.startmenu);
final FrameLayout r = (FrameLayout) findViewById(R.id.startscreen);
addViews(r);
}
public void addViews(FrameLayout r){
// add some buttons to r
// add custom OnClickListener to one of the buttons
// add some ImageViews
// add animation to one button
}
FrameLayout is designed to block out an area on the screen to display a single item. Generally, FrameLayout should be used to hold a single child view, because it can be difficult to organize child views in a way that's scalable to different screen sizes without the children overlapping each other.
That's from the Docs, did you considered to change the layout?
I figured that I have to add the fragment to the parent of the base FrameLayout. I don't know why I would have to do that though.

How to add a fragment to a layout of a DialogFragment?

I am having a custom DialogFragment which contains a layout, some UI elements, and a Fragment holder layout. What I need to do is inflate a Content fragment into the holder layout and provide a navigation inside that. On clicking a button inside the added fragment the view will navigate to another view. The fragment will be replaced by another one in the same holder i.e. the contentFragment1 will show some data and on clicking a preview button there will replace contentFragment1 with contentFragment2.
I read somewhere that you cannot replace a fragment hardcoded to the xml with another one.
So I am trying to add the contentFragment1 to the viewholder from the onActivityCreated() of the dialog fragment. But I am getting an error that the resource pointed by R.id.fragmentHolder not found. What could be the possible reason?
Here is my code for the DialogFragment:
public class MyDialog extends DialogFragment {
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Dialog customDialog = new Dialog(getActivity());
customDialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE);
customDialog.setContentView(R.layout.reports_dialog);
return customDialog;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
android.app.FragmentTransaction fragmentTransaction =getFragmentManager().beginTransaction();
fragmentTransaction.add(R.id.myFragmentHolder, new ReportsListFragment());
fragmentTransaction.commit();
super.onActivityCreated(savedInstanceState);
}
<?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="400dp"
android:background="#android:color/transparent" >
<TextView
android:id="#+id/textView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:text="This is my header text view for the Dialog"
android:textSize="18sp" />
<RelativeLayout
android:id="#+id/myFragmentHolder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/headerlayout" >
</RelativeLayout>
After trying a lot, I came to a conclusion that onCreateDialog() doesn't have a view, it just sets a view on calling setView().
That is why on adding dynamic(framelayout tag) or static fragment(fragment tag) in the layout of the dialogfragment gives no parent view or duplicate id error.
To achieve the above, one should use onCreateView with a framelayout tag which can be inflated dynamically. Title and alert buttons are then added to the layout.
R.id.myFragmentHolder is inflated to the dialog's layout, and getFragmentManager() returns the manager for the activity, so it can't find the view.
With nested fragments in API level 17 you can use getChildFragmentManager().
Just be sure that the reports_dialog layout containts a layout whose id myFragmentHolder like this one
<FrameLayout
android:id="#+id/fragment_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Just for reference here, as Brandon mention the correct answer is to use the getChildFragmentManager(), keeping in mind, that android will also restore the state of fragments.
The correct code, to add your first fragment, is:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// if the saved instance isn't null, the fragment state will be restored by android
if (savedInstanceState == null) {
getChildFragmentManager().beginTransaction().add(R.id.myFragmentHolder, new ReportsListFragment()).commit();
}
}
after the view has been added. Later use replace if only one fragment should be shown at the same time.
I would also recommend to call transaction.addToBackStack(null); if the Android back button should be supported.
id of fragment holder in layout is fragmentHolder and you are using myFragmentHolder in code try to replace this by:
fragmentTransaction.add(R.id.fragmentHolder, new ReportsListFragment());

Optimize layout during Fragment replacement in FragmentActivity

I tried to replace a Fragment in FragmentActivity run-time.
fragment_activity.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent" />
MyFragmentActivity.java
public class MyFragmentActivity extends SlidingFragmentActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_activity);
}
// Will be called by AsyncTaskLoader's onLoadFinished.
public void selectActiveContent() {
// MyFragment's top level is LinearLayout
Fragment fragment = new MyFragment();
getSupportFragmentManager().beginTransaction().replace(R.id.content, fragment).commitAllowingStateLoss();
}
However, I realize the outcome is not optimized.
I realize the FrameLayout supplied through my own fragment_activity.xml, is being attached to another parent FrameLayout.
Instead of
FrameLayout
FrameLayout
LinearLayout
LinearLayout
ListView
I wish to have
FrameLayout
LinearLayout
LinearLayout
ListView
May I know how I can achieve so? Is it possible I can have a fragment_activity.xml without a ViewGroup (FrameLayout) ?
While the <merge> element was specifically designed for removing useless levels of view hierarchy, per this answer, you cannot use merge tags in Fragments and you must instead use a ViewGroup root view as you noticed, the lightest weight (i.e., fastest to render) being a FrameLayout.

Android Fragment : bug fix explanation

I'm starting using Fragments, and I've done like the API guide but ... of course it'd be too easy ;)
When I launch the app, it crashes. After some research I've found this post Android fragment is not working
and the response of Stephen Wylie seems to correct the things for Ali, but .. I don't get it !
Where should I put the FrameLayout ? The "where_i_want_my_fragment" id... it's whatever I want, right ?
and finally where should I put the Java code ? in my activity (which is displaying 2 fragments by the way) .
Thanks !
Nico
EDIT : Let's just say what I want for design you would understand better I think.
I want a list fragment on left side which display a list of strings, and to the right side I want a fragment displaying info regarding the selected string in the list. And I wanna be able to swip with fingers movements the right side of my app (I dont know if it s better to swipe fragment or whatever.. It's the same layout but filled with differents datas)
Ok I just post my code because I really don't see why it doesn't do anything.
This is my activity_main.xml
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:baselineAligned="false"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/list_frag"
android:name="main.courante.c.DateListFragment"
android:layout_width="fill_parent"
android:layout_height="match_parent" >
</FrameLayout>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fiche_frag"
android:name="main.courante.c.fiche_frag"
android:layout_weight="2"
android:layout_width="0dp"
android:layout_height="match_parent" >
</FrameLayout>
</LinearLayout>
Here is my main activity :
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DateListFragment fragment = new DateListFragment();
getFragmentManager().beginTransaction().add(R.id.list_frag, fragment).commit();
fiche_freg frag2 = new fiche_frag();
getFragmentManager().beginTransaction().add(R.id.fiche_frag,frag2).commit();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
Here is DateListFragment (no onCreateView because it 's automatically generated)
public class DateListFragment extends ListFragment {
private int mposition = 1;
private String[] mListItem = new String[] {
"Lundi 9 Juilllet",
"Mardi 10 Juillet",
"Mercredi maintenant"
};
#Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
this.setListAdapter(new ArrayAdapter<String>
(this.getActivity(),R.layout.frag_list_view ,mListItem));
this.getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
}
and here is fiche_frag :
public class fiche_frag extends Fragment {
#Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
return inflater.inflate(R.layout.checks_matin,container,false);
}
R.layout.checks_matin works fine alone.
I thank you already and again for your help. I'm a beginner in android environnement and I find it difficult to englobe every notions for the UI at once... !!
You understand the basics. The FrameLayout goes wherever you want your fragment(s) to go. I've done it where my whole screen was one single FrameLayout before and I swapped up to five different fragments in and out of it.
If you have two Fragments that you want to display simultaneously, you could make your main layout with two FrameLayouts. However, this means you are locked into having both there all the time (or an empty space if you remove one.
If you want two fragments that don't have to be on the screen at the same time you use a single FrameLayout and write code to swap the fragments as required.
Code to instantiate fragments should always be in the controlling activity (if they are dynamic).
Without code and a more specific problem, the above is the best answer I can give you.
EDIT
An example main layout to put two fragments side by side:
<?xml version="1.0" encoding="utf-8"?>
...
<LinearLayout
android:id="#+id/frames"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="#id/hline1"
android:layout_below="#id/horizontalline"
android:orientation="horizontal" >
<FrameLayout
android:id="#+id/leftpane"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight=".4" />
<FrameLayout
android:id="#+id/rightpane"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="1" >
</FrameLayout>
</LinearLayout>
...
To add your fragment to one of the framelayouts:
FragmentClass fragment = new FragmentClass();
getFragmentManager().beginTransaction().add(R.id.leftpane, fragment).commit();
If you want to swap fragments in one of the framelayouts (say the left pane), you can do it like this:
FragmentClass fragment = new FragmentClass();
getFragmentManager().beginTransaction().replace(R.id.leftpane, fragment).commit();
I suggested instantiating from the XML because it sounded like you were going to have two fragments and not make any changes. If you are going to swap them in and out, then it would be appropriate to add a tag to each one so you can find them again if you want to display them again.

Change View content in activity dynamically

My abstract class extended from Activity class consists of three Views as described in the following XML snippet:
<?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="#drawable/bg">
<LinearLayout
android:id="#+id/top_border">
...
</LinearLayout>
<View
android:id="#+id/activity_content"
...
/>
<LinearLayout
android:id="#+id/bottom_border">
...
</LinearLayout>
</LinearLayout>
And in onCreate() method I set this XML-layout as content view.
I want the Activitys which extend this one to override onCreate() and there define the activity_content View remaining borders immutable.
For example like this:
abstract public class MyActivity extends Activity {
protected View mContent;
#Override
protected onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.common_layout);
initializeContent();
}
abstract void initializeContent();
}
class OneActivity extends MyActivity {
#Override
protected void initializeContent() {
mContent = View.inflate(this, R.layout.some_view, null); // i.e. concrete View (e.g. LinearLayout, FrameLayout, GridView, etc.)
}
}
But when I do so my mContent remain the same as it was when I defined it in MyActivity's onCreate().
How can I change view's type/content depends on what Activity is in foreground?
First change the view in your main layout into a view group (for example, a LinearLayout). Then you can add views to it. If you add a unique view, it will have exactly the effect you want to achieve.
class OneActivity extends MyActivity {
#Override
protected void initializeContent() {
final ViewGroup viewGroup = (ViewGroup) findViewById(R.id.activity_content);
viewGroup.addView(View.inflate(this, R.layout.some_view, null));
}
}
In your case that should work. If your custom view group contained other views from higher up in the hierarchy, you can clean it before adding your custom view:
viewGroup.removeAllViews();
It works, I do exactly that in most of my projects.
An alternative is to look at the Fragments API, available for latest versions of the SDK.
You can't override class data members in Java, use methods instead

Categories

Resources