On an iphone context, when we add a view as a subview of another view, anything that happens to our subview will be handled correctly, because in the xib we say which class will be handling its actions. How can we achieve this on android? Since we don't have that kind of relation between an .xml layout and a class that uses it, how can we achieve something like that?
The main purpose is, for example: while having one common header and one common footer for the entire application, we just want to add different views to "content View" between the header and footer.
You you can use the layout "include" functionality. This allows you to create a layout file for your header and one for your footer, and then include these layouts into your Activity's main layout. And if you want to include the header + footer in multiple activities and these layouts have some events you want to handle, you could create a BaseActivity that handles these events, and then have your other Activities extend the BaseActivity.
Example pseudocode:
title.xml
<LinearLayout><ImageView/><TextView/></LinearLayout>
footer.xml
<LinearLayout><TextView/><TextView/></LinearLayout>
main.xml
<RelativeLayout>
<include layout="#layout/title"/>
<WebView />
<include layout="#layout/footer"/>
</RelativeLayout>
Related
In my Android app I have a layout for an activity that presents a choice.
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/wrapper"
android:orientation="vertical">
<include layout="#layout/choices" />
<include layout="#layout/choice_one" />
<include layout="#layout/choice_two" />
</LinearLayout>
In layout/choices the user sees two buttons. One button shows layout/choice_one and the other shows layout/choice_two. (The parent in layout/choice_one and layout/choice_two is initially set to android:visibility=gone.)
So when a user chooses either choice_one or choice_two, essentially I'm setting the visibility to VISIBLE. That works great.
The issue is that inside of both choice_one and choice_two I have shared elements with the same ID. For example I have a TextView with ID header. (I did this because I figured only one of those layouts would be visible and they use the same things.)
The issue is that I use Butterknife, and it seems like if I Bind header, when I set the visibility on choice_one or choice_two, I have a 50/50 chance of correctly calling header.setText("Blah") on the appropriate header element.
I'm sure I can get around this by giving unique IDs to all elements in the layouts or ditching Butterknife and using findViewById instead. But is there another way I can target a shared ID inside of a layout without ditching Butterknife or my shared layouts?
I figured this out. (Writing it out helped, so I'll keep it here in case someone else stumbles upon it.) Instead of using include in xml and inflating layouts there, I just subclassed ViewGroup for my two layouts and added them to wrapper:
ChoiceOne choiceOne = new ChoiceOne();
wrapper.addView(choiceOne);
Is there an easy way to switch between the displayed view in a ViewSwitcher in the Android Studio preview, or is the only way to swap out the XML for the sub-views one at a time?
Unfortunately, there are no XML attributes or any option on Android Studio which can help you to define the displayed view.
A similar question for the ViewFlipper was asked here (they both are direct subclasses of ViewAnimator).
However, if and only if your views are large as the screen, you could use the include tag, for example:
<ViewSwitcher
android:id="#+id/myViewSwitcher"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include
layout="#layout/first_view">
</include>
<include
layout="#layout/second_view">
</include>
</ViewSwitcher>
Then you can see your layouts in a separate XML file.
First of all if you are thinking to use ViewSwitcher, just for showing ProgressDialog then you are not doing it in a way in which it should be.
ViewSwitcher generally used to change layout of Activity. In your case ProgressDialog is not a View of your Activity rather it is just small helper which indicates some process is doing. So In short ViewSwitcher should be use somewhere where you want to alter complete screen of Activity.
In your case you can divide your layout into smaller layout files and group them using merge or include.
Create separate files for all different screens which will define UI of your Activity and group them using include.
For an example we can create small App for Introduction thing using ViewSwitcher -
First Screen - my_product.xml - this layout will define something about product.
Second Screen - about_us.xml - this layout will describe about your company.
Third Screen - thank_you.xml - to say thank you to your users.
Group them in any container View.
<ViewSwitcher
android:layout_width="match_parent"
android:layout_height="match_parent">
<include
layout="#layout/my_product"/>
<include
layout="#layout/about_us"/>
<include
layout="#layout/thank_you"/>
</ViewSwitcher>
ViewPager can easily solve your issues.
ViewPager (it can hold multiple views). ViewPager is kind of Array Container for View objects. You can have ViewPager rotation (like you do the array rotation) or other techniques to swap inside views. And, you can create your each inside views based on the Factory DP, so that there happens less processing (shares common resources).
They have mentioned swiping views here (Note: you just need own view swiping techniques if you don't want to use default ViewPager rotation).
Creating swipes: https://developer.android.com/training/implementing-navigation/lateral.html
ViewPager for screen slides: https://developer.android.com/training/animation/screen-slide.html
Is it possible to inflate a LinearLayout from XML that contains some static objects and another LinearLayout and later when "XML" code is used inside the LinearLayout it's content is being added inside the inner LinearLayout.
Explanation with some code removed:
<LinearLayout id="main">
<LinearLayout id="top">
<TextView text="This is always here" />
<ImageView src="#drawable/image_alwayshere" />
</LinearLayout>
<LinearLayout id="bottom">
</LinearLayout>
</LinearLayout>
This is then inflated by my View "CustomLinearLayout" or whatever we call it
and when using the View in another Layout:
<com.my.views.CustomLinearLayout>
<ImageButton id="button1" src="#drawable/button1" />
</com.my.views.CustomLinearLayout>
In this case, the ImageButton should not be added below "bottom" it should be added into it. SO whatever I have in top, stays static and whatever I want to change is added to the Bottom LinearLayout.
Is this possible and if it is how could it be done?
Not sure if it's good or bad practice, if it would work. But if I have a constant layout (top container, middle container and bottom container) and I have 10 different activities and the only one changing content is the middle one, I can easily make one change to the top and bottom container at one place instead of 10 places and have whatever "View" I want to show in my activity be added inside.
Maybe I need to create a whole new ViewGroup for this? But currently working on LinearLayout since it's functionality is pretty much what I need.
If not, then what I'm looking for is where and when a LinearLayout reads the content of the XML and then override that to be added to my inner LinearLayout instead.
It is possible, you can either use include tag to add the other xml layout into the "bottom" layout and make its visibility as "gone" and change it to "visible" when you need it.
Or you can do that dynamically and inflate the xml whenever you want then add it to "bottom" using ViewGroup.addView(View) method.
I am developing an applications that is aimed at Tablets and Google TVs. It will be like many standard Google TV applications with a LeftNavBar and a top Search bar that is common to all application screens. It will look something like the following image:
Main Screen
The RED area will be different for all other screens. It may contain data like following screens mockups:
Activity One loaded into main container
Activity Two loaded into main container
So you can see that completely different sections can be loaded in the main area.
Screen 3 can be loaded as a detailed section when selecting any list item in Screen 2 (say in fragment list) OR it can be loaded as a result of selecting a tab (which will appear in LeftNavBar).
Here is how I am trying to implement it.
Step 1. I Created a main Activity with the following 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" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#9ccc" >
<!-- Top Bar -->
</LinearLayout>
<FrameLayout
android:id="#+id/mainContainer"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<!-- main Red Container that will load other Activities -->
</FrameLayout>
</LinearLayout>
mainContainer is the RED container where I want to load the Activities. LeftNavBar will be added to this Activity as its the parent of All.
Step 2 I created ActivityOne & ActivityTwo with two & three Fragments in them respectively (as shown in above second & third image).
*Step 3 I am trying to load the ActivityOne in main page's mainContainer FrameLayout... But I cannot add it.
I tried by adding the ActivityOne to mainContainer as follows:
View v = (new ActivityOne()).getWindow().getDecorView();
FrameLayout mainContainer = (FrameLayout) findViewById(R.id.mainContainer);
mainContainer.addView(v);
but the getWindow() returns null....
Other issue occurs because all the data comes from a remote services .. so please also suggest how would I be able to hold references to all the loaded Activities in mainContainer in a some kind of stack ... so I can just reload the already loaded activity instead of creating its new instance.. This will be used on BACK button press.
OR
Instead of loading an activity into the above RED container, I should create two Activities each with their own Fragments & a LeftNavBar. This might be easier than the aforementioned approach. or this might be the only solution.... however I feel that saving state for BACK buttons might get messy .. but I will try implementing this
What would you do if you had to create this type of application?
How would you design the UI layout for best performance/practice?
Your suggestions in helping me setting this app's layout are much appreciated.
Disclaimer
This is where fragments can get tricky. The problem would be simple if Activity 1 & 2 had identical layouts so that you could simply attach/detach fragments and use the fragment back stack to unwind.
Because you want 2 unique layouts to house your fragments, things are going to be a little more involved. If at all possible I would try to use the same layout so that you can take the easy path.
As another option, you could use two activities as you outline above and send data back and forth with Intents.
That said, if I really had to implement this solution as written, here is what I would do. Note that I am not advocating this solution but myself do not know of a better way of doing things.
The Solution
Create a FragmentActivity whose view would be Main Screen as you've defined above. The layout for the Main Screen would contain:
Left nav bar
Top bar
2 layouts. layout1 and layout2. These would be contained in a parent layout i.e. RelativeLayout or LinearLayout and would contain the necessary FrameLayout elements for your fragments.
Example using your XML (note, tags are a bit brief):
<?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" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#9ccc" >
<!-- Top Bar -->
</LinearLayout>
<LinearLayout android:id="#+id/layout1">
<FrameLayout android:id="#+id/listFragment" />
<FrameLayout android:id="#+id/contentFragment" />
</LinearLayout>
<LinearLayout android:id="#+id/layout2">
<FrameLayout android:id="#+id/imageFragment" />
<FrameLayout android:id="#+id/boxFragment1" />
<FrameLayout android:id="#+id/boxFragment2" />
<FrameLayout android:id="#+id/boxFragment3" />
</LinearLayout>
</LinearLayout>
The main idea is that you then show/hide layout1 & layout2 i.e. set android:visibility="gone" based on the state of your app.
The disadvantages of this method are:
Using fragment backstack may be impossible, instead you'll have to track where the user is in your UI flow and manage the back button to show/hide layout
You may need to take special care to attach/detach fragments when you show/hide their parent view to reduce resource consumption while the fragments are invisible
The advantages are:
Easy communication between fragments and the base activity since only 1 activity is used
Re: The nested Fragments problem
To get around the 'nested Fragments' problem in our application where (as you correctly note) Fragments cannot add Fragments I hosted a single templating Fragment under the activity whose only purpose was to define a set of place holders for other fragments to anchor to. When adding further Fragments to the activity past this point I used the templating Fragment's view place holder +#ids to identify the "root" or parent view Id for the Fragment being added.
getSupportFragmentManager().beginTransaction().add(#someIdFromTheTemplateFrag, fragment, fragmentTag).commit();
The Fragment I was adding then knew where to anchor itself in the current layout and of course then went about it's merry way of add it's view. This had the effect of attaching a Fragment to another Fragment hence achieving the desired visual 'nesting'...
I Have simple question, i Have some linear layout with buttons on it.
how can I make this linear layout share to all my application layouts without copy it to the beginning of each layout.
I mean that any xml layout will start from the same LinearLayout, and will share the same references , like browser bar but when I launch to another Activity it's still visible.
Thank's guys
Use the include tag in each of your layouts
<include android:id="#+id/layout_id" layout="#layout/my_layout" />
see this blog post http://www.curious-creature.org/2009/02/25/android-layout-trick-2-include-to-reuse/