简体   繁体   English

如何连接我的ListAdapter类,使其在具有针对行的自定义“模型”类的片段中工作?

[英]How can I connect my ListAdapter-class to work in a fragment with a customized “Model” class for the rows?

I am trying to create a customized ListView in an app I am making following a tutorial. 我正在尝试按照教程制作的应用程序中创建自定义ListView。 The tutorial works fine if you want to launch the ListView from an activity, but I am trying to get it to work from inside a fragment and I can not seem to figure out how to connect my adapter to the fragment. 如果您想从活动中启动ListView,则本教程效果很好,但是我试图使它在片段内部工作,而且似乎无法弄清楚如何将适配器连接到片段。 Does anyone know how I could figure this out? 有谁知道我该怎么解决? Kotlin is quite new to me at this point, so there might be an obvious solution, I just have not found it yet. 在这一点上,Kotlin对我来说还很陌生,因此可能有一个明显的解决方案,我只是还没有找到它。

I did get it to work attaching the code to an activity, but in my project, I am trying to attach it to a fragment in a navigation bar, but the fragment will not handle the code that is working in the activity. 我确实可以通过将代码附加到活动上来工作,但是在我的项目中,我试图将其附加到导航栏中的片段上,但是该片段将无法处理活动中使用的代码。

This is what the code looks like in the onCreate-method when it is attached to an activity: 这是将代码附加到活动时在onCreate方法中的代码形式:

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        //listview
        var listView = findViewById<ListView>(R.id.listView)

        var list = mutableListOf<Model>()

        //adding items to the listview
        list.add(Model("title one", "description one....", R.drawable.imgone))
        list.add(Model("title two", "description two....", R.drawable.imgtwo))
.....

        //adapter
        listView.adapter = MyListAdapter(this, R.layout.row, list)

        //ListView item clicks
        listView.setOnItemClickListener { parent, view, position, id ->
            if (position == 0){
                Toast.makeText(this@MainActivity, "Item One clicked", Toast.LENGTH_LONG).show()
            }
            if (position == 1){
                Toast.makeText(this@MainActivity, "Item Two clicked", Toast.LENGTH_LONG).show()
            }
.....
        }

    }

This is what the code looks like in the fragment at this point 这是这段代码在片段中的样子

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        val view = inflater.inflate(R.layout.fragment_home, container, false)

        val listView: ListView = view.findViewById(R.id.homeListView)

        val adapter: MyListAdapter
        //Not sure how to instantiate MyListAdapter

        return view
    }

The Model class looks like this Model类看起来像这样

class Model(val title: String, val desc: String, val img: Int)

And MyListAdapter looks like this 和MyListAdapter看起来像这样

class MyListAdapter (var mCtx: Context, var resource: Int, var items: List<Model>)
    :ArrayAdapter<Model>(mCtx, resource, items){


    override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {

        val layoutInflater: LayoutInflater = LayoutInflater.from(mCtx)

        val view: View = layoutInflater.inflate(resource, null)
        val imageView: ImageView = view.findViewById(R.id.list_view_image)
        val titleView: TextView = view.findViewById(R.id.list_view_title_txt)
        val descTView: TextView = view.findViewById(R.id.list_view_desc_txt)

        var mItems: Model = items[position]

        imageView.setImageDrawable(mCtx.resources.getDrawable(mItems.img))
        titleView.text = mItems.title
        descTView.text = mItems.desc


        return view
    }
}

My fragment_home.xml uses a pretty simple ListView: 我的fragment_home.xml使用了一个非常简单的ListView:

<ListView
            android:id="@+id/homeListView"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

    </ListView>

Whilst it is the row.xml that customizes the look of the items in my list 虽然row.xml可以自定义列表中项目的外观

<LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:padding="10dp">

    <ImageView
            android:id="@+id/list_view_image"
            android:layout_width="80dp"
            android:layout_height="80dp"
            android:contentDescription="@string/list_view_img_content_desc"/>

    <LinearLayout
            android:layout_margin="5dp"
            android:layout_gravity="center"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

        <TextView
                android:id="@+id/list_view_title_txt"
                android:text="@string/list_view_title"
                android:textSize="15sp"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"/>
        <TextView
                android:id="@+id/list_view_desc_txt"
                android:text="@string/list_view_desc"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"/>

    </LinearLayout>

</LinearLayout>

