Simple Android RecyclerView example

前端 未结 11 1426
名媛妹妹
名媛妹妹 2020-11-22 02:03

I\'ve made a list of items a few times using Android\'s RecyclerView, but it is a rather complicated process. Going through one of the numerous tutorials online

相关标签:
11条回答
  • 2020-11-22 02:36

    Start by adding recyclerview library.

    implementation 'androidx.recyclerview:recyclerview:1.1.0'
    

    Create model class.

         public class UserModel implements Serializable {
    
        private String userName;
    
    
        public UserModel(String userName) {
            this.userName = userName;
        }
    
        public String getUserName() {
            return userName;
        }
    
        public void setUserName(String userName) {
            this.userName = userName;
        }
       }
    

    create adapter class.

    public class UsersAdapter extends RecyclerView.Adapter<UsersAdapter.UsersAdapterVh> implements Filterable {
    
        private List<UserModel> userModelList;
        private List<UserModel> getUserModelListFiltered;
        private Context context;
        private SelectedUser selectedUser;
    
        public UsersAdapter(List<UserModel> userModelList,SelectedUser selectedUser) {
            this.userModelList = userModelList;
            this.getUserModelListFiltered = userModelList;
            this.selectedUser = selectedUser;
        }
    
        @NonNull
        @Override
        public UsersAdapter.UsersAdapterVh onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            context = parent.getContext();
    
            return new UsersAdapterVh(LayoutInflater.from(context).inflate(R.layout.row_users,null));
        }
    
        @Override
        public void onBindViewHolder(@NonNull UsersAdapter.UsersAdapterVh holder, int position) {
    
            UserModel userModel = userModelList.get(position);
    
            String username = userModel.getUserName();
            String prefix = userModel.getUserName().substring(0,1);
    
            holder.tvUsername.setText(username);
            holder.tvPrefix.setText(prefix);
    
        }
    
        @Override
        public int getItemCount() {
            return userModelList.size();
        }
    
        @Override
        public Filter getFilter() {
    
            Filter filter = new Filter() {
                @Override
                protected FilterResults performFiltering(CharSequence charSequence) {
                    FilterResults filterResults = new FilterResults();
    
                    if(charSequence == null | charSequence.length() == 0){
                        filterResults.count = getUserModelListFiltered.size();
                        filterResults.values = getUserModelListFiltered;
    
                    }else{
                        String searchChr = charSequence.toString().toLowerCase();
    
                        List<UserModel> resultData = new ArrayList<>();
    
                        for(UserModel userModel: getUserModelListFiltered){
                            if(userModel.getUserName().toLowerCase().contains(searchChr)){
                                resultData.add(userModel);
                            }
                        }
                        filterResults.count = resultData.size();
                        filterResults.values = resultData;
    
                    }
    
                    return filterResults;
                }
    
                @Override
                protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
    
                    userModelList = (List<UserModel>) filterResults.values;
                    notifyDataSetChanged();
    
                }
            };
            return filter;
        }
    
    
        public interface SelectedUser{
    
            void selectedUser(UserModel userModel);
    
        }
    
        public class UsersAdapterVh extends RecyclerView.ViewHolder {
    
            TextView tvPrefix;
            TextView tvUsername;
            ImageView imIcon;
            public UsersAdapterVh(@NonNull View itemView) {
                super(itemView);
                tvPrefix = itemView.findViewById(R.id.prefix);
                tvUsername = itemView.findViewById(R.id.username);
                imIcon = itemView.findViewById(R.id.imageView);
    
                itemView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        selectedUser.selectedUser(userModelList.get(getAdapterPosition()));
                    }
                });
    
    
            }
        }
    }
    

    create layout row_uses.xml

        <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical" android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <RelativeLayout
            android:layout_width="match_parent"
            android:padding="10dp"
            android:layout_height="wrap_content">
    
            <RelativeLayout
                android:layout_width="50dp"
                android:background="@drawable/users_bg"
                android:layout_height="50dp">
                <TextView
                    android:id="@+id/prefix"
                    android:layout_width="wrap_content"
                    android:textSize="16sp"
                    android:textColor="@color/headerColor"
                    android:text="T"
                    android:layout_centerInParent="true"
                    android:layout_height="wrap_content"/>
    
            </RelativeLayout>
            <TextView
                android:id="@+id/username"
                android:layout_width="wrap_content"
                android:textSize="16sp"
                android:textColor="@color/headerColor"
                android:text="username"
                android:layout_marginStart="90dp"
                android:layout_centerVertical="true"
                android:layout_height="wrap_content"/>
            <ImageView
                android:layout_width="wrap_content"
                android:id="@+id/imageView"
                android:layout_margin="10dp"
                android:layout_alignParentEnd="true"
                android:src="@drawable/ic_navigate_next_black_24dp"
                android:layout_height="wrap_content"/>
        </RelativeLayout>
    
    </LinearLayout>
    

    Find recyclerview and populate data.

    Toolbar toolbar;
    RecyclerView recyclerView;
    
    List<UserModel> userModelList = new ArrayList<>();
    
    String[] names = {"Richard","Alice","Hannah","David"};
    
    UsersAdapter usersAdapter;
    
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        recyclerView = findViewById(R.id.recyclerview);
        toolbar = findViewById(R.id.toolbar);
    
        this.setSupportActionBar(toolbar);
        this.getSupportActionBar().setTitle("");
    
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        recyclerView.addItemDecoration(new DividerItemDecoration(this,DividerItemDecoration.VERTICAL));
    
        for(String s:names){
            UserModel userModel = new UserModel(s);
    
            userModelList.add(userModel);
        }
    
        usersAdapter = new UsersAdapter(userModelList,this);
    
        recyclerView.setAdapter(usersAdapter);
    
    }
    

    find full tutorial and source code here:

    Android RecyclerView

    0 讨论(0)
  • 2020-11-22 02:37

    Since I cant comment yet im gonna post as an answer the link.. I have found a simple, well organized tutorial on recyclerview http://www.androiddeft.com/2017/10/01/recyclerview-android/

    Apart from that when you are going to add a recycler view into you activity what you want to do is as below and how you should do this has been described on the link

    • add RecyclerView component into your layout file
    • make a class which you are going to display as list rows
    • make a layout file which is the layout of a row of you list
    • now we need a custom adapter so create a custom adapter by extending from the parent class RecyclerView.Adapter
    • add recyclerview into your mainActivity oncreate
    • adding separators
    • adding Touch listeners
    0 讨论(0)
  • 2020-11-22 02:38

    Dependencies

    compile 'com.android.support:appcompat-v7:25.3.1'
    compile 'com.android.support:design:25.3.1'
    compile 'com.android.support:multidex:1.0.1'
    compile 'com.android.support:cardview-v7:25.3.1'
    compile 'com.android.support:support-v4:25.3.1'
    compile 'com.lguipeng.bubbleview:library:1.0.0'
    compile 'com.larswerkman:HoloColorPicker:1.5'
    compile 'com.mcxiaoke.volley:library-aar:1.0.0'
    

    One Class For Click Item

    import android.content.Context;
    import android.support.v7.widget.RecyclerView;
    import android.view.GestureDetector;
    import android.view.MotionEvent;
    import android.view.View;
    
    public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListener {
        private OnItemClickListener mListener;
    
        public interface OnItemClickListener {
            public void onItemClick(View view, int position);
        }
    
        GestureDetector mGestureDetector;
    
        public RecyclerItemClickListener(Context context, OnItemClickListener listener) {
            mListener = listener;
            mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
                @Override
                public boolean onSingleTapUp(MotionEvent e) {
                    return true;
                }
            });
        }
    
        @Override
        public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e) {
            View childView = view.findChildViewUnder(e.getX(), e.getY());
            if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) {
                mListener.onItemClick(childView, view.getChildPosition(childView));
                return true;
            }
            return false;
        }
    
        @Override
        public void onTouchEvent(RecyclerView view, MotionEvent motionEvent) { }
    
        @Override
        public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
    
        }
    
    
    }
    

    Second Class RecyclerView

    import android.annotation.SuppressLint;
    import android.app.ProgressDialog;
    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.Intent;
    import android.content.IntentFilter;
    import android.net.Uri;
    import android.os.Bundle;
    import android.support.annotation.Nullable;
    import android.support.v4.app.Fragment;
    import android.support.v4.app.FragmentTransaction;
    import android.support.v4.content.LocalBroadcastManager;
    import android.support.v7.widget.LinearLayoutManager;
    import android.support.v7.widget.RecyclerView;
    import android.util.Log;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.Toast;
    
    import com.android.volley.DefaultRetryPolicy;
    import com.android.volley.Request;
    import com.android.volley.RequestQueue;
    import com.android.volley.Response;
    import com.android.volley.VolleyError;
    import com.android.volley.toolbox.StringRequest;
    import com.android.volley.toolbox.Volley;
    
    import org.json.JSONArray;
    import org.json.JSONException;
    import org.json.JSONObject;
    import java.util.ArrayList;
    
    public class SLByTopics extends Fragment {
    
    
        public static ArrayList<MByTopics> byTopicsMainArrayList=new ArrayList<>();
    
    
        TabRefreshReceiver tabRefreshReceiver;
        RecyclerView recyclerView;
        SAdpByTopics sAdpByTopics;
        public ArrayList<MByTopics> mByTopicsArrayList=new ArrayList<>();
        ProgressDialog progressDialog;
    
        public SLByTopics(){
        }
    
        @Override
        public void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
        }
    
        @Override
        public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
            View view = inflater.inflate(R.layout.sl_fragment_by_topics, container, false);
    
            progressDialog = new ProgressDialog(getActivity());
            if (IsOnline.isNetworkAvailable(getActivity())) {
                getCategoryTree();
            } else{
                IsOnline.showNoInterNetMessage(getActivity());
            }
            tabRefreshReceiver = new TabRefreshReceiver();
           LocalBroadcastManager.getInstance(getContext()).registerReceiver(tabRefreshReceiver, new IntentFilter("BY_TOPICS"));
    
            setUpView(view);
            return view;
        }
    
        private void setUpView(View view) {
    
            recyclerView=(RecyclerView)view.findViewById(R.id.by_topics_list_recyclerView);
            LinearLayoutManager linearLayoutManager=new LinearLayoutManager(getActivity());
            linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
            recyclerView.setLayoutManager(linearLayoutManager);
        }
    
        @Override
        public void onResume() {
            super.onResume();
    
            recyclerView.addOnItemTouchListener(new RecyclerItemClickListener(getActivity(), new RecyclerItemClickListener.OnItemClickListener() {
                @Override
                public void onItemClick(View view, final int position) {
    
                    if (mByTopicsArrayList.get(position).getChild().size()>0){
                        Intent intent = new Intent(getActivity(), SByTopicCategory.class);
                        intent.putExtra("selectedCategoryName",mByTopicsArrayList.get(position).getCatname());
                        intent.putExtra("jsonData",mByTopicsArrayList.get(position).getMainTopicJson());
                        startActivity(intent);
                        getActivity().overridePendingTransition(R.anim.activity_in, R.anim.activity_out);
                    }else {
                        Intent intent = new Intent(getActivity(), SByCategoryQuestionList.class);
                        intent.putExtra("selectedSubCategoryName",mByTopicsArrayList.get(position).getCatname());
                        intent.putExtra("catID",mByTopicsArrayList.get(position).getId());
                        startActivity(intent);
                        getActivity().overridePendingTransition(R.anim.activity_in, R.anim.activity_out);
                    }
                }
            }));
    
        }
    
        private class TabRefreshReceiver extends BroadcastReceiver {
            @Override
            public void onReceive(Context context, Intent intent) {
                try {
                    FragmentTransaction ft = getFragmentManager().beginTransaction();
                    ft.detach(SLByTopics.this).attach(SLByTopics.this).commit();
                    LocalBroadcastManager.getInstance(getContext()).unregisterReceiver(tabRefreshReceiver);
                } catch (Exception e) {
                    e.printStackTrace();
                }
    
            }
        }
    
        private void getCategoryTree() {
            progressDialog.setMessage("Please Wait...");
            progressDialog.setCancelable(false);
            progressDialog.show();
    
            StringRequest stringRequest = new StringRequest(Request.Method.POST, Const.HOSTNAME + Const.STUDENT_GET_CATEGORY_TREE,
                    new Response.Listener<String>() {
                        @SuppressLint("LongLogTag")
                        @Override
                        public void onResponse(String response) {
                            try {
                                JSONObject object = new JSONObject(response);
                                String status = object.getString("status");
                                int i = Integer.parseInt(status);
    
                                switch (i) {
    
                                    case 0:
                                        progressDialog.dismiss();
    //                                    Toast.makeText(getActivity(), "getCategorySuccess", Toast.LENGTH_SHORT).show();
                                        Log.e("getCategoryTree Response", "getCategoryTree Response : " + response);
    
                                        try {    
                                            byTopicsMainArrayList.clear();
                                            JSONArray info = object.getJSONArray("info");
                                            if (info.length() > 0) {
                                                for (i = 0; i < info.length(); i++) {
                                                    JSONObject data = info.getJSONObject(i);
                                                    MByTopics mByTopics = new MByTopics();
                                                    mByTopics.setId(data.getString("id"));
                                                    mByTopics.setCatname(data.getString("catname"));
                                                    mByTopics.setMainTopicJson(data.toString());
    
                                                    JSONArray topicChildren = data.getJSONArray("children");
                                                    ArrayList<SMByTopicCategory> byChildrenArrayList = new ArrayList<>();
    
                                                    for (int j = 0; j < topicChildren.length(); j++) {
                                                        JSONObject topicChildrenData = topicChildren.getJSONObject(j);
                                                        SMByTopicCategory smByTopicCategory = new SMByTopicCategory();
                                                        smByTopicCategory.setId(topicChildrenData.getString("id"));
                                                        smByTopicCategory.setCatname(topicChildrenData.getString("catname"));
                                                        smByTopicCategory.setChildTopicJson(topicChildrenData.toString());
    
                                                        JSONArray topicChildrenQuestion = topicChildrenData.getJSONArray("children");
                                                        ArrayList<SMByTopicSubCategory> byChildrenSubArrayList = new ArrayList<>();
    
                                                        for (int k = 0; k < topicChildrenQuestion.length(); k++) {
                                                            JSONObject topicChildrenSubData = topicChildrenQuestion.getJSONObject(k);
                                                            SMByTopicSubCategory smByTopicSubCategory = new SMByTopicSubCategory();
                                                            smByTopicSubCategory.setId(topicChildrenSubData.getString("id"));
                                                            smByTopicSubCategory.setCatname(topicChildrenSubData.getString("catname"));
                                                            smByTopicSubCategory.setChildSubTopicJson(topicChildrenSubData.toString());
    
                                                            byChildrenSubArrayList.add(smByTopicSubCategory);
                                                        }
    
                                                        smByTopicCategory.setQuestions(byChildrenSubArrayList);
    
                                                        byChildrenArrayList.add(smByTopicCategory);
                                                    }
                                                    mByTopics.setChild(byChildrenArrayList);
                                                    byTopicsMainArrayList.add(mByTopics);
                                                }
    
    
                                                mByTopicsArrayList.clear();
                                                mByTopicsArrayList=byTopicsMainArrayList;
                                                sAdpByTopics=new SAdpByTopics(mByTopicsArrayList,getActivity());
                                                recyclerView.setAdapter(sAdpByTopics);
                                                sAdpByTopics.notifyDataSetChanged();
    
                                            }
    
                                        }catch (Exception e){
                                            e.printStackTrace();
                                        }
                                        break;
    
                                    default:
                                        progressDialog.dismiss();
    //                                    Toast.makeText(getActivity(), "getCategoryError : " + response, Toast.LENGTH_SHORT).show();
                                        Log.e("getCategoryTree Not Response", "getCategoryTree Uploading Not Response : " + response);
                                }
    
                            } catch (JSONException e) {
                                e.printStackTrace();
                            }
                        }
                    },
                    new Response.ErrorListener() {
                        @Override
                        public void onErrorResponse(VolleyError error) {
                            progressDialog.dismiss();
                            Log.e("getCategoryTree Error :","getCategoryTree Error :"+error.getMessage());
    //                        Toast.makeText(getActivity(), error.getMessage(), Toast.LENGTH_LONG).show();
                        }
                    }){
    
            };/* {
                @Override
                protected Map<String, String> getParams() throws AuthFailureError {
    
                    Map<String, String> map = new HashMap<String, String>();
    //                map.put("uid", String.valueOf(ConfigManager.getUserId()));
                    return map;
                }
            };*/
    
            stringRequest.setRetryPolicy(new DefaultRetryPolicy(
                    0,
                    DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
                    DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
    
            RequestQueue requestQueue = Volley.newRequestQueue(getActivity());
            requestQueue.add(stringRequest);
        }
    }
    

    Adapter Class For Recycler Item

    import android.app.Activity;
    import android.support.v7.widget.RecyclerView;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.TextView;
    import java.util.ArrayList;
    
    public class SAdpByTopics extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
            ArrayList<MByTopics> topicsArrayList=new ArrayList<>();
            Activity activity;
    
         public SAdpByTopics(ArrayList<MByTopics> topicsArrayList,Activity activity){
            this.topicsArrayList=topicsArrayList;
            this.activity=activity;
         }
    
         @Override
         public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View itemeView= LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_by_topic_list,parent,false);
            RecyclerView.ViewHolder holder=new Holder(itemeView);
            holder.setIsRecyclable(false);
            return holder;
         }
    
         @Override
         public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
             final Holder classHolder = (Holder) holder;
             try{
                 classHolder.txt_topic_name.setText(topicsArrayList.get(position).getCatname());
             }catch (Exception e){
                 e.printStackTrace();
             }
         }
    
         @Override
         public int getItemCount() {
            return topicsArrayList.size();
         }
    
    
    class Holder extends RecyclerView.ViewHolder implements View.OnClickListener {
        TextView txt_topic_name;
    
        public Holder(View itemView) {
            super(itemView);
            txt_topic_name = (TextView) itemView.findViewById(R.id.txt_topic_name);
        }
    
        @Override
        public void onClick(View v) {
    
        }
    }
    }
    

    Module Class

    public class MByTopics {
    
        String id;
        String topicName;
        String catname;
        String MainTopicJson;
        ArrayList<SMByTopicCategory> child;
        ArrayList<SMByTopicSubCategory> questions;
    
        public void setId(String id){
            this.id=id;
        }
        public String getId(){
            return  id;
        }
    
        public void setCatname(String catname) {
            this.catname = catname;
        }
    
        public String getCatname() {
            return catname;
        }
    
        public void setTopicName(String topicName) {
            this.topicName = topicName;
        }
        public String getTopicName() {
            return topicName;
        }
    
        public void setChild(ArrayList<SMByTopicCategory> child) {
            this.child = child;
        }
    
        public String getMainTopicJson() {
            return MainTopicJson;
        }
    
        public void setMainTopicJson(String mainTopicJson) {
            MainTopicJson = mainTopicJson;
        }
    
        public ArrayList<SMByTopicCategory> getChild() {
            return child;
        }
    
        public void setQuestions(ArrayList<SMByTopicSubCategory> questions) {
            this.questions = questions;
        }
    
        public ArrayList<SMByTopicSubCategory> getQuestions() {
            return questions;
        }
    
        public ArrayList<MByTopics> getByTopicList() {
            ArrayList<MByTopics> mByTopicsArrayList = new ArrayList<>();
    
            for (int i=0;i<11;i++){
                MByTopics mQuestionBankCategory=new MByTopics();
    
                if (i==1 || i== 5|| i==9){
                    mQuestionBankCategory.setTopicName("Microeconomics");
                }else  if (i==2 || i== 10|| i==6) {
                    mQuestionBankCategory.setTopicName("Macroeconomics");
                }else {
                    mQuestionBankCategory.setTopicName("Current Isssues");
                }
    
                mByTopicsArrayList.add(mQuestionBankCategory);
            }
    
            return mByTopicsArrayList;
        }
    
    }
    
    0 讨论(0)
  • 2020-11-22 02:45

    Now you need 1 adapter for all RecyclerView

    • One adapter can be used in for all RecyclerView. So NO onBindViewHolder, No onCreateViewHolder handling.
    • No code for setting adapter from Java/Kotlin class. Check sample class.
    • You can set events and custom data for every list by using Binding Adapters.

    I show here setting two different RecyclerView by 1 adapter -

    activity_home.xml

    <?xml version="1.0" encoding="utf-8"?>
    <layout xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:app="http://schemas.android.com/apk/res-auto">
    
        <data>
    
            <variable
                name="listOne"
                type="java.util.List"/>
    
            <variable
                name="listTwo"
                type="java.util.List"/>
    
            <variable
                name="onItemClickListenerOne"
                type="com.ks.nestedrecyclerbindingexample.callbacks.OnItemClickListener"/>
    
            <variable
                name="onItemClickListenerTwo"
                type="com.ks.nestedrecyclerbindingexample.callbacks.OnItemClickListener"/>
    
        </data>
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">
    
            <android.support.v7.widget.RecyclerView
                rvItemLayout="@{@layout/row_one}"
                rvList="@{listOne}"
                rvOnItemClick="@{onItemClickListenerOne}"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                app:layoutManager="android.support.v7.widget.LinearLayoutManager"
                />
    
            <android.support.v7.widget.RecyclerView
                rvItemLayout="@{@layout/row_two}"
                rvList="@{listTwo}"
                rvOnItemClick="@{onItemClickListenerTwo}"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                app:layoutManager="android.support.v7.widget.LinearLayoutManager"
                />
    
        </LinearLayout>
    
    </layout>
    

    You can see I pass list, item layout id and click listener from layout.

    rvItemLayout="@{@layout/row_one}"
    rvList="@{listOne}"
    rvOnItemClick="@{onItemClickListenerOne}"
    

    This custom attributes are created by BindingAdapter.

    public class BindingAdapters {
        @BindingAdapter(value = {"rvItemLayout", "rvList", "rvOnItemClick"}, requireAll = false)
        public static void setRvAdapter(RecyclerView recyclerView, int rvItemLayout, List rvList, @Nullable OnItemClickListener onItemClickListener) {
            if (rvItemLayout != 0 && rvList != null && rvList.size() > 0)
                recyclerView.setAdapter(new GeneralAdapter(rvItemLayout, rvList, onItemClickListener));
        }
    }
    

    Now from Activity, you pass list, click listener like

    HomeActivity.java

    public class HomeActivity extends AppCompatActivity {
        ActivityHomeBinding binding;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            binding = DataBindingUtil.setContentView(this, R.layout.activity_home);
            binding.setListOne(new ArrayList()); // pass your list or set list from response of API
            binding.setListTwo(new ArrayList());
            binding.setOnItemClickListenerOne(new OnItemClickListener() {
                @Override
                public void onItemClick(View view, Object object) {
                    if (object instanceof ModelParent) {
                        // TODO: your action here
                    }
                }
            });
            binding.setOnItemClickListenerTwo(new OnItemClickListener() {
                @Override
                public void onItemClick(View view, Object object) {
                    if (object instanceof ModelChild) {
                        // TODO: your action here  
                    }
                }
            });
        }
    }
    

    You don't want read too much, directly clone/download full example on from my github repo. And try it yourself.

    You can see GeneralAdapter.java in above repo.

    If you have problems while setting up data binding, please see this answer.

    0 讨论(0)
  • 2020-11-22 02:48

    Based on different sources I have created Simple Implementation of RecyclerView using a Simple Library.

    Add this line in build.gradle

    implementation 'com.hereshem.lib:awesomelib:2.0.1'
    

    AddCreate a RecyclerView by adding MyRecyclerView in activity_main.xml with

    <com.hereshem.lib.recycler.MyRecyclerView
            android:id="@+id/recycler"
            app:layoutManager="LinearLayoutManager"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
    

    Now in the MainActivity, Create a ViewHolder by passing the name of Class that needs to bind

    public static class EVHolder extends MyViewHolder<Events> {
        TextView date, title, summary;
        public EVHolder(View v) {
            super(v);
            date = v.findViewById(R.id.date);
            title = v.findViewById(R.id.title);
            summary = v.findViewById(R.id.summary);
        }
        @Override
        public void bindView(Events c) {
            date.setText(c.date);
            title.setText(c.title);
            summary.setText(c.summary);
        }
    }
    

    Create Items list variable and adapters with very few lines by passing items, class and layout in the adapter

    List<Events> items = new ArrayList<>();
    MyRecyclerView recycler = findViewById(R.id.recycler);
    RecyclerViewAdapter adapter = new RecyclerViewAdapter(this, items, EVHolder.class, R.layout.row_event);
    recycler.setAdapter(adapter);
    

    ClickListener can be added with following lines

    recycler.setOnItemClickListener(new MyRecyclerView.OnItemClickListener() {
        @Override
        public void onItemClick(int position) {
            Toast.makeText(MainActivity.this, "Recycler Item Clicked " + position, Toast.LENGTH_SHORT).show();
        }
    });
    

    Its all done.

    More example and implementation can be found here . Hope this helps !!!

    0 讨论(0)
  • 2020-11-22 02:50

    You can use abstract adapter with diff utils and filter

    SimpleAbstractAdapter.kt

    abstract class SimpleAbstractAdapter<T>(private var items: ArrayList<T> = arrayListOf()) : RecyclerView.Adapter<SimpleAbstractAdapter.VH>() {
       protected var listener: OnViewHolderListener<T>? = null
       private val filter = ArrayFilter()
       private val lock = Any()
       protected abstract fun getLayout(): Int
       protected abstract fun bindView(item: T, viewHolder: VH)
       protected abstract fun getDiffCallback(): DiffCallback<T>?
       private var onFilterObjectCallback: OnFilterObjectCallback? = null
       private var constraint: CharSequence? = ""
    
    override fun onBindViewHolder(vh: VH, position: Int) {
        getItem(position)?.let { bindView(it, vh) }
    }
    
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VH {
        return VH(parent, getLayout())
    }
    
    override fun getItemCount(): Int = items.size
    
    protected abstract class DiffCallback<T> : DiffUtil.Callback() {
        private val mOldItems = ArrayList<T>()
        private val mNewItems = ArrayList<T>()
    
        fun setItems(oldItems: List<T>, newItems: List<T>) {
            mOldItems.clear()
            mOldItems.addAll(oldItems)
            mNewItems.clear()
            mNewItems.addAll(newItems)
        }
    
        override fun getOldListSize(): Int {
            return mOldItems.size
        }
    
        override fun getNewListSize(): Int {
            return mNewItems.size
        }
    
        override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
            return areItemsTheSame(
                    mOldItems[oldItemPosition],
                    mNewItems[newItemPosition]
            )
        }
    
        abstract fun areItemsTheSame(oldItem: T, newItem: T): Boolean
    
        override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
            return areContentsTheSame(
                    mOldItems[oldItemPosition],
                    mNewItems[newItemPosition]
            )
        }
    
        abstract fun areContentsTheSame(oldItem: T, newItem: T): Boolean
    }
    
    class VH(parent: ViewGroup, @LayoutRes layout: Int) : RecyclerView.ViewHolder(LayoutInflater.from(parent.context).inflate(layout, parent, false))
    
    interface OnViewHolderListener<T> {
        fun onItemClick(position: Int, item: T)
    }
    
    fun getItem(position: Int): T? {
        return items.getOrNull(position)
    }
    
    fun getItems(): ArrayList<T> {
        return items
    }
    
    fun setViewHolderListener(listener: OnViewHolderListener<T>) {
        this.listener = listener
    }
    
    fun addAll(list: List<T>) {
        val diffCallback = getDiffCallback()
        when {
            diffCallback != null && !items.isEmpty() -> {
                diffCallback.setItems(items, list)
                val diffResult = DiffUtil.calculateDiff(diffCallback)
                items.clear()
                items.addAll(list)
                diffResult.dispatchUpdatesTo(this)
            }
            diffCallback == null && !items.isEmpty() -> {
                items.clear()
                items.addAll(list)
                notifyDataSetChanged()
            }
            else -> {
                items.addAll(list)
                notifyDataSetChanged()
            }
        }
    }
    
    fun add(item: T) {
        items.add(item)
        notifyDataSetChanged()
    }
    
    fun add(position:Int, item: T) {
        items.add(position,item)
        notifyItemInserted(position)
    }
    
    fun remove(position: Int) {
        items.removeAt(position)
        notifyItemRemoved(position)
    }
    
    fun remove(item: T) {
        items.remove(item)
        notifyDataSetChanged()
    }
    
    fun clear(notify: Boolean=false) {
        items.clear()
        if (notify) {
            notifyDataSetChanged()
        }
    }
    
    fun setFilter(filter: SimpleAdapterFilter<T>): ArrayFilter {
        return this.filter.setFilter(filter)
    }
    
    interface SimpleAdapterFilter<T> {
        fun onFilterItem(contains: CharSequence, item: T): Boolean
    }
    
    fun convertResultToString(resultValue: Any): CharSequence {
        return filter.convertResultToString(resultValue)
    }
    
    fun filter(constraint: CharSequence) {
        this.constraint = constraint
        filter.filter(constraint)
    }
    
    fun filter(constraint: CharSequence, listener: Filter.FilterListener) {
        this.constraint = constraint
        filter.filter(constraint, listener)
    }
    
    fun getFilter(): Filter {
        return filter
    }
    
    interface OnFilterObjectCallback {
        fun handle(countFilterObject: Int)
    }
    
    fun setOnFilterObjectCallback(objectCallback: OnFilterObjectCallback) {
        onFilterObjectCallback = objectCallback
    }
    
    inner class ArrayFilter : Filter() {
        private var original: ArrayList<T> = arrayListOf()
        private var filter: SimpleAdapterFilter<T> = DefaultFilter()
        private var list: ArrayList<T> = arrayListOf()
        private var values: ArrayList<T> = arrayListOf()
    
    
        fun setFilter(filter: SimpleAdapterFilter<T>): ArrayFilter {
            original = items
            this.filter = filter
            return this
        }
    
        override fun performFiltering(constraint: CharSequence?): Filter.FilterResults {
            val results = Filter.FilterResults()
            if (constraint == null || constraint.isBlank()) {
                synchronized(lock) {
                    list = original
                }
                results.values = list
                results.count = list.size
            } else {
                synchronized(lock) {
                    values = original
                }
                val result = ArrayList<T>()
                for (value in values) {
                    if (constraint!=null && constraint.trim().isNotEmpty() && value != null) {
                        if (filter.onFilterItem(constraint, value)) {
                            result.add(value)
                        }
                    } else {
                        value?.let { result.add(it) }
                    }
                }
                results.values = result
                results.count = result.size
            }
            return results
        }
    
        override fun publishResults(constraint: CharSequence, results: Filter.FilterResults) {
            items = results.values as? ArrayList<T> ?: arrayListOf()
            notifyDataSetChanged()
            onFilterObjectCallback?.handle(results.count)
        }
    
    }
    
    class DefaultFilter<T> : SimpleAdapterFilter<T> {
        override fun onFilterItem(contains: CharSequence, item: T): Boolean {
            val valueText = item.toString().toLowerCase()
            if (valueText.startsWith(contains.toString())) {
                return true
            } else {
                val words = valueText.split(" ".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
                for (word in words) {
                    if (word.contains(contains)) {
                        return true
                    }
                }
            }
            return false
        }
      }
    }
    

    And extend abstract adapter with implements methods

    TasksAdapter.kt

    import android.annotation.SuppressLint
      import kotlinx.android.synthetic.main.task_item_layout.view.*
    
    class TasksAdapter(private val listener:TasksListener? = null) : SimpleAbstractAdapter<Task>() {
    override fun getLayout(): Int {
        return R.layout.task_item_layout
    }
    
    override fun getDiffCallback(): DiffCallback<Task>? {
        return object : DiffCallback<Task>() {
            override fun areItemsTheSame(oldItem: Task, newItem: Task): Boolean {
                return oldItem.id == newItem.id
            }
    
            override fun areContentsTheSame(oldItem: Task, newItem: Task): Boolean {
                return oldItem.items == newItem.items
            }
        }
    }
    
    @SuppressLint("SetTextI18n")
    override fun bindView(item: Task, viewHolder: VH) {
        viewHolder.itemView.apply {
            val position = viewHolder.adapterPosition
            val customer = item.customer
            val customerName = if (customer != null) customer.name else ""
            tvTaskCommentTitle.text = customerName + ", #" + item.id
            tvCommentContent.text = item.taskAddress
            ivCall.setOnClickListener {
                listener?.onCallClick(position, item)
            }
            setOnClickListener {
                listener?.onItemClick(position, item)
            }
        }
    }
    
     interface TasksListener : SimpleAbstractAdapter.OnViewHolderListener<Task> {
        fun onCallClick(position: Int, item: Task)
     }
    }
    

    Init adapter

    mAdapter = TasksAdapter(object : TasksAdapter.TasksListener {
                override fun onCallClick(position: Int, item:Task) {
                }
    
                override fun onItemClick(position: Int, item:Task) {
    
                }
            })
    rvTasks.adapter = mAdapter
    

    and fill

    mAdapter?.addAll(tasks)
    

    add custom filter

    mAdapter?.setFilter(object : SimpleAbstractAdapter.SimpleAdapterFilter<MoveTask> {
                override fun onFilterItem(contains: CharSequence, item:Task): Boolean {
                    return contains.toString().toLowerCase().contains(item.id?.toLowerCase().toString())
                }
        })
    

    filter data

    mAdapter?.filter("test")
    
    0 讨论(0)
提交回复
热议问题