ตัวอย่างง่ายๆของ Android RecyclerView


170

ฉันทำรายการสิ่งของสองสามครั้งโดยใช้ Android RecyclerViewแต่เป็นกระบวนการที่ค่อนข้างซับซ้อน ผ่านหนึ่งในบทเรียนออนไลน์มากมาย ( นี่คือสิ่งนี้และสิ่งนี้ดี) แต่ฉันกำลังมองหาตัวอย่างกระดูกเปลือยที่ฉันสามารถคัดลอกและวางเพื่อเริ่มใช้งานได้อย่างรวดเร็ว จำเป็นต้องใช้คุณสมบัติต่อไปนี้เท่านั้น:

  • เค้าโครงแนวตั้ง
  • TextView เดียวในแต่ละแถว
  • ตอบสนองต่อการคลิกเหตุการณ์

เพราะฉันต้องการหลายต่อหลายครั้งในที่สุดฉันก็ตัดสินใจที่จะตอบคำถามด้านล่างนี้เพื่อใช้อ้างอิงและในอนาคต




1
สำหรับคนในอนาคตที่นี่ฉันได้เขียนบทความรายละเอียดพร้อมวิดีโอสอนhandyopinion.com/ ...
Asad Ali Choudhry

youtu.be/UZwiKdrm768 : คุณสามารถเช็คเอาต์วิดีโอสอนนี้ตามที่อธิบายในรายละเอียดเกี่ยวกับ recyclerview:
chandu vutukuri

คำตอบ:


387

ต่อไปนี้เป็นตัวอย่างเล็กน้อยที่จะมีลักษณะดังภาพต่อไปนี้

RecyclerView พร้อมรายชื่อสัตว์

เริ่มต้นด้วยกิจกรรมที่ว่างเปล่า คุณจะทำงานต่อไปนี้เพื่อเพิ่ม RecyclerView สิ่งที่คุณต้องทำคือคัดลอกและวางรหัสในแต่ละส่วน หลังจากนั้นคุณสามารถปรับแต่งมันให้เหมาะกับความต้องการของคุณ

  • เพิ่มการพึ่งพาเพื่อไล่ระดับ
  • เพิ่มไฟล์โครงร่าง xml สำหรับกิจกรรมและสำหรับแถว RecyclerView
  • สร้างอะแดปเตอร์ RecyclerView
  • เริ่มต้น RecyclerView ในกิจกรรมของคุณ

อัปเดตการอ้างอิง Gradle

ตรวจสอบให้แน่ใจว่าการพึ่งพาต่อไปนี้อยู่ในgradle.buildไฟล์แอปของคุณ:

implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support:recyclerview-v7:28.0.0'

คุณสามารถปรับปรุงหมายเลขเวอร์ชันเพื่อสิ่งที่เป็นปัจจุบันมากที่สุด ใช้compileแทนimplementationถ้าคุณยังใช้ Android Studio 2.x

สร้างโครงร่างกิจกรรม

เพิ่มRecyclerViewไปยังเค้าโครง xml ของคุณ

activity_main.xml

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

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rvAnimals"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</RelativeLayout>

สร้างเค้าโครงแถว

แต่ละแถวในเราRecyclerViewจะมีเพียงแถวเดียวTextViewเท่านั้น สร้างไฟล์รีซอร์สเลย์เอาต์ใหม่

recyclerview_row.xml

<?xml version="1.0" encoding="utf-8"?>
<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">

    <TextView
        android:id="@+id/tvAnimalName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="20sp"/>

</LinearLayout>

สร้างอะแดปเตอร์

RecyclerViewต้องการอะแดปเตอร์เพื่อเติมมุมมองในแต่ละแถวที่มีข้อมูลของคุณ สร้างไฟล์ java ใหม่

MyRecyclerViewAdapter.java

