Android: Instantiating Multiple Widgets From One Layout Declaration - android

I am creating a custom widget to display a rotating list of items. I have declared the layout in newsview.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android:id="#+id/tblLink"
style="#style/newsviewstyle"
android:layout_alignParentBottom="true">
<ImageView
android:id="#+id/newsviewimg"
style="#style/newsviewimgstyle"
android:layout_margin="5dp" />
<TextView
android:id="#+id/newsviewtitle"
android:layout_toRightOf="#id/newsviewimg"
android:layout_marginTop="5dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="5dp"
android:layout_width="fill_parent"
android:layout_height="50dp"
android:textColor="#000000" />
<TextView
android:id="#+id/newsviewurl"
android:layout_toRightOf="#id/newsviewimg"
android:layout_below="#id/newsviewtitle"
android:layout_marginTop="5dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="5dp"
android:layout_width="fill_parent"
android:layout_height="15dp"
android:textColor="#000000" />
</RelativeLayout>
The idea is in my main.xml, I have a ViewFlipper that I would like to use animate the transitions between each item. How could I instantiate "n" unique items declared above, so they can bee added to the ViewFlipper. How would I be able to get access to the layout declared from a class outside the main activity (and also outside the package containing the main application, i.e. a view controller).
As a note, collecting the list of items takes place in a controller outside the main activity of my application. I would like to keep everything as much as possible in the controller for possible reuse later on.

How could I instantiate "n" unique items declared above, so they can bee added to the ViewFlipper.
Use getLayoutInflater().inflate(), the same way you would in a custom Adapter. In fact, on Honeycomb, there is AdapterViewFlipper to handle this very scenario.
How would I be able to get access to the layout declared from a class outside the main activity (and also outside the package containing the main application, i.e. a view controller).
I'm sorry, but this sentence did not parse for me.

Related

Reuse a group of buttons across several fragments

I have a fragment defined by the following xml file:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fragment_example"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_example"/>
</RelativeLayout>
Now I would like to reuse the ImageButton (and other buttons I will add) in another fragment, ideally
without copying its definition
by keeping the definition in xml and not adding it programmatically
I.e. the goal is to overlay the same set of buttons in different fragments.
Is there a way to define all buttons in a separate xml file and load them programmatically on fragment creation?
Yes, You can.
Define all buttons in different xml say layout_buttons.xml
and add them in each fragment layout using
<include layout="#layout/layout_buttons" />

Can my layout be improved for efficiency?

I have a layout as shown below. It is inflated by code and added to a HorizontalScrollView, sometimes a few hundred times, and causing getting memory issues.
I'm wondering if there's anything that can be done to make it more efficient? Originally I used LinearLayouts, and replacing that with RelativeLayout made a huge difference to the scrolling. Now I'm wondering if it can be further improved?
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="156dp"
android:layout_height="254dp"
android:paddingLeft="7dip"
android:paddingRight="7dip">
<FrameLayout android:id="#+id/button_frame"
android:layout_width="156dp"
android:layout_height="218dp">
<ImageView android:id="#+id/button_bg"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/image_bg"
/>
<ImageView android:id="#+id/button_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="bottom|right"
/>
<TextView android:id="#+id/button_select"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="2dip"
android:layout_marginRight="2dip"
android:background="#drawable/btn_selector_bg_selected"
/>
<TextView android:id="#+id/button_selected"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_marginLeft="2dip"
android:layout_marginRight="2dip"
android:background="#drawable/title_bg_selected"/>
</FrameLayout>
<TextView
android:id="#+id/button_title"
android:layout_width="156dp"
android:layout_height="36dp"
android:textColor="#ffffff"
android:singleLine="true"
android:textSize="13sp"
android:textStyle="bold"
android:gravity="center_vertical|left"
android:ellipsize="end"
android:paddingLeft="30dip"
android:paddingRight="5dip"
android:layout_below="#id/button_frame"
android:background="#drawable/title_bg"/>
</RelativeLayout>
The ImageView button_image is populated using AQuery image caching, so I'm not sure if there's much more I can do to improve the way the image is handled. But any tips on improvements greatly appreciated.
In general, a good way to optimize layouts in Android is to minimize the amount of nesting of containers within each other. The deeper you nest layout containers, the more work the framework must do to measure, layout, and process events for the view hierarchy.
But I think you may be asking the wrong question.
The HorizontalScrollView and VerticalScollView are not intended for the use you're putting them to. They're meant to hold a mostly static layout, and allow it to scroll if necessary depending upon the size of the screen it happens to be running on.
You want a repetitive list of mostly identical Views, that the user can scroll. The correct Android view container to use is ListView, or one of the other descendants of AdapterView.
ListView is careful only to create/inflate the necessary child views to fill the space on screen, and reuse them as the user scrolls. This solves the memory problems you're experiencing. It does that by requiring you to pair it up with an Adapter - an object that wraps the actual data being displayed, and creates on-demand the correct view for a given data item.
Since you're trying to do horizontal scrolling, you might also look at Gallery (now deprecated in Android) or the newer ViewPager class, both of which support horizontal movement through a large list of data.
If you can use a ListView instead of a HorizontalScrollView, you could create an Array Adapter that uses the viewHolder pattern which essentially allows you to re-use views per item in your list view. Take a look at this for more details: http://www.jmanzano.es/blog/?p=166

