Проблема с использованием вкладок, содержащих списки (Android) - PullRequest
0 голосов
/ 19 января 2011

Я попытался создать одну вкладку с двумя вкладками. Каждая вкладка содержит один просмотр списка. Вот код для 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
        }
    }
}

А вот и код для 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>

А вот и сообщение об ошибке от 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

Заранее. СПАСИБО! :)

Ответы [ 2 ]

0 голосов
/ 19 января 2011

здесь много путаницы для меня (я никогда не создаю ListView таким образом ...), но я понимаю, что ошибка, которую вы получаете, заключается в том, что вы создаете ArrayAdapter с ресурсом макета (2-й параметр), когда ArrayAdapter ожидает, что вторым параметром будет ресурс TextView. Или, если второй параметр - это макет, этот макет должен содержать TextView, и я не уверен, что android.R.layout.simple_list_item_1 содержит TextView, поэтому попробуйте это вместо этого;

lvAlle.setAdapter(new ArrayAdapter(this, android.R.layout.android.R.id.text1, new String[]{"1"}));//sh.getListNameAlle()));

Может быть, я не понимаю ваш вопрос, но надеюсь, что это поможет.

0 голосов
/ 19 января 2011

Это довольно прямое сообщение об ошибке.Из документов:

ListAdapter, который управляет ListView, поддерживаемым массивом произвольных объектов.По умолчанию этот класс ожидает, что предоставленный идентификатор ресурса ссылается на один TextView.Если вы хотите использовать более сложный макет, используйте конструкторы, которые также принимают идентификатор поля.Этот идентификатор поля должен ссылаться на TextView в более крупном ресурсе макета.

По сути, в вашем методе onTabChanged при создании ArrayAdapter вместо android.R.layout.simple_list_item_2 он ожидаетидентификатор TextView, а не макета.Вам нужно использовать другой конструктор, который берет ресурс И идентификатор TextView, поэтому в этом случае вы должны иметь возможность использовать:

lvNedlastet.setAdapter(new ArrayAdapter(this, android.R.layout.simple_list_item_2,
    android.R.id.text1, sh.getListNameNedlastet())); 

Если это сложнее, чем один TextView, вы, вероятно, должны посмотретьв создании собственного адаптера списка.

...