public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.ViewHolder> {

    private List<String> mData;
    private LayoutInflater mInflater;
    private ItemClickListener mClickListener;

    // data is passed into the constructor
    MyRecyclerViewAdapter(Context context, List<String> data) {
        this.mInflater = LayoutInflater.from(context);
        this.mData = data;
    }

    // inflates the row layout from xml when needed
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = mInflater.inflate(R.layout.recyclerview_row, parent, false);
        return new ViewHolder(view);
    }

    // binds the data to the TextView in each row
    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        String animal = mData.get(position);
        holder.myTextView.setText(animal);
    }

    // total number of rows
    @Override
    public int getItemCount() {
        return mData.size();
    }


    // stores and recycles views as they are scrolled off screen
    public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        TextView myTextView;

        ViewHolder(View itemView) {
            super(itemView);
            myTextView = itemView.findViewById(R.id.tvAnimalName);
            itemView.setOnClickListener(this);
        }

        @Override
        public void onClick(View view) {
            if (mClickListener != null) mClickListener.onItemClick(view, getAdapterPosition());
        }
    }

    // convenience method for getting data at click position
    String getItem(int id) {
        return mData.get(id);
    }

    // allows clicks events to be caught
    void setClickListener(ItemClickListener itemClickListener) {
        this.mClickListener = itemClickListener;
    }

    // parent activity will implement this method to respond to click events
    public interface ItemClickListener {
        void onItemClick(View view, int position);
    }
}

หมายเหตุ

  • แม้ว่าจะไม่จำเป็นอย่างเด็ดขาด แต่ฉันได้รวมฟังก์ชันการฟังเพื่อคลิกเหตุการณ์ไว้ในแถว นี่เป็นรุ่นเก่าListViewsและเป็นความต้องการทั่วไป คุณสามารถลบรหัสนี้ได้หากคุณไม่ต้องการ

เริ่มต้น RecyclerView ในกิจกรรม

เพิ่มรหัสต่อไปนี้ลงในกิจกรรมหลักของคุณ

MainActivity.java

public class MainActivity extends AppCompatActivity implements MyRecyclerViewAdapter.ItemClickListener {

    MyRecyclerViewAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // data to populate the RecyclerView with
        ArrayList<String> animalNames = new ArrayList<>();
        animalNames.add("Horse");
        animalNames.add("Cow");
        animalNames.add("Camel");
        animalNames.add("Sheep");
        animalNames.add("Goat");

        // set up the RecyclerView
        RecyclerView recyclerView = findViewById(R.id.rvAnimals);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        adapter = new MyRecyclerViewAdapter(this, animalNames);
        adapter.setClickListener(this);
        recyclerView.setAdapter(adapter);
    }

    @Override
    public void onItemClick(View view, int position) {
        Toast.makeText(this, "You clicked " + adapter.getItem(position) + " on row number " + position, Toast.LENGTH_SHORT).show();
    }
}

หมายเหตุ

  • ขอให้สังเกตว่ากิจกรรมดำเนินการตามItemClickListenerที่เรากำหนดไว้ในอะแดปเตอร์ของเรา onItemClickนี้ช่วยให้เราจัดการกับเหตุการณ์แถวคลิก

เสร็จ

แค่นั้นแหละ. คุณควรจะสามารถเรียกใช้โครงการของคุณตอนนี้และรับสิ่งที่คล้ายกับภาพที่ด้านบน

กำลังเกิดขึ้น

การเพิ่มตัวแบ่งระหว่างแถว

คุณสามารถเพิ่มตัวแบ่งเรียบง่ายเช่นนี้

DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(),
    layoutManager.getOrientation());
recyclerView.addItemDecoration(dividerItemDecoration);

หากคุณต้องการบางสิ่งที่ซับซ้อนกว่านี้เล็กน้อยให้ดูคำตอบต่อไปนี้:

การเปลี่ยนสีของแถวเมื่อคลิก

ดูคำตอบนี้สำหรับวิธีการเปลี่ยนสีพื้นหลังและเพิ่มเอฟเฟกต์ระลอกคลื่นเมื่อคลิกแถว

แทรกรายการเดียว

กำลังอัปเดตแถว

ดูคำตอบสำหรับวิธีเพิ่มลบและอัปเดตแถว

แทรกรายการเดียว

อ่านเพิ่มเติม


1
ดีมาก. ใช้งานได้จนกว่าฉันจะเพิ่มปุ่มและพยายามตั้งค่าฟังการคลิก ความคิดใด ๆ ที่อาจรบกวน?
john ktejik

1
@johnktejik มันยากที่จะรู้ว่าสิ่งที่คุณกำลังพูดถึงจากข้อมูลที่คุณให้ที่นี่ นี่อาจจะถูกถามว่าเป็นคำถามใหม่ที่ดีที่สุด ฉันเดาว่าปุ่มของคุณกำลังจัดการเหตุการณ์การเคลื่อนไหวเพื่อให้สิ่งอื่นไม่ได้รับ
Suragch

1
ขอโทษ .. ที่จะเพิ่มคำอธิบายของสัตว์? EX: อูฐใน TextView ใหม่: เป็นสัตว์ // แกะใน TextVire ใหม่: เป็นสัตว์ ฉันต้องการความช่วยเหลือ .. T_T
Montse Mkd

2
@ โคเดอร์, ไม่เป็นไร ใช่ฉันใช้สิ่งนี้ในการแสดงผลในแนวนอนและใช้งานได้เหมือนกัน
Suragch

4
คำตอบนี้ต้องการการอัปเดตเป็น androidx
Jose Alcérreca

7

มุมมอง Recycler ขั้นต่ำพร้อมที่จะใช้เทมเพลต Kotlin สำหรับ:

  • เค้าโครงแนวตั้ง
  • TextView เดียวในแต่ละแถว
  • ตอบสนองต่อการคลิกเหตุการณ์ (Single และ LongPress)

ฉันรู้ว่านี่เป็นหัวข้อเก่าและเป็นคำตอบที่นี่ การเพิ่มคำตอบนี้สำหรับการอ้างอิงในอนาคต:

เพิ่มมุมมองรีไซเคิลในเค้าโครงของคุณ

   <android.support.v7.widget.RecyclerView
            android:id="@+id/wifiList"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
           /> 

สร้างเค้าโครงเพื่อแสดงรายการ (list_item.xml)

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <LinearLayout
        android:padding="5dp"
        android:layout_width="match_parent"
        android:orientation="vertical"
        android:layout_height="wrap_content">

        <android.support.v7.widget.AppCompatTextView
            android:id="@+id/ssid"
            android:text="@string/app_name"
            android:layout_width="match_parent"
            android:textSize="17sp"
            android:layout_height="wrap_content" />

    </LinearLayout>

</android.support.v7.widget.CardView>

ตอนนี้สร้างอแด็ปเตอร์น้อยที่สุดเพื่อเก็บข้อมูลรหัสที่นี่เป็นคำอธิบายตัวเอง

 class WifiAdapter(private val wifiList: ArrayList<ScanResult>) : RecyclerView.Adapter<WifiAdapter.ViewHolder>() {

     // holder class to hold reference
    inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        //get view reference
        var ssid: TextView = view.findViewById(R.id.ssid) as TextView
    }

     override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
         // create view holder to hold reference
         return ViewHolder( LayoutInflater.from(parent.context).inflate(R.layout.list_item, parent, false))
     }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        //set values
        holder.ssid.text =  wifiList[position].SSID
    }

    override fun getItemCount(): Int {
        return wifiList.size
    }
      // update your data
     fun updateData(scanResult: ArrayList<ScanResult>) {
         wifiList.clear()
         notifyDataSetChanged()
         wifiList.addAll(scanResult)
         notifyDataSetChanged()

     }
 }

เพิ่มคลาสนี้เพื่อจัดการคลิกเดียวและกิจกรรมคลิกยาวในรายการ

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;

public class RecyclerTouchListener implements RecyclerView.OnItemTouchListener {

    public interface ClickListener {
        void onClick(View view, int position);

        void onLongClick(View view, RecyclerView recyclerView, int position);

    }
    private GestureDetector gestureDetector;
    private ClickListener clickListener;

    public RecyclerTouchListener(Context context, final RecyclerView recyclerView, final ClickListener clickListener) {
        this.clickListener = clickListener;
        gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
            @Override
            public boolean onSingleTapUp(MotionEvent e) {
                return true;
            }

            @Override
            public void onLongPress(MotionEvent e) {
                View child = recyclerView.findChildViewUnder(e.getX(), e.getY());
                if (child != null && clickListener != null) {
                    clickListener.onLongClick(child,recyclerView,  recyclerView.getChildPosition(child));
                }
            }
        });
    }


    @Override
    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
        View child = rv.findChildViewUnder(e.getX(), e.getY());
        if (child != null && clickListener != null && gestureDetector.onTouchEvent(e)) {
            clickListener.onClick(child, rv.getChildPosition(child));
        }
        return false;
    }

    @Override
    public void onTouchEvent(RecyclerView rv, MotionEvent e) {

    }

    @Override
    public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {

    }

ตั้งค่าอะแดปเตอร์ของคุณเป็น Recycler View และเพิ่ม Touch Listener เพื่อเริ่มการดักจับเหตุการณ์แตะครั้งเดียวหรือสองครั้งในรายการ

    wifiAdapter = WifiAdapter(ArrayList())

    wifiList.apply {
        // vertical layout
        layoutManager = LinearLayoutManager(applicationContext)
        // set adapter
        adapter = wifiAdapter

        // Touch handling
        wifiList.addOnItemTouchListener(RecyclerTouchListener(applicationContext, wifiList, object : RecyclerTouchListener.ClickListener {
            override fun onClick(view: View?, position: Int) {
                Toast.makeText(applicationContext, "RV OnCLickj " + position, Toast.LENGTH_SHORT).show()
            }

            override fun onLongClick(view: View, recyclerView: RecyclerView, position: Int) {
                Toast.makeText(applicationContext, "RV OnLongCLickj " + position, Toast.LENGTH_SHORT).show()
            }
        }
        ))
    }

โบนัส; อัปเดตข้อมูล

wifiAdapter.updateData(mScanResults as ArrayList<ScanResult>)

ผลลัพธ์:

ป้อนคำอธิบายรูปภาพที่นี่


5

นี่จะเป็นเวอร์ชันที่ง่ายที่สุดในการติดตั้ง RecyclerView

ป้อนคำอธิบายรูปภาพที่นี่

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.recyclerview.widget.RecyclerView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/recycler_view"/>

</FrameLayout>

list_item_view.xml

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

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/textview"
        android:text="TextView"
        android:textSize="16dp" />

</LinearLayout>

CustomAdapter.java

public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.ViewHolder> {
  private List<String> data;
  public CustomAdapter (List<String> data){
    this.data = data;
  }

  @Override
  public CustomAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View rowItem = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_view, parent, false);
    return new ViewHolder(rowItem);
  }

  @Override
  public void onBindViewHolder(CustomAdapter.ViewHolder holder, int position) {
    holder.textView.setText(this.data.get(position));
  }

  @Override
  public int getItemCount() {
    return this.data.size();
  }

  public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
    private TextView textView;

    public ViewHolder(View view) {
      super(view);
      view.setOnClickListener(this);
      this.textView = view.findViewById(R.id.textview);
    }

    @Override
    public void onClick(View view) {
      Toast.makeText(view.getContext(), "position : " + getLayoutPosition() + " text : " + this.textView.getText(), Toast.LENGTH_SHORT).show();
    }
  }
}

MainActivity.java

public class MainActivity extends AppCompatActivity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    RecyclerView recyclerView = findViewById(R.id.recycler_view);
    
    recyclerView.setLayoutManager(new LinearLayoutManager(this));
    recyclerView.setAdapter(new CustomAdapter(generateData()));
    recyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
  }

  private List<String> generateData() {
    List<String> data = new ArrayList<>();
    for (int i = 0; i < 100; i++) {
      data.add(String.valueOf(i) + "th Element");
    }
    return data;
  }

}

5

Android RecyclerView

เริ่มต้นด้วยการเพิ่มไลบรารีวิวไลบรารี

implementation 'androidx.recyclerview:recyclerview:1.1.0'

สร้างคลาสโมเดล

     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;
    }
   }

สร้างคลาสอะแดปเตอร์

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()));
                }
            });


        }
    }
}

สร้างเค้าโครง 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>

ค้นหา recyclerview และเติมข้อมูล

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);

}

ค้นหาบทแนะนำแบบเต็มและซอร์สโค้ดที่นี่:

Android RecyclerView


ทำไมคุณถึงส่งบริบทไปที่คลาสอะแดปเตอร์ผู้ใช้ usersAdapter = new UsersAdapter(userModelList,this);?
Omar Boshra

4

ฉันได้สร้าง Simple Implementation ของ RecyclerView โดยใช้แหล่งข้อมูลที่แตกต่างกันโดยใช้ Simple Library

เพิ่มบรรทัดนี้ใน build.gradle

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

เพิ่มสร้าง RecyclerView โดยเพิ่ม MyRecyclerView ใน activity_main.xml ด้วย

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

ตอนนี้ใน MainActivity สร้าง ViewHolder โดยส่งชื่อของ Class ที่ต้องการผูก

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);
    }
}

สร้างตัวแปรรายการไอเท็มและอะแด็ปเตอร์ที่มีบรรทัดน้อยมากโดยผ่านไอเท็มคลาสและโครงร่างในอะแด็ปเตอร์

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();
    }
});

มันทำทั้งหมดแล้ว

ตัวอย่างอื่น ๆ และการดำเนินงานที่สามารถพบได้ที่นี่ หวังว่านี่จะช่วย !!!


1
กิจกรรมเดี่ยวคืออะไร
john ktejik

1
: ข้อผิดพลาด: ไม่สามารถหาสัญลักษณ์สรุป = v.findViewById (R.id.summary); สัญลักษณ์ ^: ตำแหน่งสรุปตัวแปร: คลาสรหัส EVHolder.java:15: ข้อผิดพลาด: วิธีการไม่ได้แทนที่หรือใช้วิธีการจาก supertype @Override ^ EVHolder.java:17: ข้อผิดพลาด: ไม่สามารถหา date date.setText (c.date) ;
john ktejik

1
@johnktejik R.id.summary เป็นรหัสที่กำหนดไว้สำหรับไฟล์ทรัพยากรรูปแบบ โปรดดูไฟล์เลย์เอาต์นี้github.com/hereshem/Easy-RecyclerView-Library/blob/master/app/…
Hem Shrestha

3

ตอนนี้คุณต้องมี1 อะแดปเตอร์สำหรับทุกคนRecyclerView

  • หนึ่งอะแดปเตอร์สามารถใช้ในทุก RecyclerView ดังนั้นNO onBindViewHolder , ไม่มี onCreateViewHolderการจัดการ
  • ไม่มีรหัสสำหรับการตั้งค่าอะแดปเตอร์จากคลาส Java / Kotlin ตรวจสอบระดับตัวอย่าง
  • คุณสามารถตั้งค่าเหตุการณ์และข้อมูลที่กำหนดเองสำหรับทุกรายการโดยใช้อะแดปเตอร์เข้าเล่ม

ภาพหน้าจอ

ฉันแสดงที่นี่การตั้งค่าที่แตกต่างกันสองRecyclerViewโดย 1 อะแดปเตอร์ -

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>

คุณสามารถเห็นฉันผ่านรายการรหัสโครงร่างรายการและคลิกฟังจากเค้าโครง

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

แอตทริบิวต์ที่กำหนดเองนี้ถูกสร้างขึ้นโดย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));
    }
}

ตอนนี้จากกิจกรรมคุณส่งรายการคลิกฟังเหมือน

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  
                }
            }
        });
    }
}

คุณไม่ต้องการอ่านมากเกินไปโคลน / ดาวน์โหลดตัวอย่างเต็มโดยตรงจาก gitub repo ของฉัน และลองด้วยตัวคุณเอง

คุณสามารถดูได้GeneralAdapter.javaใน repo ด้านบน

หากคุณมีปัญหาในขณะตั้งค่าการเชื่อมโยงข้อมูลโปรดดูคำตอบนี้


2

เนื่องจากฉันไม่สามารถแสดงความคิดเห็นได้ แต่ฉันจะโพสต์เป็นคำตอบลิงก์ .. ฉันพบวิธีการสอนที่เรียบง่ายและจัดระเบียบอย่างดีบน recyclerview http://www.androiddeft.com/2017/10/01/recyclerview-android/

นอกเหนือจากนั้นเมื่อคุณจะเพิ่มมุมมองของนักรีไซเคิลในกิจกรรมที่คุณต้องการทำคือด้านล่างและวิธีที่คุณควรทำสิ่งนี้ได้รับการอธิบายในลิงค์

  • เพิ่มส่วนประกอบ RecyclerView ลงในไฟล์เลย์เอาต์ของคุณ
  • สร้างคลาสที่คุณจะแสดงเป็นแถวรายการ
  • ทำไฟล์เลย์เอาต์ซึ่งเป็นเลย์เอาต์ของแถวของคุณ
  • ตอนนี้เราจำเป็นต้องใช้อะแดปเตอร์ที่กำหนดเองเพื่อสร้างอะแดปเตอร์ที่กำหนดเองโดยการขยายจากระดับผู้ปกครอง RecyclerView.Adapter
  • เพิ่ม recyclerview ลงใน mainActivity ของคุณ
  • เพิ่มตัวคั่น
  • เพิ่มตัวฟัง Touch

2

คุณสามารถใช้อะแดปเตอร์นามธรรมพร้อมตัวกรองและตัวกรองที่ต่างกัน

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")

เพิ่มการเปลี่ยนแปลงบางอย่างด้วย diff utils เพิ่มการสนับสนุนประเภทgist.github.com/arnyigor/568035c6db9bdbeaf609b68a71834349
Igor Arny

1

การอ้างอิง

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);
    }
}

คลาส Adaptor สำหรับรายการ Recycler

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;
    }

}

3
คำอธิบายจะดี
ThomasEdwin

1

การดำเนินการ androidx.recyclerview: recyclerview: .... ขอแนะนำให้อัปเดตเป็นห้องสมุด androidx ซึ่งอยู่ที่นี่:

https://developer.android.com/jetpack/androidx/releases/recyclerview

จากนั้นเลย์เอาต์แท็ก Widget XML ของไฟล์ต้องอัปเดตเป็น: androidx.recyclerview.widget.RecyclerView


คุณถูก. ฉันต้องการอัปเดตคำตอบด้วย AndroidX
Suragch

1

นี่เป็นวิธีแก้ปัญหา Kotlin รุ่นใหม่ซึ่งง่ายกว่าคำตอบมากมายที่เขียนไว้ที่นี่โดยใช้คลาสที่ไม่ระบุชื่อ

val items = mutableListOf<String>()

inner class ItemHolder(view: View): RecyclerView.ViewHolder(view) {
    var textField: TextView = view.findViewById(android.R.id.text1) as TextView
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    rvitems.layoutManager = LinearLayoutManager(context)
    rvitems.adapter = object : RecyclerView.Adapter<ItemHolder>() {

        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemHolder {
            return ItemHolder(LayoutInflater.from(parent.context).inflate(android.R.layout.simple_list_item_1, parent, false))
        }

        override fun getItemCount(): Int {
            return items.size
        }

        override fun onBindViewHolder(holder: ItemHolder, position: Int) {
            holder.textField.text = items[position]
            holder.textField.setOnClickListener {
                Toast.makeText(context, "Clicked $position", Toast.LENGTH_SHORT).show()
            }
        }
    }
}

ฉันใช้เสรีภาพในการใช้android.R.layout.simple_list_item_1เพราะมันง่ายกว่า ฉันต้องการทำให้มันง่ายยิ่งขึ้นและวาง ItemHolder เป็นคลาสภายใน แต่ไม่สามารถหาวิธีการอ้างอิงในประเภทในพารามิเตอร์คลาสภายนอกได้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.