Basic design needed

i am targeting an app on android 2.1. i am having a layout which contains three sections. the header, mainbody and the footer. the footer remains same all through the application lifecycle. the footer has four options for the user to select(like four tabs). when the user selects each option in the footer the content has to change in the mainbody. and when the user interacts with the UI in the mainbody, there is a need to change the content of just the mainbody(like activity replacing an activity). and the user selection in the footer has to remain highlighted untill user selects another option in the footer.i alomost have a need like, launching activities within the same tab, but the tabs are placed below. a lot of people have suggested using activitygroup but as it is deprecated how do i go about doing this?. if anybody needs more clarity about question i am ready to provide
If you want support from lower versions like 2.1 and higher I can propose my way. I always use separate XML layout for tray (footer in your case), for example (res/layout/tray.xml):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/mainMenu"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="#EEEEEE"
android:gravity="bottom|fill_horizontal"
android:orientation="horizontal"
android:padding="5dp" >
<ImageView
android:id="#+id/addBtn"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="#drawable/add" android:layout_weight="0.2"/>
<ImageView
android:id="#+id/catalogBtn"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="#drawable/catalog" android:layout_weight="0.2"/>
<ImageView
android:id="#+id/searchBtn"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="#drawable/search" android:layout_weight="0.2"/>
<ImageView
android:id="#+id/settingsBtn"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="#drawable/settings" android:layout_weight="0.2"/>
<ImageView
android:id="#+id/infoBtn"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="#drawable/info" android:layout_weight="0.2"/>
</LinearLayout>
And includes it in every Activity I need:
<include layout="#layout/tray" android:id="#+id/tray" />
After that I can in java code hide/show some buttons in tray by ID, or select some of them with another color ...
To display the footer menu across all activities, you may create a custom layout - the layout of the footer - and include it in every activity, or to be more specific, include it in the layout of every activity with <include />
Also, all your activities should have a parent activity, let it be BaseActivity, where you will provide appropriate actions for you footer menu.
Then you will need just to inherit the BaseActivity and include the footer menu layout, into your current layout, to have the menu available for any Activity you would like.
Another possible approach is using fragments instead of a full activity per content page. Fragments are a lot like activities, except that they need to be embedded in an activity to be displayed and they give you the freedom to change the content of one part of an activity (that is, swapping one fragment for another), meaning you can have another part of the activity remain unchanged - for instance tabs for switching between these fragments. A nice bonus is that reusing that content page in another activity is very easy, and should you choose create a tablet-friendly version you can easily compose more complex views of your existing fragments.
Using a ViewPager together with some type of page indicator, such as the tab indicator here you can have an active fragment and easily switch between them.
Since you are targeting 2.1 you will need to use the android support library to support fragments.

how to capture events from dynamically added layouts in Android

In my android project, I need to add controls dynamically into my main activity screen. I created one xml (row.xml) which is added on button click on main screen. I want to capture events from the controls (button) given in row.xml.
Can anybody help me where and how to capture onClick events from newly added layouts?
Also, I want to add many child layout elements, do I need to write separate onClick methods for all the child views added dynamically?
row.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/layout_Time"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dip"
android:orientation="horizontal" >
<EditText
android:id="#+id/editText_FromTime"
android:layout_width="216dp"
android:layout_height="wrap_content"
android:focusableInTouchMode="false"
android:hint="#string/hintFromTime" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:orientation="horizontal" >
<Button
android:id="#+id/button_Delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/btnDelete" />
</LinearLayout>
</LinearLayout>
So, when I click on Add Time slot button, I get a newly created row with two elements.
I want to delete this row when I click on Delete button. Do I need to have a viewID also to delete this newly-added-view?
Create an onclicklistener in the list adapter and set it to the buttons in the getView method of the adapter. That should work.
You can keep track of your controls as Java variables - don't worry about dynamic android xml. Consider declaring them all at the top, outside of methods.
One way to avoid adding a new OnClickListener for each control is let your class implement OnClickListener then use view.setOnClickListener(this). Alternatively create a subclass which overrides onClick(View) and use setOnClickListener(MyListener).
You can use Layout.removeView(View) to remove controls, as long as you keep track of them.

How to share a view across various activities

Is there any way to share the same object of the View across various activities? For example myApp has 4 activities, and every activity shows a Logo at the top of the screen. Now each activity will initiate 4 copies of the same Logo. So is there any way to get around this? And if 3 out of 4 share the same logo?
I can't say that it is completely impossible for you to do that. What I can say with almost certainty is that you should not attempt it or expect anything good to happen if you do manage it. Don't fight the framework, let it work for you. If the duplication is that much of an issue you create an abstract class that your Activities inherit from.
Also, since View's maintain a reference to the Context they were created in. If you did manage to pass a View from one Activity to another you would be creating a memory leak. Since the View would hold a reference to the old Activity via the Context it was created in.
Use seperate layout to make your logo.
Ex: title.xml
<?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="wrap_content"
android:layout_alignParentTop="true"
android:background="#drawable/headercon" >
<ImageView
android:id="#+id/headerView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="centerInside"
android:src="#drawable/header" />
</LinearLayout>
This layout can be included in any other layout by using include tag
Ex:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
...
<include layout="#layout/title" />
...
</RelativeLayout>

Categories

Resources