I have list of conversations, and messenger UI.. what I want is: When an item of the list of conversations clicked, the messenger UI appear with that specific conversation messages..
my attempt: Until now I haven't code this part, I just look for an idea,is it good Idea to save each message immediately to DB, and when I navigate between the conversations I drop the appropriate messages?
Recently I've been working in something similar. For achieving this I've used a TabHost, with a FrameLayout associated to each one that might be converted to a TextView, which is what I suppose you want.
This approach has a handicap: You can access just to the currently opened tab's view (in this case, a TextView). If you don't plan to add text to an inactive tab, you don't need to do anything further as TabHost handles each tab's previous messages. But for instance, if you want to add messages to an inactive tab, you have to store them first in a queue and once the tab is activated, process them with an OnTabChangedListener event.
That's my definition for the TabHost structure:
<LinearLayout xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" >
<LinearLayout
android:id="#+id/TabContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="99"
android:orientation="vertical">
<TabHost
android:id="#+android:id/tabhost"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="#+id/TabLinearLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!-- This makes your TabHost horizontally scrollable if it reaches a certain number of tabs -->
<HorizontalScrollView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:fillViewport="true"
android:scrollbars="none">
<TabWidget
android:id="#+android:id/tabs"
android:layout_width="wrap_content"
android:layout_height="wrap_content"></TabWidget>
</HorizontalScrollView>
<!-- You may also want to make this FrameLayour vertically scrollable -->
<FrameLayout
android:id="#+android:id/tabcontent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="10dp"></FrameLayout>
</LinearLayout>
</TabHost>
</LinearLayout>
If you need to process events on a tabchange, you should have something like this:
final TabHost th = (TabHost) (this.findViewById(android.R.id.tabhost));
th.setOnTabChangedListener(new OnTabChangeListener() {
#Override
public void onTabChanged(final String tabId) {
// Here you do the stuff you need. tabId is the name (also called Indicator) of the activated tab
}
});
You should also be aware of controlling the buffer of each tab. That is, control that each tab doesn't have more than X messages, as if it grows without control your app may start being irresponsive.
These links might help you as they did to me when I was programming this part:
https://gist.github.com/jerolimov/618086
http://androidituts.com/android-tab-layout-example/
http://learnandroideasily.blogspot.com.es/2013/07/android-tabwidget-example.html
I guess saving convs in DB isn't a good idea. You should serialize the data or should you use files to save'em.? Or rather, you can use delimiters to have a random access.
Related
I want to display two different activities in a single screen how can i do that in android?Please if anybody has idea share it.And I don't wanna use fragments.
I want to display a screen which contains some fields and below(at the bottom of the screen) I want another screen with some buttons.
Is this possible in android?
If so, How can i do this ?
You can't have two activities in one screen. You can have only one. So, ultimate solution is Fragments.
An activity is not directly a visual component, so I'm thinking that what you're really asking is how to have a single activity display different views.
There's nothing that says you can't rerun setContentView() with a different layout/view ID. But there's another non-fragments way of doing what your probably want.
You can define more than one full-size (match_parent) view in a layout. What you want to do is set the visibility for one of them to "visible" with android:visibility="visible" and all the others to "gone" with android:visibility="gone".
Then when you want to switch the displayed view, you'll run setVisibility(View.GONE) on the outgoing view and setVisibility(View.VISIBLE) on the incoming. It's important to use GONE and not INVISIBLE or the layouts won't render correctly.
Sample layout file:
<FrameLayout 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"
tools:context=".MainActivity" >
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:id="#+id/img"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="visible" />
<SurfaceView
android:id="#+id/video"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" />
<WebView
android:id="#+id/web"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" />
</FrameLayout>
Sample Code to switch view:
video.setVisibility(View.VISIBLE);
img.setVisibility(View.GONE);
web.setVisibility(View.GONE);
That said, you probably want to learn how to use fragments since you can handle switching the view along with other state in a single unit of work (a transaction). But the above approach above does work for simple view changes.
I would like to know if its possible to have different tabs on the top and bottom that lead to different activities when clicked. Googled it but didnt find anything about it.
Thanks
The good thing with Android is that almost everything you want to do should be possible. If we were to alter your XML we would change it to something like:
<?xml version="1.0" encoding="utf-8"?>
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#android:id/tabhost"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TabWidget
android:id="#android:id/tabs_top"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="0" />
<FrameLayout
android:id="#android:id/tabcontent"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1" />
<TabWidget
android:id="#android:id/tabs_bottom"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="0" />
</LinearLayout>
</TabHost>
Notice that I've changed the ID's of the TabWidgets.
This is only half of the problem. The other half is how the source code for the core class TabHost should altered to accommodate this change.
You can review the source of the original TabHost here. Looking at the source it's pretty obvious the code has a single mTabWidget and this is initialized using the very specific ID = tabs (com.android.internal.R.id.tabs). We've changed the ID's so we should be mindful of this.
So, how can we alter the original source? One approach is to make our own class and extend the core TabHost. This will not be easy because half of the functions and members inside the original TabHost are private (why aren't they protected?!?). Anyways, since you have the source code and it's pretty simple, it's possible to do it.
Let's say your new extended class is MyTabHost (potentially place it in the same package as the original TabHost just so you can access variables/functions which have no private or public), then you can replace in the XML the word TabHost with MyTabHost or com.yourpackage.MyTabHost actually) and then your class will be used in the XML instead of the original.
From looking at the source code, it's obvious that this feature isn't supported by default. But - I think that if you really want to make it happen, you can see a way.
I'm pretty new on android, i'm currently reading a lot of documentation to understand how to start. I've tried to search before asking here but i'm not able to find relevant information.
My problem is have 2 listview in the same acivity.
The Listview A with a list of category.
The Listview B with a details data (at startup the values showed are based on the category 1 of the listviewA)
When a click on a item of the listviewA the data of the listViewB change to reflect the new selection and show the new list of details data.
Can someone give me the right direction or a link to a tutorial that cover this topic ?
Sorry i'm not able to post any code at the moment.
I am not sure that the type of layout you are trying to make is user friendly. It would give the users far more richer UI experience if you change with an ExpandableListView. You can check out a tutorial here. Using this would give you the chances of engaging the user via an interaction.
Anyway, if you are sure to go with ListView then simply create a root LinearLayout and within this you take two ListViews. But taking the second one as a listview does not make sense. Rather, instead of making the second control a ListView, take a TextView to show the details.Provide the height of both layouts (ListView and TextView) according to your requirement.
Look at this tutorial
2 Listviews:
<LinearLayout android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="#+id/linearLayout1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:baselineAligned="false" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1" >
<ListView
android:id="#+id/listView1"
android:layout_width="fill_parent"
android:layout_height="fill_parent" android:visibility="visible">
</ListView>
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1" >
<ListView
android:id="#+id/listView2"
android:layout_width="fill_parent"
android:layout_height="fill_parent" android:visibility="visible">
</ListView>
</LinearLayout>
</LinearLayout>
1 ListView 1 TextView:
<LinearLayout android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="#+id/linearLayout1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:baselineAligned="false" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1" >
<ListView
android:id="#+id/listView1"
android:layout_width="fill_parent"
android:layout_height="fill_parent" android:visibility="visible">
</ListView>
</LinearLayout>
<TextView android:id="#+id/TextView1" android:text="details"/>
</LinearLayout>
UPDATE:
Please explain your problem a bit more. Because, in your scenario the data between the list views is connected with each other. Say, if ListView A is about Products so ListView B is about ProductDetails. So you need to declare a class variable say ProductID which is common entity between both data and set this variable setOnClickListener in ``getView()` of ListView A and fetch the data regarding this just after that and set the Adapter of ListView B with the results of this query (which may be to SQL db or RESTful server).
I have used this strategy before and it worked out well for me.
Use a linear layout to position the two list views, Populate the 'category' listview and set a list adaptor for it. On this listview I set an OnItemSelectedListener which when activated set ups the list-adaptor on the second 'detail' view.
Depending on your exact need you can either replace the detail listview's adapter or just change the content the adapter looks at and tell it to refresh.
Try this:
After get listview by id (list_A) set click listener
list_A.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
//here you can get click position from parameter position
// and do somthing in Adapter_B and then call notifyDataSetChanged() for Adapter_B
Adapter_B.notifyDataSetChanged();
}
});
Android does not have a support for section headers on ListView by default. Based from my research, I've learned that there are 2 ways to implement a section header on ListView. The first one is to support 2 types of views in the list view: the separator view and the content view. The second one is to include a separator view in all of the content views and just set the visibility of the separator view to either VISIBLE or GONE. I'm using the second method.
However, when I scroll the ListView upwards, the section header is also scrolled up. I know this is normal. But I want the section header to remain on top as long as some data belonging to its section are still being displayed. The behavior that I want to accomplish is similar to the behavior of the section headers of UITableView in iOS. How can I accomplish this?
Also, I would like to note that I've read that one solution for this is to create a view above the ListView and just change it if needed. However, this won't work for all phones. For example, the ListView on Samsung phones are bouncing. If I placed a view above the ListView to act as header and the ListView bounces, the dummy header view won't bounce together with the ListView. Also, the top of the default ListView can easily be spotted because it glows when the ListView is being scrolled. Is there anyway to accomplish the said effect while making sure that it still looks natural?
The picture below shows the problem that I will be encountering if I just add a textview on top of the listview: (Taken from Samsung Galaxy S2)
see in this xml + symbol is static u will get some help
<?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"
android:id="#+id/linearlayout">
<LinearLayout
android:id="#+id/linearLayout2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="#00ffff">
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/plus" />
</LinearLayout>
<ScrollView
android:id="#+id/scrollView1"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="#+id/linearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
</LinearLayout>
</ScrollView>
I am following this tutorial https://developer.android.com/guide/tutorials/views/hello-tabwidget.html and have completed it. Now I would actually like to add you know some controls to these tabs like textboxes(text edit).
How do I do this? I go to my mail.xml using eclipse as my ide and go to layout view and I now get a NullPointerException so I can't even drag stuff onto the layout anymore.
Edit
This is what I have
<?xml version="1.0" encoding="utf-8"?>
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#android:id/tabhost"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TabWidget
android:id="#android:id/tabs"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<FrameLayout
android:id="#android:id/tabcontent"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:id="#+id/textview1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="this is a tab" />
<EditText android:text="" android:id="#+id/EditText01" android:layout_width="wrap_content" android:layout_height="wrap_content" android:password="true"></EditText>
</LinearLayout>
<TextView
android:id="#+id/textview2"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="this is another tab" />
<TextView
android:id="#+id/textview3"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="this is a third tab" />
</FrameLayout>
</LinearLayout>
</TabHost>
Tabs are a bit funny to get working initially since there's a lot of code overhead, but once you've worked your way through that they aren't too bad. To get tabs to work, let's start by improving your XML file and then we can make sure your code to actually load them is correct.
First off, your XML file. Instead of including everything directly in your main.xml, you should use the include feature. As the name would suggest, this lets you work on a separate xml file and then include it in your main with one line. This makes the main.xml file much easier to read. So we'd modify your file above to make it look like this:
//No need to change anything above this
<FrameLayout
android:id="#android:id/tabcontent"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<include layout="#layout/tab1"/>
<include layout="#layout/tab2"/>
//and however many other tabs you want to include
</FrameLayout>
You then need to create tab1.xml, tab2.xml and so forth. These are normal xml files in that they start with a ViewGroup (i.e. LinearLayout, RelativeLayout) which contains any number of other widgets. These widgets can be things like EditTexts, buttons, custom views, whatever you want. The only rule is that the parent ViewGroup (the one at the top) must have a unique ID in it, in the manner of android:id="#+id/someUniqueName". You will use that to refer to that specific layout/tab in your code. So for example, this would be:
tab1.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/tab1Layout"
android:orientation="vertical">
<TextView ... />
<EditText ... />
</LinearLayout>
With that done, we can look at your code. I assume you've probably already got this, but just in case here's what you want:
public class YourProject extends TabActivity {
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Resources res = getResources();
TabHost tabHost = getTabHost();
tabHost.addTab(tabHost.newTabSpec("tab1").setIndicator("Tab1 title",
res.getDrawable(R.drawable.logo1)).setContent(R.id.tab1Layout));
(...)
//You can also fill tabs with a separate activity like so:
Intent intent = new Intent(this, YourClass.class);
tabHost.addTab(tabHost.newTabSpec("tab2").setIndicator("Another title",
res.getDrawable(R.drawable.logo2)).setContent(intent));
tabHost.setCurrentTab(0);
}
}
As shown above you can set the content of one of the tabs to be a separate activity. In that case, the activity is defined just as any other one with its own Class, layout, etc. Usually you shouldn't do this and instead just use a different View (with setContent(R.id.tabXLayout), but sometimes it's needed. For example if you want one of your tabs to have a list, then you need to start an activity in there that extends ListView, and include all the boilerplate code for ListViews.
I hope that helps!
The layout view in Eclipse can be a bit flaky, particularly with complex layouts. A bit of trial and error might find the View node it is choking on.
As regards developing the tab-based layout further, you have two options, the 'quick' way or the 'right' way. First is to adapt the existing layout xml by replacing one of the TextViews with a LinearLayout (or some other layout) which contains the content you want.
http://google.com/codesearch/p?hl=en#HQNWZ1u2Pig/trunk/HelloLayoutAndroid/res/layout/tab_widget.xml
However Tabs are generally used where there is complex content. For scalability it may be better to locate the TabHost in the layout, call newTabSpec() and then use setContent() to supply an Intent that identifies an internal Activity, which supplies its own Layout.
the include often makes problems while parsing XML, I tried it and got :cannot resolve #layout/mylayout..
my code was correct 100%, but it's common problem spicialy if you need Id for the layout and other attributes.
samply: I solve it by the disign mode, when you drop tabhost to your layout, place it wherever you want, it creates 3 Linear layouts (tab1,tab2,tab3)... on XML editor, in each tab (leanearlayout) insert your markup of the control you need to use as content of the tab.
and in java file do the next:
TabHost tabHost = (TabHost)findViewById(R.id.tabHost);
tabHost.setup();
TabHost.TabSpec tab1 = tabHost.newTabSpec("smil1");
TabHost.TabSpec tab2 = tabHost.newTabSpec("smil2");
TabHost.TabSpec tab3 = tabHost.newTabSpec("smil3");
tab1.setIndicator("#1");//the name will apear on the first tab
tab1.setContent(R.id.smiles1); // the Id of the control you put in the first LeanerLayout
tab2.setIndicator("#2"); // the same as abouv but for the second tab
tab2.setContent(R.id.smiles2);
tab3.setIndicator("#3"); // the thierd tab
tab3.setContent(R.id.smiles3);
// add the tabs
tabHost.addTab(tab1);
tabHost.addTab(tab2);
tabHost.addTab(tab3);
this is the way solving your problem if include makes problem in parsing your XML.
The NullPointerException in the layout editor is a known bug in the Android Development Tools.