Android 添加自定义列表视图

Android Add Above Custom Listview

我是 Android 的新手,所以努力学习最佳实践等,主要使用教程。

我让我的应用程序使用自定义列表视图执行我希望它执行的操作。我的问题是准确理解它是如何工作的,因为代码中没有实际的列表视图。

我想做的是在列表视图上方添加一个容器,但我尝试的一切似乎都不起作用,而且它是一个自定义适配器,我很难找到很多资源。

这是我的片段:

package info.androidhive.slidingmenu;

import android.annotation.TargetApi;
import android.app.ListFragment;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.View;

import android.view.ViewStub;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.Toast;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class PhotosFragment extends ListFragment {
    private static final String TAG = MainActivity.class.getSimpleName();
    private List<ListViewItem> mItems;        // ListView items list
    JSONObject obj;
    JSONArray stories;

    class RequestTask extends AsyncTask<String, String, String> {

        @Override
        protected String doInBackground(String... uri) {
            HttpClient httpclient = new DefaultHttpClient();
            HttpResponse response;
            String responseString = null;
            try {

                response = httpclient.execute(new HttpGet(uri[0]));
                StatusLine statusLine = response.getStatusLine();
                if (statusLine.getStatusCode() == HttpStatus.SC_OK) {
                    ByteArrayOutputStream out = new ByteArrayOutputStream();
                    response.getEntity().writeTo(out);

                    out.close();
                    responseString = out.toString();

                    //Do anything with response..
                    Log.d(TAG, responseString);

                } else {
                    //Closes the connection.
                    response.getEntity().getContent().close();
                    throw new IOException(statusLine.getReasonPhrase());
                }
            } catch (ClientProtocolException e) {
                //TODO Handle problems..
                Log.d(TAG, String.valueOf(e));
            } catch (IOException e) {
                //TODO Handle problems..
                Log.d(TAG, String.valueOf(e));
            }
            return responseString;
        }

        @Override
        protected void onPostExecute(String result) {
            super.onPostExecute(result);

            Log.e(TAG, result);
            try {
                obj = new JSONObject(result);
                stories = obj.getJSONArray("stories");

                // initialize the items list
                mItems = new ArrayList<ListViewItem>();

                for (int i = 0; i < stories.length(); i++) {

                    JSONObject storyObj = stories.getJSONObject(i);

                    if (!storyObj.has("Advert")) {

                        newsStories newsStories = new newsStories();

                        newsStories.setTitle(storyObj.getString("subject"));
                        newsStories.setBody(storyObj.getString("body"));

                        mItems.add(new ListViewItem(newsStories.getTitle(), newsStories.getBody(), ""));

                    } else {
                        newsStories newsStories = new newsStories();
                        newsStories.setThumbnailUrl(storyObj.getString("Advert"));
                        mItems.add(new ListViewItem("", "", newsStories.getThumbnailUrl()));

                    }

                    // initialize and set the list adapter
                    setListAdapter(new ListViewDemoAdapter(getActivity(), mItems));

                }

            } catch (JSONException e) {
                e.printStackTrace();
            }
        }

        public class newsStories {
            private String name, thumbnailUrl, body;

            public String getTitle() {
                return name;
            }

            public void setTitle(String name) {
                this.name = name;
            }

            public String getBody() {
                return body;
            }

            public void setBody(String body) {

                this.body = body.substring(0, 150);

            }


            public String getThumbnailUrl() {
                return thumbnailUrl;
            }

            public void setThumbnailUrl(String thumbnailUrl) {
                //Check if thumbnail exists, if so take out spaces and replace with -

                this.thumbnailUrl = thumbnailUrl;

            }

        }

    }

    @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);


       // View importPanel = ((ViewStub) getActivity().findViewById(R.id.stub_import)).inflate();
        new RequestTask().execute("http://www.myjsonurl.co.uk");
        // remove the dividers from the ListView of the ListFragment
        getListView().setDivider(null);
    }

    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
        // retrieve theListView item
        ListViewItem item = mItems.get(position);

        // do something
        Toast.makeText(getActivity(), item.title, Toast.LENGTH_SHORT).show();
    }

    public class ListViewItem {
        public final String title;        // the text for the ListView item title
        public final String description;  // the text for the ListView item description
        public final String adUrl;
        //public final Drawable image;

        public ListViewItem(String title, String description, String Advert_Url) {

            Log.e("Advert:", Advert_Url);


            if (Advert_Url != null && !Advert_Url.isEmpty()) {

                String Advert = "http://alinktomyadvert.co.uk";

                Log.e("TITLE: ", title);
                this.title = "";
                this.description = "";
                this.adUrl = Advert;

            } else {
                this.title = title;
                this.description = description;
                this.adUrl = "";
            }
        }
    }


}

