Problème à l'aide des onglets qui contient listviews (applications)
-
12-10-2019 - |
Question
J'ai essayé de créer un tabhost avec deux onglets. Chaque onglet contient un listview. Voici le code pour le fichier java
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)){
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
}
}
}
Et voici le code pour le 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>
Et voici le message d'erreur du 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
à l'avance. MERCI! :)
La solution
Il est un message d'erreur assez simple. De la documentation:
Un ListAdapter qui gère un ListView soutenu par un réseau de arbitraire objets. Par défaut, cette classe attend que l'ID fourni des ressources fait référence à un seul TextView. Si vous veulent utiliser une disposition plus complexe, l'utilisation les constructeurs qui prend aussi champ id. Ce champ id devrait référencer un TextView dans la plus grande ressource mise en page.
En fait, dans votre méthode onTabChanged, quand vous construisez la ArrayAdapter, au lieu de android.R.layout.simple_list_item_2, il est l'id attend d'un TextView, et non d'une mise en page. Vous devez utiliser un constructeur différent qui prend une ressource et un identifiant TextView, dans ce cas, vous devriez être en mesure d'utiliser:
lvNedlastet.setAdapter(new ArrayAdapter(this, android.R.layout.simple_list_item_2,
android.R.id.text1, sh.getListNameNedlastet()));
S'il est plus compliqué qu'un seul TextView, vous devriez probablement dans la création de votre propre adaptateur liste personnalisée.
Autres conseils
il y a beaucoup de confusion pour moi ici, (je ne construis ListView cette façon ...), mais chose que je que l'erreur que vous obtenez est parce que vous construit le ArrayAdapter avec une ressource de mise en page (2ème paramètre) lorsque ArrayAdapter attend à ce que la second paramètre être une ressource TextView. Ou si le second paramètre est une disposition, que la mise en page doit tenir une TextView, et je ne pas sûr si android.R.layout.simple_list_item_1 est titulaire d'un TextView, donc, essayez ce lieu;
lvAlle.setAdapter(new ArrayAdapter(this, android.R.layout.android.R.id.text1, new String[]{"1"}));//sh.getListNameAlle()));
peut-être que je ne comprends pas votre question, mais espère que cette aide.