What it is supposed to do, is that I should be able to launch my customized ListView from my HomeFragment and from there be able to click on an item in the list and have a Toast show up(eventually another fragment, but first things first). 它应该做的是,我应该能够从HomeFragment中启动自定义的ListView,然后从中单击列表中的项目并显示Toast(最终是另一个片段,但首先要做的是) 。 At the moment, I have the customized rows and the ListView ready, but I can not seem to make the connection from MyListAdapter to the HomeFragment. 目前,我已经准备好自定义的行和ListView,但是似乎无法建立从MyListAdapter到HomeFragment的连接。

MyListAdapter should be able to take a reference to a Fragment instead of a Context (Activity) provided you change the parameter type and local variable in MyListAdapter, then, you just have to pass 'this' and the syntax is the same as that of an Activity. 只要您在MyListAdapter中更改参数类型和局部变量,MyListAdapter应该能够引用片段而不是上下文(活动),然后,您只需传递“ this”,并且语法与活动。 If that doesn't work, then you might need to get the Fragment's Context (Activity) onCreate() and save it for use in the creation of MyListAdapter. 如果这不起作用,那么您可能需要获取Fragment的Context(活动)onCreate()并将其保存以用于创建MyListAdapter。 I'll have to look at my code samples tomorrow for an example... 我明天必须看一下我的代码示例作为示例...

OK, this is how I do it (sorry it is not in Kotlin): 好的,这就是我的方法(对不起,它不在Kotlin中):

FavoritesFragment.java 收藏夹Fragment.java

            package org.mycompany.myapp;

            import java.util.ArrayList;
            import java.util.HashMap;
            import java.util.Map;

            import org.json.JSONArray;
            import org.json.JSONException;
            import org.json.JSONObject;
            import org.mycompany.TEST.adapter.FavoriteListAdapter;
            import org.mycompany.TEST.model.FavoriteItem;

            import android.app.Fragment;
            import android.app.ProgressDialog;
            import android.content.Context;
            import android.content.Intent;
            import android.view.LayoutInflater;
            import android.view.View;
            import android.view.ViewGroup;
            import android.widget.AdapterView;
            import android.widget.ListView;

            public class FavoritesFragment extends Fragment {

                Context thisContext;
                private MainActivity myActivity;

                private ViewGroup container;
                private View rootView;

                private ListView mFavoriteList;                 
                private ArrayList<FavoriteItem> favoriteItems;
                private FavoriteListAdapter adapter;
                private FavoritesFragment thisFragment;

                public FavoritesFragment(){}

                @Override
                public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

                    rootView = inflater.inflate(R.layout.fragment_favorites, container, false);
                    this.container = container;

                    //Get a reference to the fragments activity 
                    myActivity = (MainActivity)getActivity();   

                    RestoreAllItems();

                    //Declare the favorite array
                    favoriteItems = new ArrayList<FavoriteItem>();

                    //Load the favorite array
                    callGetFavorites();

                    return rootView;

                }

                private void RestoreAllItems()
                {

                    //Get a reference to the fragments Context
                    thisContext = container.getContext();

                    //Get a reference to the Fragment
                    thisFragment = this;

                    mFavoriteList = (ListView) rootView.findViewById(R.id.list_browse);

                    mFavoriteList.setOnItemClickListener(new FavoriteClickListener());


                }

                /**
                 * Item click listener
                 * */
                private class FavoriteClickListener implements ListView.OnItemClickListener {
                    @Override
                    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

                        FavoriteItem item = favoriteItems.get(position);

                            Intent iIntent = new Intent(thisContext, DetailActivity.class);

                            iIntent.putExtra("animal_id", item.getAnimalID());

                            startActivityForResult(iIntent, ACTIVITY_PET_DETAIL);

                    }
                }  

                //Method called from the ListAdapter when an items checkbox changes
                public void checkChanged(int position, boolean isChecked) {

                    if (position < favoriteItems.size()) {      
                        FavoriteItem item = favoriteItems.get(position);
                        item.setSelected(isChecked);

                        favoriteItems.set(position, item);
                    }


                }

                //Load the favoriteItems array
                private void getFavorites(String url) {
                    final ProgressDialog dialog;    

                    dialog = new ProgressDialog(thisContext);         
                    dialog.setMessage("Loading, please wait...");         
                    dialog.setIndeterminate(true);         
                    dialog.setCancelable(false);         
                    dialog.show();     

                    favoriteItems = new ArrayList<FavoriteItem>();

                    JsonArrayRequest req = new JsonArrayRequest(url, new Response.Listener<JSONArray> () {  

                        @Override
                        public void onResponse(JSONArray response) {
                            try {
                                ....

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

                                ....

                                    // Load the favoriteItems array
                                    favoriteItems.add(new FavoriteItem(name, breed, sex, age_long, animal_id));

                                }

                                try {

                                    //When the array is fully loaded set the ListAdapter
                                    adapter = new FavoriteListAdapter(thisContext, favoriteItems, thisFragment);
                                    mFavoriteList.setAdapter(adapter);

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

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

                            dialog.dismiss();
                        }


                    }, new Response.ErrorListener() {
                        @Override
                        public void onErrorResponse(VolleyError error) {
                            VolleyLog.e("Error: ", error.getMessage());
                            Log.e("Error: ", error.getMessage());
                            dialog.dismiss();
                        }
                    }) {

                       @Override
                       public Map<String, String> getHeaders() throws AuthFailureError {
                           HashMap<String, String> headers = new HashMap<String, String>();
                                String authValue = "Bearer " + apiToken;
                                headers.put("Authorization", authValue);
                                headers.put("Accept", "application/json; charset=UTF-8");
                                headers.put("Content-Type", "application/json; charset=UTF-8");
                           return headers;
                       };
                    };

                    // add the request object to the queue to be executed
                    MyApplication.getInstance().addToRequestQueue(req);
                }   
            }