如果有人能给我指出正确的方向,我将不胜感激。

编辑:

按照@Sufian 的建议,我现在有以下内容:

包 info.androidhive.slidingmenu;

import android.annotation.TargetApi;
import android.app.Fragment;
import android.app.ListFragment;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;

import android.view.ViewGroup;
import android.view.ViewStub;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class PhotosFragment extends Fragment {
    public PhotosFragment(){}
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_photos, container, false);
        return rootView;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        new RequestTask().execute("http://www.myaddress.co.uk/app/index.php?Type=8&catid=7&userid=4");
        Log.v("created", "onActivityCreated()");
        setHasOptionsMenu(true);
        //mProgressBar = (ProgressBar) getView().findViewById(R.id.progressBar);
        ListView mListView = (ListView) getView().findViewById(R.id.listView2);
        //mTvEmpty = (TextView) getView().findViewById(R.id.textView);

        ArrayAdapter<ListViewItem> adapter = new ArrayAdapter<ListViewItem>(getActivity(), android.R.layout.simple_list_item_1, mItems);
        // load your data to your mListView
        mListView.setAdapter(adapter); //NULL POINTER
    }
    private static final String TAG = MainActivity.class.getSimpleName();
   private List<ListViewItem> mItems;        // ListView items list
    JSONObject obj;
    JSONArray stories;
//
    class RequestTask extends AsyncTask<String, String, String> {

        @Override
        protected String doInBackground(String... uri) {
            HttpClient httpclient = new DefaultHttpClient();
            HttpResponse response;
            String responseString = null;
            try {

                response = httpclient.execute(new HttpGet(uri[0]));
                StatusLine statusLine = response.getStatusLine();
                if (statusLine.getStatusCode() == HttpStatus.SC_OK) {
                    ByteArrayOutputStream out = new ByteArrayOutputStream();
                    response.getEntity().writeTo(out);

                    out.close();
                    responseString = out.toString();

                    //Do anything with response..
                    Log.d(TAG, responseString);

                } else {
                    //Closes the connection.
                    response.getEntity().getContent().close();
                    throw new IOException(statusLine.getReasonPhrase());
                }
            } catch (ClientProtocolException e) {
                //TODO Handle problems..
                Log.d(TAG, String.valueOf(e));
            } catch (IOException e) {
                //TODO Handle problems..
                Log.d(TAG, String.valueOf(e));
            }
            return responseString;
        }

        @Override
        protected void onPostExecute(String result) {
            super.onPostExecute(result);

            Log.e(TAG, result);
            try {
                obj = new JSONObject(result);
                stories = obj.getJSONArray("stories");

                // initialize the items list
                mItems = new ArrayList<ListViewItem>();

                for (int i = 0; i < stories.length(); i++) {

                    JSONObject storyObj = stories.getJSONObject(i);

                    if (!storyObj.has("Advert")) {

                        newsStories newsStories = new newsStories();

                        newsStories.setTitle(storyObj.getString("subject"));
                        newsStories.setBody(storyObj.getString("body"));

                        mItems.add(new ListViewItem(newsStories.getTitle(), newsStories.getBody(), ""));

                    } else {
                        newsStories newsStories = new newsStories();
                        newsStories.setThumbnailUrl(storyObj.getString("Advert"));
                        mItems.add(new ListViewItem("", "", newsStories.getThumbnailUrl()));

                    }

                    // initialize and set the list adapter
                    //setListAdapter(new ListViewDemoAdapter(getActivity(), mItems));

                }

            } catch (JSONException e) {
                e.printStackTrace();
            }
        }

        public class newsStories {
            private String name, thumbnailUrl, body;

            public String getTitle() {
                return name;
            }

            public void setTitle(String name) {
                this.name = name;
            }

            public String getBody() {
                return body;
            }

            public void setBody(String body) {

                this.body = body.substring(0, 150);

            }


            public String getThumbnailUrl() {
                return thumbnailUrl;
            }

            public void setThumbnailUrl(String thumbnailUrl) {
                //Check if thumbnail exists, if so take out spaces and replace with -

                this.thumbnailUrl = thumbnailUrl;

            }

        }

    }
//
//    @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
//    @Override
//    public void onViewCreated(View view, Bundle savedInstanceState) {
//        super.onViewCreated(view, savedInstanceState);
//
//
//        // View importPanel = ((ViewStub) getActivity().findViewById(R.id.stub_import)).inflate();
//        new RequestTask().execute("http://www.myjsonurl.co.uk");
//        // remove the dividers from the ListView of the ListFragment
//        getListView().setDivider(null);
//    }
//
//    @Override
//    public void onListItemClick(ListView l, View v, int position, long id) {
//        // retrieve theListView item
//        ListViewItem item = mItems.get(position);
//
//        // do something
//        Toast.makeText(getActivity(), item.title, Toast.LENGTH_SHORT).show();
//    }
//
    public class ListViewItem {
        public final String title;        // the text for the ListView item title
        public final String description;  // the text for the ListView item description
        public final String adUrl;
        //public final Drawable image;

        public ListViewItem(String title, String description, String Advert_Url) {

            Log.e("Advert:", Advert_Url);


            if (Advert_Url != null && !Advert_Url.isEmpty()) {

                String Advert = "http://www.myaddress.co.uk/images/websitelogo.png?width=700&height=200";

                Log.e("TITLE: ", title);
                this.title = "";
                this.description = "";
                this.adUrl = Advert;

            } else {
                this.title = title;
                this.description = description;
                this.adUrl = "";
            }
      }

   }


}

我现在在设置适配器命令上遇到空指针异常 - 我有点不确定从这里调试的位置。我假设这意味着列表为空?

编辑 2

Logcat:

01-19 05:27:30.371    1287-1287/info.androidhive.slidingmenu D/OpenGLRenderer﹕ Enabling debug mode 0
01-19 05:27:31.031    1287-1287/info.androidhive.slidingmenu I/Choreographer﹕ Skipped 60 frames!  The application may be doing too much work on its main thread.
01-19 05:27:57.901    1287-1287/info.androidhive.slidingmenu V/created﹕ onActivityCreated()

01-19 05:28:08.271    1287-1287/info.androidhive.slidingmenu D/dalvikvm﹕ GC_FOR_ALLOC freed 326K, 9% free 4066K/4468K, paused 24ms, total 26ms
01-19 05:28:08.471    1287-1287/info.androidhive.slidingmenu D/AndroidRuntime﹕ Shutting down VM
01-19 05:28:08.471    1287-1287/info.androidhive.slidingmenu W/dalvikvm﹕ threadid=1: thread exiting with uncaught exception (group=0xb3ac2ba8)
01-19 05:28:08.511    1287-1287/info.androidhive.slidingmenu E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: info.androidhive.slidingmenu, PID: 1287
    java.lang.NullPointerException
            at info.androidhive.slidingmenu.PhotosFragment$RequestTask.onPostExecute(PhotosFragment.java:130)
            at info.androidhive.slidingmenu.PhotosFragment$RequestTask.onPostExecute(PhotosFragment.java:52)
            at android.os.AsyncTask.finish(AsyncTask.java:632)
            at android.os.AsyncTask.access0(AsyncTask.java:177)
            at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:645)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:136)
            at android.app.ActivityThread.main(ActivityThread.java:5017)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
            at dalvik.system.NativeStart.main(Native Method)

fragment_photos.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ProgressBar
        style="?android:attr/progressBarStyleLarge"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/progressBar"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="190dp" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="New Text"
        android:id="@+id/textView"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="63dp" />

    <ListView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/listView2"
        android:layout_below="@+id/progressBar"
        android:layout_centerHorizontal="true" />
</RelativeLayout>

编辑 3

包 info.androidhive.slidingmenu;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.text.Html;
import android.text.Layout;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import com.squareup.picasso.Picasso;
import java.util.List;

public class ListViewDemoAdapter extends ArrayAdapter<PhotosFragment.ListViewItem> {

    public ListViewDemoAdapter(Context context, List<PhotosFragment.ListViewItem> items) {

        super(context, R.layout.listview_item, items);

    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder viewHolder;

        if(convertView == null) {

            // inflate the GridView item layout
            LayoutInflater inflater = LayoutInflater.from(getContext());


            convertView = inflater.inflate(R.layout.listview_item, parent, false);

            // initialize the view holder
            viewHolder = new ViewHolder();

            viewHolder.ivIcon = (ImageView) convertView.findViewById(R.id.ivIcon);
            viewHolder.tvTitle = (TextView) convertView.findViewById(R.id.tvTitle);
            viewHolder.tvDescription = (TextView) convertView.findViewById(R.id.tvDescription);

            convertView.setTag(viewHolder);

        } else {

            // recycle the already inflated view
            viewHolder = (ViewHolder) convertView.getTag();

        }

        // update the item view
        PhotosFragment.ListViewItem item = getItem(position);

        //viewHolder.ivIcon.setImageDrawable(item.image);
        viewHolder.tvTitle.setText((Html.fromHtml(item.title)));
        viewHolder.tvDescription.setText(Html.fromHtml(item.description));

        if (!item.adUrl.isEmpty()) {
            Picasso.with(getContext())
                    .load(item.adUrl)
                    .into(viewHolder.ivIcon);
            viewHolder.ivIcon.setVisibility(viewHolder.ivIcon.VISIBLE);
            viewHolder.ivIcon.setOnClickListener(new View.OnClickListener() {
                //@Override
                public void onClick(View v) {
                    Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.myaddress.co.uk"));
                    getContext().startActivity(browserIntent);
                }
            });

        }else {
           viewHolder.ivIcon.setVisibility(viewHolder.ivIcon.GONE);
        }

        return convertView;
    }

    /**
     * The view holder design pattern prevents using findViewById()
     * repeatedly in the getView() method of the adapter.
     *
     * @see
     */

    private static class ViewHolder {
        ImageView ivIcon;
        TextView tvTitle;
        TextView tvDescription;
    }


}

ListFragment 带有一个 ListView、一个 ProgressBar(显示直到你写 setListShown(true);)和一个 TextView(当 ListView没有项目。

如果您想在 ListView 之上添加任何内容,最简单的方法是将 ListFragment 替换为 Fragment 并扩充您自己的 XML。如下所示:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    return inflater.inflate(R.layout.fragment_home, container, false);
}

并在 onActivityCreated() 中设置您的字段并填充数据,例如:

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    Log.v("created", "onActivityCreated()");
    setHasOptionsMenu(true);
    mProgressBar = (ProgressBar) getView().findViewById(R.id.progressBar1);
    mListView = (ListView) getView().findViewById(R.id.listView1);
    mTvEmpty = (TextView) getView().findViewById(R.id.tv_empty);
    // load your data to your mListView
}

编辑:

将您的 onPostExecute() 更新为:

@Override
protected void onPostExecute(String result) {
    super.onPostExecute(result);

    Log.e(TAG, result);
    try {
        obj = new JSONObject(result);
        stories = obj.getJSONArray("stories");

        // initialize the items list
        mItems = new ArrayList<ListViewItem>();

        for (int i = 0; i < stories.length(); i++) {

            JSONObject storyObj = stories.getJSONObject(i);

            if (!storyObj.has("Advert")) {

                newsStories newsStories = new newsStories();

                newsStories.setTitle(storyObj.getString("subject"));
                newsStories.setBody(storyObj.getString("body"));

                mItems.add(new ListViewItem(newsStories.getTitle(), newsStories.getBody(), ""));

            }
            else {
                newsStories newsStories = new newsStories();
                newsStories.setThumbnailUrl(storyObj.getString("Advert"));
                mItems.add(new ListViewItem("", "", newsStories.getThumbnailUrl()));

            }

            // initialize and set the list adapter
            //setListAdapter(new ListViewDemoAdapter(getActivity(), mItems));

        }

        //mProgressBar = (ProgressBar) getView().findViewById(R.id.progressBar);
        ListView mListView = (ListView) getView().findViewById(R.id.listView2);
        //mTvEmpty = (TextView) getView().findViewById(R.id.textView);

        Log.d("mListView: ", String.valueOf(mListView));

        ArrayAdapter<ListViewItem> adapter = new ArrayAdapter<ListViewItem>(getActivity(), android.R.layout.simple_list_item_1, mItems);

        Log.d("Adapter: ", String.valueOf(adapter));

        // load your data to your mListView
        mListView.setAdapter(adapter);

    }
    catch (JSONException e) {
        e.printStackTrace();
    }
}

即使 mItems 为空,您也正在创建适配器(将它放在 catch 之后 运行 它总是)。