我用Android的RecyclerView做过几次物品列表,但这是一个相当复杂的过程。浏览众多在线教程中的一个作品(这个,这个,这个都很好),但我正在寻找一个简单的示例,我可以复制和粘贴来快速启动和运行。只需要以下特性:
垂直布局 每行都有一个单一的TextView 响应点击事件
因为这个愿望我已经许过好几次了,所以我最终决定把答案写在下面,供我和你们将来参考。
我用Android的RecyclerView做过几次物品列表,但这是一个相当复杂的过程。浏览众多在线教程中的一个作品(这个,这个,这个都很好),但我正在寻找一个简单的示例,我可以复制和粘贴来快速启动和运行。只需要以下特性:
垂直布局 每行都有一个单一的TextView 响应点击事件
因为这个愿望我已经许过好几次了,所以我最终决定把答案写在下面,供我和你们将来参考。
当前回答
依赖关系
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'
一个类为点击项目
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) {
}
}
第二个类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);
}
}
适配器类回收项目
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) {
}
}
}
模块类
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;
}
}
其他回答
您可以使用带有diff utils和过滤器的抽象适配器
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
}
}
}
并利用实现方法对抽象适配器进行扩展
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)
}
}
初始化适配器
mAdapter = TasksAdapter(object : TasksAdapter.TasksListener {
override fun onCallClick(position: Int, item:Task) {
}
override fun onItemClick(position: Int, item:Task) {
}
})
rvTasks.adapter = mAdapter
并填写
mAdapter?.addAll(tasks)
添加自定义过滤器
mAdapter?.setFilter(object : SimpleAbstractAdapter.SimpleAdapterFilter<MoveTask> {
override fun onFilterItem(contains: CharSequence, item:Task): Boolean {
return contains.toString().toLowerCase().contains(item.id?.toLowerCase().toString())
}
})
过滤数据
mAdapter?.filter("test")
基于不同的资源,我使用简单库创建了RecyclerView的简单实现。
在build.gradle中添加这一行
implementation 'com.hereshem.lib:awesomelib:2.0.1'
通过在activity_main.xml中添加MyRecyclerView来创建一个RecyclerView
<com.hereshem.lib.recycler.MyRecyclerView
android:id="@+id/recycler"
app:layoutManager="LinearLayoutManager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
现在在MainActivity中,通过传递需要绑定的类的名称来创建一个ViewHolder
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);
}
}
通过在适配器中传递项目、类和布局来创建Items列表变量和适配器,行数很少
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可以用以下几行添加
recycler.setOnItemClickListener(new MyRecyclerView.OnItemClickListener() {
@Override
public void onItemClick(int position) {
Toast.makeText(MainActivity.this, "Recycler Item Clicked " + position, Toast.LENGTH_SHORT).show();
}
});
都搞定了。
更多示例和实现可以在这里找到。 希望这能有所帮助!!
依赖关系
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'
一个类为点击项目
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) {
}
}
第二个类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);
}
}
适配器类回收项目
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) {
}
}
}
模块类
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;
}
}
实现androidx.recyclerview: recyclerview:… 建议更新到下面的androidx库:
https://developer.android.com/jetpack/androidx/releases/recyclerview
布局文件Widget XML标签必须更新为: androidx.recyclerview.widget.RecyclerView
由于我还不能评论,我将发布一个链接的答案..我在recyclerview上找到了一个简单、组织良好的教程 http://www.androiddeft.com/2017/10/01/recyclerview-android/
除此之外,当你要在你的活动中添加一个回收器视图时,你想做的事情如下所示,你应该如何做,已经在链接中描述了
将RecyclerView组件添加到布局文件中 创建一个要显示为列表行的类 制作一个布局文件,这是你列表中的一行的布局 现在我们需要一个自定义适配器,因此通过扩展来创建一个自定义适配器 从父类RecyclerView。适配器 在mainActivity oncreate中添加recyclerview 添加分隔符 添加Touch监听器