Then, the ListAdapter: FavoriteListAdapter.java 然后,ListAdapter:FavoriteListAdapter.java

            package org.mycompany.TEST.adapter;

            import java.util.ArrayList;

            import org.mycompany.TEST.FavoritesFragment;
            import org.mycompany.TEST.R;
            import org.mycompany.TEST.model.FavoriteItem;

            import android.app.Activity;
            import android.content.Context;
            import android.view.LayoutInflater;
            import android.view.View;
            import android.view.ViewGroup;
            import android.widget.BaseAdapter;
            import android.widget.CheckBox;
            import android.widget.CompoundButton;
            import android.widget.CompoundButton.OnCheckedChangeListener;
            import android.widget.ImageView;
            import android.widget.TextView;


            public class FavoriteListAdapter extends BaseAdapter {

                private Context context;
                private FavoritesFragment thisFragment;
                private ArrayList<FavoriteItem> favoriteItems;
                private boolean isEditing = false;


                public FavoriteListAdapter(Context context, ArrayList<FavoriteItem> favoriteItems, FavoritesFragment thisFragment){
                    //Reference to the Context
                    this.context = context;
                    //Reference to the ArrayList
                    this.favoriteItems = favoriteItems;
                    //Reference to the Fragment that created the ListAdapter
                    this.thisFragment = thisFragment;
                }

                @Override
                public int getCount() {
                    return favoriteItems.size();
                }

                @Override
                public Object getItem(int position) {       
                    return favoriteItems.get(position);
                }

                @Override
                public long getItemId(int position) {
                    return position;
                }

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

                    if (convertView == null) {
                        //Context allows you to get the LayoutInflater
                        LayoutInflater mInflater = (LayoutInflater)context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
                        convertView = mInflater.inflate(R.layout.favorite_list_item, null);
                    }

                     TextView txtName = (TextView) convertView.findViewById(R.id.name);
                    CheckBox chkSelected = (CheckBox) convertView.findViewById(R.id.isSelected);

                    txtName.setText(favoriteItems.get(position).getName());
                    chkSelected.setChecked(favoriteItems.get(position).isSelected());
                    //Store the position in the list of this list item
                    chkSelected.setTag("" + position);
                    chkSelected.setOnCheckedChangeListener(new OnCheckedChangeListener() 
                    {

                        public void onCheckedChanged(CompoundButton chkBox, boolean isChecked) 
                        {
                            //Get the position out of the tag when the checkbox changes
                            String sPos = (String) chkBox.getTag();
                            int position = Integer.parseInt(sPos);

                            //Call the checkChanged method in the Fragment
                            thisFragment.checkChanged(position, isChecked);
                        }
                    });

                    return convertView;
                }

            }
 val adapter: MyListAdapter
    //Not sure how to instantiate MyListAdapter

Will go: 会去:

listView.adapter = MyListAdapter(context, R.layout.row, list)

The context ( this.context , where this is your HomeFragment and context is from getContext() ) will be used in your adapter to inflate you list row (resource = R.layout.row) 上下文this.context是您的HomeFragment, 上下文来自getContext())将在您的适配器中用于为列表行填充(resource = R.layout.row)

In the case that you need your activity as context you can instantiate your list adapter like this: 在需要将活动作为上下文的情况下,可以实例化列表适配器,如下所示:

listView.adapter = MyListAdapter(activity, R.layout.row, list)

where activity is from getActivity() 活动来自getActivity()

In either case you'll get access to your application's resources to get the Model.img. 无论哪种情况,您都可以访问应用程序的资源以获取Model.img。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM