Firstly I have a tabview with multiple activities, three of which are listviews.
I created the first one - equipment and that worked a treat. I then created the rest by cut/paste the files in eclipse and renaming the files and calling the new files.
Problem - Equipment has stopped scrolling.
Ive even reduced it to its component parts and removed the list prepopulation with a simply options1-5 but it still refuses to move up or down.
IN other windows, even if the list is not fully populated, the window can be grabbed and the contents will scroll up/down and when released will pop back to nromal view at the top of the screen.
Ive compared line by line and for the life of me cant figure out why this is not working.
Code below:
public class harpcsEquipment extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView (R.layout.tab_harp_equipment);
// Got the entire Equipment list and now we populate the Listview
String[] listitems = {"Option 1","Option 2","Option 3","Option 4","Option 5"};
ListView lv = (ListView) findViewById(R.id.list);
lv.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, listitems));
//#Override
protected void onResume()
{
super.onResume();
// NOW WE ADD DATA TO THE TEMPLATE
//populateXMLCharacter();
}
}
tab_harp_equipment.xml
<?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">
<ListView android:id="#+id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1" />
</LinearLayout>
the listview was called equiplist but changing to the default name made no difference...
Any help would be greatly appreciated!
Regards
Jason
I have a lot of code (in this and the cloned classes and the clones work but the parent does not...) I can copy paste the entire lot but since the only difference is the data that is being pasted and the number of fields I am displaying (thus different layout files called in the arrayadapter), but since the basic demo code above doesnt work, Im at a loss...
OK, better success here after much testing.
I have TWO icons on a home screen (think google plus icon screen if it helps).
Two icons open a tabhost each - there are 8 tabs and fitting them all on one tab is just messy.
All tabs on the first tabhost work. Listviews scroll in them.
All listviews on the second tab do NOT work.
Copying the text:
intentE = new Intent().setClass (this, harpcsEquipment.class);
specE = tabHostE.newTabSpec("Equipment").setIndicator("Equipment",
res.getDrawable(R.drawable.shield)).setContent(intentE);
tabHostE.addTab(specE);
from one tabActivity to the next works fine - the equipment listview opens and scrolls.
So the problem is the tabActivity.
Does anyone know why a second tabactivity will not allow a listview to scroll inside it?
OK, Resolved.
TabActivity has a flaw/undocumented feature/etc.
It wont allow you to get full functionality form a second TabActivity inside a program.
So in the calling java program, when I use the intent to call the program that creates the tabhost, I simply putExtra("tab", "1") or putExtra("tab", "2").
Inside the program I simply get the Extra and if tab==1 then load tabhost with one set of Tabhosts intents, and else load it with another set of tabhosts intents.
Damn tabactivity... Whoda thunk it huh?
Hope this helps someone else in the future.
Related
I am having a somewhat weird scenario building the UI for an Android application. Although I got to solve the error, I don't know the cause and I would like to understand why this is happening in order learn more about Android. I reproduced the scenario in a simple application:
Creating a new Hello World Android application adding this resources file under res/layout/footer_view.xml:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="Foo Bar" />
And using this Activity:
public class MainActivity extends ListActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(android.R.layout.list_content);
ListAdapter adapter = new ArrayAdapter(this, android.R.layout.activity_list_item);
setListAdapter(adapter);
View footer = LayoutInflater.from(this).inflate(R.layout.footer_view, getListView(), false);
getListView().addFooterView(footer);
}
}
We get the following screen:
To my surprise I saw that the footer view, which is a TextView saying "Foo Bar", was missing. After some playing around I found out the solution was to move the "setListAdapter(adapter);" line to the end of the onCreate() method, or said differently, after adding the footer to the view.
Exploring a little further I found out the problem is the width, which is 0 if I have the adapter added before. Another solution was to indicate an explicit width other than match_parent.
Any clue why this happens? For me it'd be more intuitive that it didn't work if the adapter hadn't been added because the list may not be ready, but why would it not work if everything is prepared?
The reason is that internally, if there are headers or footers, the adapter is wrapped inside another adapter.
So if you call setAdapter before adding the header and footer views, then the wrapping adapter is not aware of them.
If you leave setAdapter to the end, then the adapter that wraps your adapter knows about the headers/footers since those have already been added to the list.
See the documentation:
Add a fixed view to appear at the bottom of the list. If addFooterView
is called more than once, the views will appear in the order they were
added. Views added using this call can take focus if they want.
Note: When first introduced, this method could only be called before
setting the adapter with setAdapter(ListAdapter). Starting with
KITKAT, this method may be called at any time. If the ListView's
adapter does not extend HeaderViewListAdapter, it will be wrapped with
a supporting instance of WrapperListAdapter.
My goal is to create an Android UI window that displays three regions: navigation, main, and popup. The navigation and main region will function as a split view. The popup region will be centered in the screen and overlay the other two regions; it will also only be visible part of the time. Ideally, I'd like these regions to host fragments that are dynamically changed to display different layouts and view models based on user interaction. And, all of this should be accomplished without breaking the MvvmCross bindings.
I've got something that works, but it feels a bit hacked together. The current implementation most closely follows resource 1 below. Each region has a dictionary. All of the fragments are registered with a dictionary based on their target region. This is done from the activity. The activity also takes care of inflating each layout and associating it with the correct view model. I’d like to change this so that MvvmCross can do more of the work.
Is it possible to create a custom presenter, in Android, that is a mix between the dynamic fragment layout from resource 2 and the iOS custom presenter shown in resource 3? Just to clarify, I want to specifically define where each region will be displayed using a layout. Then I want to dynamically fill the content, of each region, with different layouts and their associated view models, at runtime.
Resource 1: MvvmCross v3 Fragment Sample
https://github.com/slodge/MvvmCross-Tutorials/tree/master/Fragments
See: “FragmentSample.UI.Droid/Views/TitlesView.cs” and “FragmentSample.UI.Droid/Setup.cs”
Resource 2: N=26 - Androids… down at Fragment Rock
http://www.youtube.com/watch?feature=player_embedded&v=uQT3_WXQQr0
Dynamic Fragment Layout created explained at 26:25 – 32:10
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<FrameLayout
android:id="#+id/subframe1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<FrameLayout
android:id="#+id/dubframe1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>
(In addition to being an extremely helpful video, of all the N+1 videos I've had a chance to watch, this one has the best intro!)
Resource 3: N=24 - Split View
http://www.youtube.com/watch?feature=player_embedded&v=PpeysFIINcY
iOS SplitPresenter created at 11:25 – 15:05
public class SplitViewController : UISplitViewController
{
public SplitViewController()
{
this.ViewControllers = new UIViewController[]
{
new UIViewController(),
new UIViewController(),
};
}
public void SetLeft(UIViewController left)
{
this.ViewControllers = new UIViewController[]
{
left,
this.ViewControllers[1]
};
}
public void SetRight(UIViewController right)
{
this.ViewControllers = new UIViewController[]
{
this.ViewControllers[0],
right,
};
}
}
I created a small example project on GitHub that demonstrates how to create multiple regions.
This shows the three regions: Navigation, Main and Popup. The location, size and shape of each region is defined in one layout file. The content is defined, with separate layout files and view models, for each region and is dynamically changed at runtime. MvvmCross bindings still work with each individual view model.
EDIT
I added a more robust solution example on github. This allows the ViewModel to be opened in the standard way. The MultiRegionPresenter handles matching up the view with the correct region by looking at a tag in the view. Views are now tagged with their intended region like this: [Region(Resource.Id.MainRegion)].
The new example project is located here: MultiRegionPresenter Example
want to make an Android app that starts with a main layout and when you push a button (called stateButton) that is in this layout the layout changes to a main2 layout containing another button (called boton2), and when you push this one you get back to the first main.
I want to do this in the same activity without creating or starting another one.
Here I show you part of the code:
public class NuevoshActivity extends Activity
implements SensorEventListener, OnClickListener {
private Button stateButton;
private Button boton2;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
this.stateButton = (Button) this.findViewById(R.id.boton);
this.boton2 = (Button) this.findViewById(R.id.boton2);
stateButton.setOnClickListener(this);
boton2.setOnClickListener(this);
}
#Override
public void onClick(View v) {
if(v==stateButton) {
setContentView(R.layout.main2);
}
else if(v==boton2) {
setContentView(R.layout.main);
}
}
}
The mains only have some images, text views and the buttons.
But I've some troubles. Can't it just be as simple as that or what am I missing or what is wrong?
When you use findViewById, you are actually trying to find a view inside the layout you specified by the setContentView. So using setContentView again and again might bring problems when you are trying to check for buttons.
Instead of using a setContentView, I would add the 2 layouts for the screen as child's for a view-flipper which only shows one child at a time. And you can specify the index of which child to show. The benefit of using a view flipper is that you can easily specify a 'in' and 'out' animation for the view if you need an animation when you switch between views. This is a lot cleaner method then recalling setContentView again and again.
The FrameLayout handles this wonderfully... Use this with the <include... contstruct to load multiple other layouts, then you can switch back and forth between them by using setvisibility(View.VISIBLE); and setVisibility(View.INVISIBLE); on the individual layouts.
For example:
Main XML including two other layouts:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout android:id="#+id/frameLayout1" android:layout_width="fill_parent" android:layout_height="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android">
<include android:id="#+id/buildinvoice_step1_layout" layout="#layout/buildinvoice_step1" android:layout_width="fill_parent" android:layout_height="fill_parent"></include>
<include android:id="#+id/buildinvoice_step2_layout" android:layout_width="fill_parent" layout="#layout/buildinvoice_step2" android:layout_height="fill_parent"></include>
</FrameLayout>
Code to switch between layouts:
findViewById(R.id.buildinvoice_step1_layout).setVisibility(View.VISIBLE);
findViewById(R.id.buildinvoice_step2_layout).setVisibility(View.INVISIBLE);
You will also need to set the visibility of the individual layouts when the activity starts (or in XML) otherwise you will see them both - one on top of the other.
Your boton2 button will be NULL because the definition of the button is in main2.xml.
The only views you will be able to find are the views which are defined in main.xml.
Thanks!!! All the info was usefull to understand a lot of things and as C0deAttack commented I've got troubles with the button on the main2. What I've done is to set View.VISIBLE and View.GONE to the TextViews and Buttons that I wanted in each layout. Thank you very much.
I've been grappling with this problem throughout the life of my project. I have many lists in my project and most of them have headers. I have been making a separate layout file and adding it to the list using addHeaderView(). The problem is that when the data (ArrayList, in my case) is empty, the header doesn't appear. After hours of searching for a way to reuse the header layout as an empty view, I gave up and decided to replicate the layout in code and assign it as an empty view using setEmptyView(). The problem with this is that a lot of the headers contain clickable views and so I have to double all of my clickable logic for every view that is duplicated. I tried to include the header before but failed, mostly because I still don't quite understand how layouts are inflated, etc.
Finally, I have come up with a solution that I would like to share with the community, in case others are having a similar problem. I don't know if this is the best way to solve this problem and any feedback or suggestions would definitely be welcomed.
here is the code for the layout that contains the list list view:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
>
<ListView
android:id="#+id/lv_my_list"
style="#style/ListStyle"
android:headerDividersEnabled="false"
/>
<include
layout="#layout/my_list_header"
android:id="#+id/my_list_empty"
/>
</LinearLayout>
the style defines the layout width and height among other things.
now I have the layout file that contains the header view
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:id="#+id/my_list_header"
>
<Button
android:id="#+id/my_list_button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Click Me"
/>
</LinearLayout>
I know LinearLayout is not very efficient and I am experimenting with using merge or other efficiency measures, but this is the first version that works so I'm going with it for now. Finally the code:
// set up the header
myListView = (ListView)findViewById(R.id.lv_my_list);
View header = View.inflate(this, R.layout.my_list_header, null);
Button b = (Button)header.findViewById(R.id.my_list_button);
b.setOnClickListener(this);
myListView.addHeaderView(header);
// set up the empty view
LinearLayout ll = (LinearLayout)findViewById(R.id.my_list_empty);
b = (Button)ll.findViewById(R.id.my_list_button);
b.setOnClickListener(this);
meLocalListView.setEmptyView(ll);
The reason I wrapped the button in a layout is because I can set each instance of the button to use this as an OnClickListener and then refer to both of them with a single id: R.id.my_list_button in my onClick method. I need to test this a lot more but it seems to work for now. I haven't implemented it on all my lists yet, just the one so it might not work in all situations. If you have any suggestions please let me know because this has been a problem for me for a long time now. One problem might be that if you want to instantiate the button from the ID you would probably have to go through this entire process again to access the correct IDs?
If you want to show the header of a ListView when the list is empty, what you really want to do is to show the list itself rather than a separate empty view. So, the simplest way is to check whether your list is empty and set the list visible if it is not already:
getListView().setVisibility(View.VISIBLE);
You can test this very easily with the following code:
public class TestListActivity extends ListActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test_listview);
// create the empty grid item mapping
String[] from = new String[] {};
int[] to = new int[] {};
// prepare the empty list
List<HashMap<String, String>> fillMaps = new ArrayList<HashMap<String, String>>();
// fill in the grid_item layout
SimpleAdapter adapter = new SimpleAdapter(this, fillMaps, R.layout.test_listitem, from, to);
View listHeader =
((LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE))
.inflate(R.layout.test_listheader, null, false);
getListView().addHeaderView(listHeader);
getListView().setAdapter(adapter);
}
}
The list is empty, but the header is visible.
My solution is to create a view with the layout for the header, but set the background to be the same as the list items.
android:background="#android:drawable/list_selector_background"
But my solution does not work if I use 'include' to embed the header layout from another layout file. Do not know why.
I'm new to android,I'm using tabHost adding some tabs to it,its working quite fine but when i rotate my device in landscape mode it also work there fine but i don't need tab bar there because it covers much space and i also have google ads so both of them cover half of the screen and leave a little space for user to interact.All i need is a solution to somehow hide tab bar just like we can do it in iphone to make a bit room for user to interact.I need some solution urgent.Thanks
I think you should wrap your tab widget in any ViewGroup such as LinearLayout or RelativeLayout, and create a static function in your tabActivity to show/hide this wrapper, Here's a little code might be helpful for you.
<LinearLayout
android:id="#+id/popupTabs"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:visibility="gone">
<TabWidget android:id="#android:id/tabs"
android:layout_height="wrap_content"
android:layout_width="fill_parent"></TabWidget>
</LinearLayout>
Now your tab activity should do something like this.
public class TabsView extends TabActivity {
public static LinearLayout popupTabs ;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
popupTabs = (LinearLayout) findViewById(R.id.popupTabs);
// Your other code
//............
//............
}
// Show Tabs method
public static void showTabs(){
popupTabs.setVisibility(ViewGroup.VISIBLE);
}
// Hide Tabs method
public static void hideTabs(){
popupTabs.setVisibility(ViewGroup.GONE);
}
}
Now you can call this method statically from any location in your code like this
// hide tab from any activity
TabsView.showTabs();
// hide tab from any activity
TabsView.hideTabs()
For Hide
mTabHost.getTabWidget().setVisibility(View.GONE);
For Visible
mTabHost.getTabWidget().setVisibility(View.VISIBLE);
The simplest way would be to create a second version of your layout.xml file which doesn't include the TabHost and put it in a resource folder named 'layout-land' (the 'land' suffix is short for 'landscape'). Please see this SDK article for more information.
Apart from doing what Reuben is telling you would be to animate the transition between both so that the change would be a bit smoother.