Problem using tabs that contains listviews (Android)
I have tried to create one tabhost with two tabs. Each tab contains one listview. Here is the code for the java file
package com.Bussruter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import android.app.AlertDialog;
import android.app.TabActivity;
import android.content.ActivityNotFoundException;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Resources;
import android.net.ConnectivityManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TabHost;
import android.widget.TabHost.TabContentFactory;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.TabHost.OnTabChangeListener;
public class Bussruter extends TabActivity implements OnTabChangeListener {
/** Alle */
private static final String LIST1_TAB_TAG = "List1";
/** Nedlastet */
private static final String LIST2_TAB_TAG = "List2";
private StorageHandler sh;
private Resources res;// Resource object to get Drawables
private ListView lvNedlastet;
private ListView lvAlle;
private TabHost th;
/*private int[] created = new int[]{
0,
20100108,
0
};*/
/** Called when the activity is first created. */
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//Checking which pdfs are already downloaded.
sh = new StorageHandler();
this.checkAvaliablePdfs();
th = getTabHost();
res = getResources();
th.setOnTabChangedListener(this);
lvAlle = (ListView) findViewById(R.id.list1);
lvNedlastet = (ListView) findViewById(R.id.list2);
lvAlle.setAdapter(new ArrayAdapter(this, android.R.layout.simple_list_item_1, new String[]{"1"}));//sh.getListNameAlle()));
lvNedlastet.setAdapter(new ArrayAdapter(this, android.R.layout.simple_list_item_2, new String[]{"1"}));//sh.getListNameNedlastet()));
OnItemClickListener itemCLAlle = this.createClickListenerAlle();
OnItemClickListener itemCLNedlastet = this.createClickListenerNedlastet();
lvAlle.setOnItemClickListener(itemCLAlle);
lvNedlastet.setOnItemClickListener(itemCLNedlastet);
OnItemLongClickListener itemLCL = this.createLongClickListener();
lvAlle.setOnItemLongClickListener(itemLCL);
lvAlle.setLongClickable(true);
lvNedlastet.setOnItemLongClickListener(itemLCL);
lvNedlastet.setLongClickable(true);
th.addTab(th.newTabSpec(LIST2_TAB_TAG)
.setIndicator(LIST2_TAB_TAG,
res.getDrawable(R.drawable.ic_tab_nedlastet))
.setContent(new TabContentFactory() {
public View createTabContent(String arg0) {
return lvNedlastet;
}
}));
th.addTab(th.newTabSpec(LIST1_TAB_TAG)
.setIndicator(LIST1_TAB_TAG,
res.getDrawable(R.drawable.ic_tab_alle))
.setContent(new TabContentFactory() {
public View createTabContent(String arg0) {
return lvAlle;
}
}));
th.setCurrentTabByTag(LIST1_TAB_TAG);
}
private OnItemLongClickListener createLongClickListener() {
return
new OnItemLongClickListener() {
public boolean onItemLongClick(AdapterView<?> parent, final View view,
final int position, long id) {
if(isAvailable(position)){
try{
new AlertDialog.Builder(parent.getContext())
.setMessage("Vil du slette bussruten?")
.setCancelable(false)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
deleteFile(view, position);
sh.availability[position] = false;
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
})
.show();
}catch(Exception e){
toastText("ERROR: "+e.getMessage(), Toast.LENGTH_LONG);
}
return true;
}else return false;
}
};
}
private OnItemClickListener createClickListenerAlle(){
return
new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id){
boolean temp = sh.availability[position];
if(temp == true){
if(Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)){
开发者_C百科 File file = new File(StorageHandler.sdcardUrl+ StorageHandler.uniqueBussFilename[position]);
if (file.exists()) {//open the file
Uri path = Uri.fromFile(file);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(path, "application/pdf");
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
try {
startActivity(intent);
}
catch (ActivityNotFoundException e) {
toastText("No Application Available for viewing PDF", Toast.LENGTH_LONG);
}
}else{
toastText("The file "+file.getAbsolutePath()+" was not found.", Toast.LENGTH_LONG);
}
}else{
toastText("sdkort er ikke tilgjengelig.", Toast.LENGTH_LONG);
}
}else{//Have to download the file.
connect();
try {
String absUrl = StorageHandler.webUrl[position];
InputStream inputStream = OpenHttpConnection(absUrl);
File tempFile = new File(StorageHandler.sdcardUrl+StorageHandler.uniqueBussFilename[position]);
File tempFile2 = new File(StorageHandler.sdcardUrl);
if(!tempFile.exists()){
tempFile2.mkdirs();
tempFile.createNewFile();
}
OutputStream output = new FileOutputStream(tempFile);
int bytesRead;
byte[] buffer = new byte[8 * 1024];
while((bytesRead = inputStream.read(buffer)) != -1){
output.write(buffer,0,bytesRead);
}
output.close();
inputStream.close();
toastText("Bussruten er lastet ned.", Toast.LENGTH_LONG);
sh.availability[position] = true;
} catch (IOException e) {
toastText("ERROR:Kan ikke laste ned bussruten.\nStacktrace:\n"+e.getMessage(), Toast.LENGTH_LONG);
}
}
}
};
}
private OnItemClickListener createClickListenerNedlastet(){
return
new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id){
boolean temp = sh.availability[position];
if(temp == true){
if(Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)){
File file = new File(StorageHandler.sdcardUrl+ StorageHandler.uniqueBussFilename[position]);
if (file.exists()) {//open the file
Uri path = Uri.fromFile(file);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(path, "application/pdf");
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
try {
startActivity(intent);
}
catch (ActivityNotFoundException e) {
toastText("No Application Available for viewing PDF", Toast.LENGTH_LONG);
}
}else{
toastText("The file "+file.getAbsolutePath()+" was not found.", Toast.LENGTH_LONG);
}
}else{
toastText("sdkort er ikke tilgjengelig.", Toast.LENGTH_LONG);
}
}
};
};
}
private boolean isConnected(){
if(sh.isEmulator){
return true;
}else{
ConnectivityManager connMan = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
if (connMan.getActiveNetworkInfo().isConnected()){//getNetworkInfo(ConnectivityManager.TYPE_WIFI).isConnected()) {
return true;
}else{
return false;
}
}
}
private void toastText(String t, int l){
final String text = t;
final int length = l;
Toast.makeText(getApplicationContext(), text, length).show();
}
private void connect(){
if(isConnected()){
sh.isConnected = true;
toastText("Kobler til...", Toast.LENGTH_SHORT);
}else{
sh.isConnected = false;
toastText("Bussruten har ikke blitt lastet ned.\n" +
"Vennligst koble til internet for å laste ned ruten", Toast.LENGTH_LONG);
}
}
private InputStream OpenHttpConnection(String urlString)
throws IOException
{
InputStream in = null;
int response = -1;
URL url = new URL(urlString);
URLConnection conn = url.openConnection();
if (!(conn instanceof HttpURLConnection))
throw new IOException("Not an HTTP connection");
try{
HttpURLConnection httpConn = (HttpURLConnection) conn;
httpConn.setAllowUserInteraction(false);
httpConn.setInstanceFollowRedirects(true);
httpConn.setRequestMethod("GET");
httpConn.connect();
response = httpConn.getResponseCode();
if (response == HttpURLConnection.HTTP_OK) {
in = httpConn.getInputStream();
}
}
catch (Exception ex)
{
throw new IOException("Error connecting");
}
return in;
}
/*
private String urlWithSpaces2Percentage20(String url){
String output = "";
for(int i = 0;i<url.length();i++){
char c = url.charAt(i);
if(c == ' '){
output = output + "%20";
}else{
output = output + c;
}
}
return output;
}
private int getCreatedDateFromFullName(String name){
return 0;
}*/
private boolean isAvailable(int position){
File f = new File(StorageHandler.sdcardUrl + StorageHandler.uniqueBussFilename[position]);
if(f.exists()){
return true;
}
return false;
}
private void checkAvaliablePdfs(){
for(int i = 0;i<StorageHandler.uniqueBussFilename.length;i++){
File f = new File(StorageHandler.sdcardUrl + StorageHandler.uniqueBussFilename[i]);
if(f.exists()){
sh.availability[i] = true;
}
}
}
private void deleteFile(View view, int index){
try{
File f = new File(StorageHandler.sdcardUrl + StorageHandler.uniqueBussFilename[index]);
f.delete();
}catch(Exception e){
toastText("ERROR: "+e.getMessage(), Toast.LENGTH_LONG);
}
}
/*
private void setTextColor(View view, int id){
if(availability[id]){
view.setPressed(true);
}
}*/
/**
* Implement logic here when a tab is selected
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public void onTabChanged(String tabName) {
if(tabName.equals(LIST2_TAB_TAG)) {
lvNedlastet.setAdapter(new ArrayAdapter(this,
android.R.layout.simple_list_item_2,
sh.getListNameNedlastet()));
}
else if(tabName.equals(LIST1_TAB_TAG)) {
//do something
}
}
}
And here is the code for the main.xml
<?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">
<ListView android:id="@+id/list1" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_weight="1">
</ListView>
<ListView android:id="@+id/list2" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_weight="1">
</ListView>
</FrameLayout>
</LinearLayout>
</TabHost>
And here is the Error message from the DDMS
01-19 21:40:13.198: ERROR/AndroidRuntime(16123): Uncaught handler: thread main exiting due to uncaught exception
01-19 21:40:13.838: ERROR/AndroidRuntime(16123): java.lang.IllegalStateException: ArrayAdapter requires the resource ID to be a TextView
01-19 21:40:13.838: ERROR/AndroidRuntime(16123): at android.widget.ArrayAdapter.createViewFromResource(ArrayAdapter.java:347)
01-19 21:40:13.838: ERROR/AndroidRuntime(16123): at android.widget.ArrayAdapter.getView(ArrayAdapter.java:323)
01-19 21:40:13.838: ERROR/AndroidRuntime(16123): at android.widget.AbsListView.obtainView(AbsListView.java:1274)
01-19 21:40:13.838: ERROR/AndroidRuntime(16123): at android.widget.ListView.measureHeightOfChildren(ListView.java:1147)
01-19 21:40:13.838: ERROR/AndroidRuntime(16123): at android.widget.ListView.onMeasure(ListView.java:1060)
01-19 21:40:13.838: ERROR/AndroidRuntime(16123): at android.view.View.measure(View.java:7964)
01-19 21:40:13.838: ERROR/AndroidRuntime(16123): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3023)
01-19 21:40:13.838: ERROR/AndroidRuntime(16123): at android.widget.FrameLayout.onMeasure(FrameLayout.java:245)
01-19 21:40:13.838: ERROR/AndroidRuntime(16123): at android.view.View.measure(View.java:7964)
01-19 21:40:13.838: ERROR/AndroidRuntime(16123): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3023)
01-19 21:40:13.838: ERROR/AndroidRuntime(16123): at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:888)
01-19 21:40:13.838: ERROR/AndroidRuntime(16123): at android.widget.LinearLayout.measureVertical(LinearLayout.java:350)
01-19 21:40:13.838: ERROR/AndroidRuntime(16123): at android.widget.LinearLayout.onMeasure(LinearLayout.java:278)
01-19 21:40:13.838: ERROR/AndroidRuntime(16123): at android.view.View.measure(View.java:7964)
01-19 21:40:13.838: ERROR/AndroidRuntime(16123): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3023)
01-19 21:40:13.838: ERROR/AndroidRuntime(16123): at android.widget.FrameLayout.onMeasure(FrameLayout.java:245)
01-19 21:40:13.838: ERROR/AndroidRuntime(16123): at android.view.View.measure(View.java:7964)
01-19 21:40:13.838: ERROR/AndroidRuntime(16123): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3023)
01-19 21:40:13.838: ERROR/AndroidRuntime(16123): at android.widget.FrameLayout.onMeasure(FrameLayout.java:245)
01-19 21:40:13.838: ERROR/AndroidRuntime(16123): at android.view.View.measure(View.java:7964)
01-19 21:40:13.838: ERROR/AndroidRuntime(16123): at android.widget.LinearLayout.measureVertical(LinearLayout.java:464)
01-19 21:40:13.838: ERROR/AndroidRuntime(16123): at android.widget.LinearLayout.onMeasure(LinearLayout.java:278)
01-19 21:40:13.838: ERROR/AndroidRuntime(16123): at android.view.View.measure(View.java:7964)
01-19 21:40:13.838: ERROR/AndroidRuntime(16123): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3023)
01-19 21:40:13.838: ERROR/AndroidRuntime(16123): at android.widget.FrameLayout.onMeasure(FrameLayout.java:245)
01-19 21:40:13.838: ERROR/AndroidRuntime(16123): at android.view.View.measure(View.java:7964)
01-19 21:40:13.838: ERROR/AndroidRuntime(16123): at android.view.ViewRoot.performTraversals(ViewRoot.java:763)
01-19 21:40:13.838: ERROR/AndroidRuntime(16123): at android.view.ViewRoot.handleMessage(ViewRoot.java:1633)
01-19 21:40:13.838: ERROR/AndroidRuntime(16123): at android.os.Handler.dispatchMessage(Handler.java:99)
01-19 21:40:13.838: ERROR/AndroidRuntime(16123): at android.os.Looper.loop(Looper.java:123)
01-19 21:40:13.838: ERROR/AndroidRuntime(16123): at android.app.ActivityThread.main(ActivityThread.java:4363)
01-19 21:40:13.838: ERROR/AndroidRuntime(16123): at java.lang.reflect.Method.invokeNative(Native Method)
01-19 21:40:13.838: ERROR/AndroidRuntime(16123): at java.lang.reflect.Method.invoke(Method.java:521)
01-19 21:40:13.838: ERROR/AndroidRuntime(16123): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
01-19 21:40:13.838: ERROR/AndroidRuntime(16123): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
01-19 21:40:13.838: ERROR/AndroidRuntime(16123): at dalvik.system.NativeStart.main(Native Method)
01-19 21:40:13.838: ERROR/AndroidRuntime(16123): Caused by: java.lang.ClassCastException: android.widget.TwoLineListItem
01-19 21:40:13.838: ERROR/AndroidRuntime(16123): at android.widget.ArrayAdapter.createViewFromResource(ArrayAdapter.java:340)
01-19 21:40:13.838: ERROR/AndroidRuntime(16123): ... 35 more
In advance. THANKS! :)
It's a pretty straightforward error message. From the docs:
A ListAdapter that manages a ListView backed by an array of arbitrary objects. By default this class expects that the provided resource id references a single TextView. If you want to use a more complex layout, use the constructors that also takes a field id. That field id should reference a TextView in the larger layout resource.
Basically, in your onTabChanged method, when you're constructing the ArrayAdapter, instead of android.R.layout.simple_list_item_2, it's expecting the id of a TextView, not of a layout. You need to use a different constructor that takes a resource AND a TextView id, so in this case, you should be able to use:
lvNedlastet.setAdapter(new ArrayAdapter(this, android.R.layout.simple_list_item_2,
android.R.id.text1, sh.getListNameNedlastet()));
If it's more complicated than a single TextView, you should probably look into creating your own custom list adapter.
there are many confusions for me here, (i never build the ListView this way... ) but i thing that the error you get is because you constructs the ArrayAdapter with a layout resource (2nd parameter) when ArrayAdapter expects that the second parameter be a TextView resource. Or if the second parameter is a layout, that layout must hold a TextView, and i don´t sure if android.R.layout.simple_list_item_1 holds a TextView, so, try this instead;
lvAlle.setAdapter(new ArrayAdapter(this, android.R.layout.android.R.id.text1, new String[]{"1"}));//sh.getListNameAlle()));
maybe i dont understand your question, but hope this help.
精彩评论