이 튜토리얼에서 우리는 체크박스나 라디오버튼이 있는 커스텀 리사이클러뷰를 만들고 사용하는 방법과 그 상태를 처리하는 방법을 살펴볼 것입니다.

배울 개념

이 튜토리얼은 예제를 통해 다음을 배우는 것을 목표로 합니다.

  1. 체크박스나 라디오버튼으로 리사이클러뷰를 생성하고 상태를 적절하게 처리하는 방법.
  2. 부울 데이터를 포함하여 mysql 데이터베이스의 데이터를 체크박스가 있는 재활용 보기에서 렌더링하는 방법.
  3. 체크/비체크 상태를 유지하면서 체크박스로 리사이클러뷰를 검색/필터링하는 방법.

데모

다음은 생성될 데모 중 일부입니다.

체크박스 데모

코틀린 RecyclerView 체크박스 예시

라디오 버튼 데모

Android RecyclerView RadioButton 예

예제 1: Android RecyclerView 체크박스 – 체크 상태 유지

이것은 안드로이드 리사이클러뷰 체크박스 튜토리얼입니다. cardview를 사용하여 사용자 정의 재활용 보기에서 확인란, 이미지 및 텍스트를 먼저 렌더링하는 방법을 보고 싶습니다. 그런 다음 선택되거나 확인된 카드 보기를 가져오고 토스트 메시지를 표시합니다. 여러 확인란을 사용하여 RecyclerView에서 항목을 다중 선택하거나 단일 선택할 수 있습니다.

이것은 체크박스를 사용하여 cardview를 재활용함에도 불구하고 리사이클러뷰에서 체크박스의 체크 상태를 적절하게 유지하는 방법을 알려줄 것입니다.

그런 다음 사용자는 부동 작업 버튼을 클릭하여 선택한 항목을 가져오고 토스트 메시지에 표시할 수 있습니다.

1단계: 종속성

이 프로젝트에는 특별한 종속성이 필요하지 않습니다. 우리가 사용하는 것은 recyclerview 및 cardview와 같은 표준 androidx 종속성뿐입니다.

2단계: 기본 활동 레이아웃 만들기

활동_main.xml

이것은 우리의 주요 활동 레이아웃이 될 것이며 XML로 작성합니다. XML은 사용자 인터페이스를 생성할 뿐만 아니라 데이터를 교환하는 데 사용되는 마크업 언어입니다. 이 경우 Android 사용자 인터페이스를 생성하는 데 사용합니다.

이 레이아웃은 우리의 주요 활동으로 확장될 것입니다. 루트에는 RelativeLayout이 있습니다.

Android 애플리케이션의 제목을 표시하기 위한 headerTextView인 TextView가 있습니다.

그런 다음 이 경우 어댑터 뷰인 RecyclerView가 있습니다. 이 RecyclerView는 이미지, 텍스트 및 확인란을 렌더링합니다.

RecyclerView 아래에는 FloatingActionButton이 있습니다. 사용자가 이 FAB 버튼을 클릭하면 재활용 보기에서 선택한 항목이 표시됩니다. 우리의 리사이클러뷰는 이미지, 텍스트, 체크박스가 있는 카드뷰로 구성될 것임을 기억하십시오.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout

    android_layout_width="match_parent"
    android_layout_height="match_parent"
    tools_context="info.camposha.checkablerecyclerviews.MainActivity">

    <TextView
        android_id="@+id/headerTextView"
        android_layout_width="match_parent"
        android_layout_height="wrap_content"
        android_text="Spiritual Teachers"
        android_textAlignment="center"
        android_textAppearance="@style/TextAppearance.AppCompat.Large"
        android_textColor="@color/colorAccent" />

    <androidx.recyclerview.widget.RecyclerView
        android_id="@+id/myRecycler"
        android_layout_width="match_parent"
        android_layout_height="wrap_content"
        android_layout_alignParentLeft="true"
        android_layout_alignParentStart="true"
        android_layout_below="@+id/headerTextView"
        android_layout_marginTop="30dp" />

    <android.support.design.widget.FloatingActionButton
        android_id="@+id/fab"
        android_layout_width="wrap_content"
        android_layout_height="wrap_content"
        android_layout_alignParentBottom="true"
        android_layout_alignParentEnd="true"
        android_layout_alignParentRight="true"
        android_layout_gravity="bottom|end"
        android_src="@android:drawable/ic_dialog_email" />

</RelativeLayout>

3단계: RecyclerView 항목 만들기

모델.xml

이 레이아웃은 리사이클러 뷰의 다른 카드들 사이에서 렌더링될 단일 카드뷰를 모델링할 것입니다.

이 레이아웃은 이러한 모든 카드뷰를 모델링합니다. 루트에는 CardView가 요소로 있습니다. CardView는 android.support.v7.widget 네임스페이스에 있습니다.

카드 고도를 ‘5dp’로 설정하고 카드 모서리 반경을 ’10dp’로 설정했습니다.

그 안에 위젯을 서로 상대적으로 구성하는 RelativeLayout이 있습니다.

먼저 Image를 렌더링할 ImageView가 있습니다. 그런 다음 TextView에서 텍스트를 렌더링합니다.

CardView의 맨 오른쪽에는 각 cardview의 선택 속성을 보유할 CheckBox가 있습니다. CheckBox는 선택하거나 선택 취소할 수 있습니다.

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
    android_orientation="horizontal" android_layout_width="match_parent"

    android_layout_margin="5dp"
    card_view_cardCornerRadius="10dp"
    card_view_cardElevation="5dp"
    android_layout_height="match_parent">

    <RelativeLayout
        android_layout_width="match_parent"
        android_layout_height="match_parent">
        <ImageView
            android_layout_width="150dp"
            android_layout_height="150dp"
            android_id="@+id/teacherImageView"
            android_padding="5dp"
            android_src="@drawable/cle" />

        <TextView
            android_layout_width="wrap_content"
            android_layout_height="wrap_content"
            android_textAppearance="?android:attr/textAppearanceLarge"
            android_text="Teacher Name"
            android_id="@+id/nameTextView"
            android_padding="5dp"
            android_textColor="@color/colorAccent"
            android_layout_alignParentTop="true"
            android_layout_toRightOf="@+id/teacherImageView" />

        <TextView
            android_layout_width="wrap_content"
            android_layout_height="wrap_content"
            android_textAppearance="?android:attr/textAppearanceMedium"
            android_text="Teacher Description..."
            android_id="@+id/descritionTextView"
            android_padding="5dp"
            android_layout_alignBottom="@+id/teacherImageView"
            android_layout_toRightOf="@+id/teacherImageView" />

        <CheckBox
            android_layout_width="wrap_content"
            android_layout_height="wrap_content"
            android_id="@+id/myCheckBox"
            android_layout_alignParentRight="true"
            />

    </RelativeLayout>
</androidx.cardview.widget.CardView>

4단계: MainActivity.java

패키지 지정 및 가져오기 추가

Java 클래스는 패키지에 상주하므로 하나를 지정하고 적절한 가져오기를 추가합니다.

여기에는 android.support.v7.widget 패키지의 RecyclerView와 android.widget 패키지의 CheckBox가 포함됩니다.

package info.camposha.checkablerecyclerviews;

import android.content.Context;
import android.support.design.widget.FloatingActionButton;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
활동 만들기

활동은 사용자 인터페이스를 나타내는 Android 구성 요소입니다.

일반 클래스를 활동으로 전환하기 위해 AppCompatActivity에서 파생되도록 합니다.

public class MainActivity extends AppCompatActivity {..}
POJO 만들기

그런 다음 POJO 클래스인 Plain OLD Java Object를 생성합니다. 이것은 단일 Teacher 개체를 나타냅니다.

각 SpiritualTecaher에는 여러 속성이 있습니다. 각 개체는 RecyclerView의 자체 CardView에서 렌더링됩니다.

    public class SpiritualTeacher {
        //our properties.
    }

이러한 속성 중 하나는 ‘isSelected’ 속성이 될 것입니다. 이 속성은 CardView의 확인 상태를 유지하는 부울 값입니다.

뷰 홀더 만들기

RecyclerView.ViewHolder 클래스에서 파생하여 RecyclerView ViewHolder 클래스를 만듭니다.

또한 클래스는 View.OnClickListener 인터페이스를 구현합니다. 이를 통해 각 CardView의 클릭 이벤트를 캡처할 수 있습니다.

    static class MyHolder extends RecyclerView.ViewHolder implements View.OnClickListener{...}
RecyclerView 어댑터 생성

그런 다음 어댑터 클래스가 될 클래스인 RecyclerView.Adapter 클래스를 만듭니다.

    static class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyHolder> {..}

어댑터 클래스로서 이 클래스에는 두 가지 기본 역할이 있습니다.

  1. 사용자 정의 모델 레이아웃을 뷰 개체로 확장합니다.
  2. 데이터 세트를 팽창 뷰로 바인딩합니다.

바인딩할 데이터는 사용자 지정 배열(이 경우에는 SpiritualTeachers 배열)에서 가져옵니다.

        public MyAdapter(Context c, SpiritualTeacher[] teachers) {
            this.c = c;
            this.teachers = teachers;
        }

이 클래스는 또한 우리가 선택한 항목을 보관할 arraylist를 유지 관리합니다.

        ArrayList<SpiritualTeacher> checkedTeachers=new ArrayList<>();

사용자는 recyclerview 항목을 확인하고 우리는 이 arraylist에 확인된 항목을 보유합니다. 그런 다음 나중에 Toast 메시지에 이러한 확인 항목을 표시할 수 있습니다.

레이아웃을 뷰로 확장

이것은 우리가 동의한 대로 RecyclerView 어댑터에서 발생합니다. 이를 위해서는 LayoutInflater 클래스가 필요합니다.

        @Override
        public MyHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View v= LayoutInflater.from(parent.getContext()).inflate(R.layout.model,null);
            MyHolder holder=new MyHolder(v);
            return holder;
        }

그런 다음 보다시피 팽창 뷰 객체를 RecyclerView ViewHolder 생성자에 전달했습니다. 그런 다음 ‘View Holder’ 인스턴스를 반환했습니다.

데이터 바인딩

우리는 onBindViewHolder 메소드 내에서 데이터를 바인딩합니다:

        @Override
        public void onBindViewHolder(MyHolder holder, int position) {
            final SpiritualTeacher teacher=teachers[position];
            holder.nameTxt.setText(teacher.getName());
            holder.posTxt.setText(teacher.getQuote());
            holder.myCheckBox.setChecked(teacher.isSelected());
            holder.img.setImageResource(teacher.getImage());
            ...
        }

먼저 우리는 재활용 보기에서 항목의 위치를 ​​받았고 이를 사용하여 배열에서 현재 교사를 가져왔습니다.

그런 다음 해당 개체의 값으로 TextView, imageView 및 CheckBox 위젯을 설정합니다.

선택한 항목과 선택하지 않은 항목 유지 관리

그런 다음 CardView의 클릭 이벤트를 수신합니다. 분명히 CheckBox를 클릭하면 해당 확인란의 상태가 변경됩니다.

이러한 변경 사항을 확인합니다. 확인란을 클릭하면 배열 목록에 항목이 추가됩니다.

선택하지 않으면 arraylist에서 항목을 제거합니다.

            holder.setItemClickListener(new MyHolder.ItemClickListener() {
                @Override
                public void onItemClick(View v, int pos) {
                    CheckBox myCheckBox= (CheckBox) v;
                    SpiritualTeacher currentTeacher=teachers[pos];

                    if(myCheckBox.isChecked()) {
                        currentTeacher.setSelected(true);
                        checkedTeachers.add(currentTeacher);
                    }
                    else if(!myCheckBox.isChecked()) {
                        currentTeacher.setSelected(false);
                        checkedTeachers.remove(currentTeacher);
                    }
                }
            });

전체 소스 코드를 살펴보겠습니다.

전체 코드

다음은 전체 MainActivity 코드입니다.

package info.camposha.checkablerecyclerviews;

import android.content.Context;
import android.support.design.widget.FloatingActionButton;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

    public class SpiritualTeacher {
        private String name,quote;
        private int image;
        private boolean isSelected;

        public SpiritualTeacher(String name, String quote, int image) {
            this.name = name;
            this.quote = quote;
            this.image = image;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String getQuote() {
            return quote;
        }
        public int getImage() {
            return image;
        }

        public boolean isSelected() {
            return isSelected;
        }

        public void setSelected(boolean selected) {
            isSelected = selected;
        }
    }
    static class MyHolder extends RecyclerView.ViewHolder implements View.OnClickListener{

            ImageView img;
            TextView nameTxt,posTxt;
            CheckBox myCheckBox;

            ItemClickListener itemClickListener;

            public MyHolder(View itemView) {
                super(itemView);

                nameTxt= itemView.findViewById(R.id.nameTextView);
                posTxt= itemView.findViewById(R.id.descritionTextView);
                img= itemView.findViewById(R.id.teacherImageView);
                myCheckBox= itemView.findViewById(R.id.myCheckBox);

                myCheckBox.setOnClickListener(this);
            }
            public void setItemClickListener(ItemClickListener ic)
            {
                this.itemClickListener=ic;
            }
            @Override
            public void onClick(View v) {
                this.itemClickListener.onItemClick(v,getLayoutPosition());
            }
            interface ItemClickListener {

                void onItemClick(View v,int pos);
            }
        }
    static class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyHolder> {

        Context c;
        SpiritualTeacher[] teachers;
        ArrayList<SpiritualTeacher> checkedTeachers=new ArrayList<>();

        public MyAdapter(Context c, SpiritualTeacher[] teachers) {
            this.c = c;
            this.teachers = teachers;
        }

        //VIEWHOLDER IS INITIALIZED
        @Override
        public MyHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View v= LayoutInflater.from(parent.getContext()).inflate(R.layout.model,null);
            MyHolder holder=new MyHolder(v);
            return holder;
        }

        //DATA IS BOUND TO VIEWS
        @Override
        public void onBindViewHolder(MyHolder holder, int position) {
            final SpiritualTeacher teacher=teachers[position];
            holder.nameTxt.setText(teacher.getName());
            holder.posTxt.setText(teacher.getQuote());
            holder.myCheckBox.setChecked(teacher.isSelected());
            holder.img.setImageResource(teacher.getImage());

            holder.setItemClickListener(new MyHolder.ItemClickListener() {
                @Override
                public void onItemClick(View v, int pos) {
                    CheckBox myCheckBox= (CheckBox) v;
                    SpiritualTeacher currentTeacher=teachers[pos];

                    if(myCheckBox.isChecked()) {
                        currentTeacher.setSelected(true);
                        checkedTeachers.add(currentTeacher);
                    }
                    else if(!myCheckBox.isChecked()) {
                        currentTeacher.setSelected(false);
                        checkedTeachers.remove(currentTeacher);
                    }
                }
            });
        }

        @Override
        public int getItemCount() {
            return teachers.length;
        }

    }
    private SpiritualTeacher[] getTeachers() {
        SpiritualTeacher[] spiritualTeachers={
                new SpiritualTeacher("Rumi","Out beyond ideas of wrongdoing and rightdoing there is a field.I'll meet you there.",R.drawable.rumi),
                new SpiritualTeacher("Anthony De Mello","Don't Carry Over Experiences from the past",R.drawable.anthony_de_mello),
                new SpiritualTeacher("Eckhart Tolle","Walk as if you are kissing the Earth with your feet.",R.drawable.eckhart_tolle),
                new SpiritualTeacher("Meister Eckhart","Man suffers only because he takes seriously what the gods made for fun.",R.drawable.meister_eckhart),
                new SpiritualTeacher("Mooji","I have lived with several Zen masters -- all of them cats.",R.drawable.mooji),
                new SpiritualTeacher("Confucius","I'm simply saying that there is a way to be sane. I'm saying that you ",R.drawable.confucius),
                new SpiritualTeacher("Francis Lucille","The way out is through the door. Why is it that no one will use this method?",R.drawable.francis_lucille),
                new SpiritualTeacher("Thich Nhat Hanh","t is the power of the mind to be unconquerable.",R.drawable.thich),
                new SpiritualTeacher("Dalai Lama","It's like you took a bottle of ink and you threw it at a wall. Smash! ",R.drawable.dalai_lama),
                new SpiritualTeacher("Jiddu Krishnamurti","A student, filled with emotion and crying, implored, 'Why is there so much suffering?",R.drawable.jiddu_krishnamurti),
                new SpiritualTeacher("Osho","Only the hand that erases can write the true thing.",R.drawable.osho),
                new SpiritualTeacher("Sedata","Many have died; you also will die. The drum of death is being beaten.",R.drawable.sedata),
                new SpiritualTeacher("Allan Watts","Where there are humans, You'll find flies,And Buddhas.",R.drawable.allant_watts),
                new SpiritualTeacher("Leo Gura","Silence is the language of Om. We need silence to be able to reach our Self.",R.drawable.sadhguru),
                new SpiritualTeacher("Rupert Spira","One day in my shoes and a day for me in your shoes, the beauty of travel lies ",R.drawable.rupert_spira),
                new SpiritualTeacher("Sadhguru","Like vanishing dew,a passing apparition or the sudden flashnof lightning",R.drawable.sadhguru)
        };

        return spiritualTeachers;
    }
    StringBuilder sb=null;
    MyAdapter adapter;

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

        adapter=new MyAdapter(this,getTeachers());

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                sb=new StringBuilder();

                int i=0;
                do {
                    SpiritualTeacher spiritualTeacher=adapter.checkedTeachers.get(i);
                    sb.append(spiritualTeacher.getName());
                    if(i != adapter.checkedTeachers.size()-1){
                        sb.append("n");
                    }
                    i++;

                }while (i < adapter.checkedTeachers.size());

                if(adapter.checkedTeachers.size()>0)
                {
                    Toast.makeText(MainActivity.this,sb.toString(),Toast.LENGTH_SHORT).show();
                }else
                {
                    Toast.makeText(MainActivity.this,"Please Check An Item First", Toast.LENGTH_SHORT).show();
                }
            }
        });

        //RECYCLER
        RecyclerView rv= (RecyclerView) findViewById(R.id.myRecycler);
        rv.setLayoutManager(new LinearLayoutManager(this));
        rv.setItemAnimator(new DefaultItemAnimator());

        //SET ADAPTER
        rv.setAdapter(adapter);

    }

}

예제 2: SingleChoice RecyclerView – RadioButton 사용

Android SingleChoice RecyclerView 튜토리얼

이 튜토리얼에서는 단일 선택 리사이클러 뷰를 생성하는 방법을 알고 싶습니다. 그것은 라디오 버튼이 있는 리사이클러뷰입니다. 사용자는 단일 항목을 선택할 수 있으며 항목의 세부 활동을 열어 해당 데이터를 표시합니다.

왜 SingleChoice RecyclerView입니까?

대안은 다중 선택 Recyclerview입니다. 즉, 체크박스가 있는 recyclerview입니다. 그러나 어떤 경우에는 사용자가 재활용 보기에서 단일 항목을 선택할 수 있기를 원합니다. 이것은 라디오 버튼이 들어오는 곳입니다.

그러나 우리의 경우 사용자가 주어진 라디오 버튼을 선택할 때 세부 활동을 엽니다. 그런 다음 인텐트를 사용하여 데이터를 세부 활동에 전달합니다.

무엇을 보여줍니까?

글쎄, 우리는 이미지, 텍스트 및 라디오 버튼을 보여줍니다. 일반적으로 이미지는 imageview에서 렌더링됩니다. 텍스트는 textview에서 렌더링됩니다. 반면에 라디오 버튼은 기본적으로 확인 여부에 관계없이 복합 상태를 보여줍니다.

1단계: Gradle 스크립트

(a) Build.gradle

특별한 종속성이 필요하지 않습니다. 우리는 의존성으로 CardView와 recyclerview를 추가합니다.

CardView는 Galaxy 개체를 보유합니다. RecyclerView는 여러 cardview를 보유합니다. AppCompat은 MainActivity가 확장되는 AppCompatActivity를 제공합니다.

2단계: 레이아웃 만들기

세 가지 레이아웃이 있습니다.

1. 활동_main.xml

이 레이아웃은 MainActivity로 확장됩니다. 여기에는 단순히 RecyclerView가 포함되어 있습니다. 내 배경색을 사용자 지정했습니다.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    android_layout_width="match_parent"
    android_background="#009968"
    android_layout_height="match_parent">

    <androidx.recyclerview.widget.RecyclerView
        android_id="@+id/mRecylcerview"
        android_layout_width="match_parent"
        android_layout_height="match_parent" />
</RelativeLayout>

2. 활동_detail.xml

Detail 활동의 레이아웃입니다. 데이터를 표시하기 위한 imageview 및 textviews.를 포함합니다.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout

    android_layout_width="match_parent"
    android_layout_height="match_parent"
    android_background="#009688"
    tools_context=".DetailsActivity"
    tools_showIn="@layout/activity_detail">

    <androidx.cardview.widget.CardView
        android_layout_width="match_parent"
        android_layout_height="match_parent"
        android_layout_margin="3dp"
        card_view_cardCornerRadius="3dp"
        card_view_cardElevation="5dp">

        <ScrollView
            android_layout_width="match_parent"
            android_layout_height="match_parent">

            <LinearLayout
                android_layout_width="match_parent"
                android_layout_height="match_parent"
                android_orientation="vertical">

                <ImageView
                    android_id="@+id/galaxyImg"
                    android_layout_width="match_parent"
                    android_layout_height="200dp"
                    android_layout_alignParentTop="true"
                    android_padding="5dp"
                    android_scaleType="fitXY"
                    android_src="@drawable/placeholder" />

                <LinearLayout
                    android_layout_width="match_parent"
                    android_layout_height="wrap_content"
                    android_orientation="vertical">

                    <LinearLayout
                        android_layout_width="match_parent"
                        android_layout_height="wrap_content"
                        android_orientation="horizontal">

                        <TextView
                            android_id="@+id/nameLabel"
                            android_layout_width="0dp"
                            android_layout_weight="1"
                            android_layout_height="wrap_content"
                            android_maxLines="1"
                            android_padding="5dp"
                            android_text="NAME"
                            android_textColor="@color/colorAccent"
                            android_textAppearance="?android:attr/textAppearanceSmall"
                            android_textStyle="bold" />

                        <TextView
                            android_id="@+id/nameTxt"
                            android_layout_width="0dp"
                            android_layout_weight="2"
                            android_layout_height="wrap_content"
                            android_maxLines="1"
                            android_padding="5dp"
                            android_text="Milky Way"
                            android_textAppearance="?android:attr/textAppearanceSmall"/>
                    </LinearLayout>

                    <LinearLayout
                        android_layout_width="match_parent"
                        android_layout_height="wrap_content"
                        android_orientation="horizontal">

                        <TextView
                            android_id="@+id/dateLabel"
                            android_layout_width="0dp"
                            android_layout_weight="1"
                            android_layout_height="wrap_content"
                            android_maxLines="1"
                            android_textColor="@color/colorAccent"
                            android_padding="5dp"
                            android_text="DATE"
                            android_textAppearance="?android:attr/textAppearanceSmall"
                            android_textStyle="bold" />

                        <TextView
                            android_id="@+id/dateDetailTextView"
                            android_layout_width="0dp"
                            android_layout_weight="2"
                            android_layout_height="wrap_content"
                            android_maxLines="1"
                            android_padding="5dp"
                            android_text="Today"
                            android_textAppearance="?android:attr/textAppearanceSmall"/>
                    </LinearLayout>

                    <LinearLayout
                        android_layout_width="match_parent"
                        android_layout_height="wrap_content"
                        android_orientation="horizontal">

                        <TextView
                            android_id="@+id/descLabel"
                            android_layout_width="0dp"
                            android_layout_weight="1"
                            android_layout_height="wrap_content"
                            android_maxLines="1"
                            android_textColor="@color/colorAccent"
                            android_padding="5dp"
                            android_text="DESCRIPTION : "
                            android_textAppearance="?android:attr/textAppearanceSmall"
                            android_textStyle="bold" />

                        <TextView
                            android_id="@+id/descTxt"
                            android_layout_width="0dp"
                            android_layout_weight="2"
                            android_layout_height="wrap_content"
                            android_maxLines="10"
                            android_padding="5dp"
                            android_text="Description..."
                            android_textAppearance="?android:attr/textAppearanceSmall"/>
                    </LinearLayout>

                </LinearLayout>
            </LinearLayout>
        </ScrollView>
    </androidx.cardview.widget.CardView>
</RelativeLayout>

삼. 모델.xml

이것은 항목 보기 레이아웃입니다. 그것은 우리의 recyclerview 보기 항목으로 부풀려질 것입니다. 이것은 RecyclerView 어댑터에 의해 수행됩니다.

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
    android_orientation="horizontal" android_layout_width="match_parent"

    android_layout_margin="1dp"
    card_view_cardCornerRadius="1dp"
    card_view_cardElevation="5dp"
    android_layout_height="135dp">

        <RelativeLayout
            android_layout_width="wrap_content"
            android_layout_height="match_parent">

        <ImageView
            android_layout_width="120dp"
            android_layout_height="120dp"
            android_id="@+id/mGalaxyImageView"
            android_padding="5dp"
            android_scaleType="fitXY"
            android_src="@drawable/placeholder" />

        <TextView
            android_layout_width="wrap_content"
            android_layout_height="wrap_content"
            android_textAppearance="?android:attr/textAppearanceSmall"
            android_text="Name"
            android_id="@+id/mNameTxt"
            android_padding="5dp"
            android_textColor="@color/colorAccent"
            android_layout_alignParentTop="true"
            android_layout_toRightOf="@+id/mGalaxyImageView" />

        <TextView
            android_layout_width="wrap_content"
            android_layout_height="wrap_content"
            android_textAppearance="?android:attr/textAppearanceSmall"
            android_text="Description"
            android_textStyle="italic"
            android_maxLines="3"
            android_id="@+id/mDescTxt"
            android_padding="5dp"
            android_layout_alignBottom="@+id/mGalaxyImageView"
            android_layout_toRightOf="@+id/mGalaxyImageView" />

            <RadioButton
                android_id="@+id/mRadioButton"
                android_layout_width="wrap_content"
                android_layout_height="wrap_content"
                android_layout_alignParentRight="true" />

        </RelativeLayout>
</androidx.cardview.widget.CardView>

4단계: Java 코드를 작성합니다.

이 프로젝트에는 다음과 같은 Java 클래스가 있습니다.

  1. 갤럭시.자바
  2. RecyclerAdapter.java
  3. DetailsActivity.java
  4. MainActivity.java
(a).Galaxy.java

이것은 우리의 데이터 개체를 나타냅니다. 이것은 우리의 모델 클래스이며 다음과 같은 속성을 가진 은하를 나타냅니다.

  1. 이름.
  2. 설명
  3. 이미지.

다음은 전체 코드입니다.

package info.camposha.singlechoicerecyclerview_vela;

import java.io.Serializable;

/**
 * Please take note that our data object will implement Serializable.This
 * will allow us to pass this serialized object to DetailsActivity,
 */
public class Galaxy implements Serializable{
    private String name,description;
    private int image;

    public Galaxy(String name, String description,int image) {
        this.name = name;
        this.description = description;
        this.image=image;
    }

    public String getName() {return name;}
    public String getDescription() {return description;}
    public int getImage() {return image;}

}

Serializable 인터페이스를 구현한 것을 볼 수 있습니다. 이를 통해 데이터 개체를 직렬화하여 의도를 통해 전체 DetailsActivity 활동으로 전송할 수 있습니다.

(b). RecyclerAdapter.java

이것은 어댑터 클래스입니다. 그것은 우리의 모델 레이아웃을 리사이클러뷰에 의해 렌더링될 수 있는 뷰 객체로 팽창시킬 것입니다. 또한 팽창된 뷰 개체에 데이터를 바인딩합니다.

package info.camposha.singlechoicerecyclerview_vela;

import android.content.Context;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ImageView;
import android.widget.RadioButton;
import android.widget.TextView;

import java.util.List;

public class RecyclerAdapter extends RecyclerView.Adapter<
RecyclerAdapter.RecyclerViewHolder> {

    /**
     * Let's start by defining our instance fields
     */
    private int selectedStarPosition = -1;
    private List<Galaxy> galaxies;
    private Context c;
    private AdapterView.OnItemClickListener onItemClickListener;

    /**
     * Let's create our constructor
     * @param context
     * @param mGalaxies
     */
    public RecyclerAdapter(Context context, List<Galaxy> mGalaxies) {
        this.c = context;
        this.galaxies = mGalaxies;
    }

    /**
     * OnCreateViewHolder - here is where we inflate our model layout
     * @param viewGroup
     * @param i
     * @return
     */
    @Override
    public RecyclerViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
        final View v = LayoutInflater.from(c).inflate(R.layout.model, viewGroup, false);
        return new RecyclerViewHolder(v, this);
    }

    /**
     * OnBindViewHolder - Here's where we bind our data
     * @param viewHolder
     * @param position
     */
    @Override
    public void onBindViewHolder(RecyclerViewHolder viewHolder, final int position) {
        Galaxy galaxy = galaxies.get(position);
        try {
            viewHolder.bindData(galaxy, position);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * Let's return the number of items to be bound to our adapter.
     * @return
     */
    @Override
    public int getItemCount() {
        return galaxies.size();
    }

    /**
     * Let's receive our onItemClickListener and assign it to our local one.
     * @param onItemClickListener
     */
    public void setOnItemClickListener(AdapterView.OnItemClickListener
     onItemClickListener) {
        this.onItemClickListener = onItemClickListener;
    }

    /**
     * When user clicks our itemView, we still invoke the onItemClick
     * @param holder
     */
    public void onItemHolderClick(RecyclerViewHolder holder) {
        if (onItemClickListener != null)
            onItemClickListener.onItemClick(null, holder.itemView,
             holder.getAdapterPosition(), holder.getItemId());
    }

    /**
     * Let's come create our ViewHolder class.
     */
    class RecyclerViewHolder extends RecyclerView.ViewHolder implements
     View.OnClickListener {

        private RecyclerAdapter mAdapter;
        private RadioButton mRadioButton;
        private TextView mNameTxt,mDescTxt;
        private ImageView mGalaxyImg;

        /**
         * In our constructor, we reference our itemView widgets.
         * @param itemView
         * @param mAdapter
         */
        public RecyclerViewHolder(View itemView, final RecyclerAdapter mAdapter) {
            super(itemView);
            this.mAdapter = mAdapter;

            mNameTxt = itemView.findViewById(R.id.mNameTxt);
            mDescTxt = itemView.findViewById(R.id.mDescTxt);
            mRadioButton = itemView.findViewById(R.id.mRadioButton);
            mGalaxyImg=itemView.findViewById(R.id.mGalaxyImageView);
            itemView.setOnClickListener(this);
            mRadioButton.setOnClickListener(this);
        }

        /**
         * Let's create a method that allows us bind our data.
         * @param galaxy
         * @param position
         */
        public void bindData(Galaxy galaxy, int position) {
            mRadioButton.setChecked(position == selectedStarPosition);
            mNameTxt.setText(galaxy.getName());
            mDescTxt.setText(galaxy.getDescription());
            mGalaxyImg.setImageResource(galaxy.getImage());
        }

        /**
         * Let's override our OnClick method.
         * @param v
         */
        @Override
        public void onClick(View v) {
            selectedStarPosition = getAdapterPosition();
            notifyItemRangeChanged(0, galaxies.size());
            mAdapter.onItemHolderClick(RecyclerViewHolder.this);
        }
    }
}
//end
(씨). 세부 정보 활동.자바

우리의 세부 활동 수업. 클릭한 은하계의 세부 정보가 표시됩니다.

package info.camposha.singlechoicerecyclerview_vela;

import android.content.Intent;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import android.widget.ImageView;
import android.widget.TextView;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

public class DetailsActivity extends AppCompatActivity {

  TextView nameTxt, descTxt, dateDetailTextView;
  ImageView galaxyImg;

  //We start by initializing our widgets.
  private void initializeWidgets() {
    nameTxt = findViewById(R.id.nameTxt);
    descTxt = findViewById(R.id.descTxt);
    dateDetailTextView = findViewById(R.id.dateDetailTextView);
    descTxt = findViewById(R.id.descTxt);
    galaxyImg = findViewById(R.id.galaxyImg);
  }

  //This method will get todays date and return it as a string
  private String getDateToday() {
    DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");
    Date date = new Date();
    String today = dateFormat.format(date);
    return today;
  }

  //I'll create a method to receive and show data.
  private void receiveAndShowData() {
    //RECEIVE DATA FROM ITEMS ACTIVITY VIA INTENT
    Intent i = this.getIntent();
    Galaxy g= (Galaxy) i.getSerializableExtra("GALAXY_KEY");

    //SET RECEIVED DATA TO TEXTVIEWS AND IMAGEVIEWS
    nameTxt.setText(g.getName());
    descTxt.setText(g.getDescription());
    dateDetailTextView.setText(getDateToday());
    galaxyImg.setImageResource(g.getImage());
  }

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

    initializeWidgets();
    receiveAndShowData();
  }
}
//end
(d). 메인 액티비티.자바

우리의 주요 활동 수업. 여기에서 우리는 리사이클러 뷰를 참조하고 데이터 소스를 정의합니다.

package info.camposha.singlechoicerecyclerview_vela;

import android.content.Intent;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Toast;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity implements AdapterView.OnItemClickListener {

    RecyclerView mRecyclerView;
    private RecyclerAdapter mAdapter;
    /**
     * Let's start by defining our data source.
     * @return
     */
    private ArrayList<Galaxy> getData()
    {
        ArrayList<Galaxy> galaxies=new ArrayList<>();
        Galaxy g=new Galaxy("Whirlpool",
                "The Whirlpool Galaxy, also known as Messier 51a, M51a, and NGC 5194, is an interacting grand-design spiral Galaxy with a Seyfert 2 active galactic nucleus in the constellation Canes Venatici.",
                R.drawable.whirlpool);
        galaxies.add(g);

        g=new Galaxy("Ring Nebular",
                "The Ring Nebula is a planetary nebula in the northern constellation of Lyra. Such objects are formed when a shell of ionized gas is expelled into the surrounding interstellar medium by a red giant star.",
                R.drawable.ringnebular);
        galaxies.add(g);

        g=new Galaxy("IC 1011",
                "C 1011 is a compact elliptical galaxy with apparent magnitude of 14.7, and with a redshift of z=0.02564 or 0.025703, yielding a distance of 100 to 120 Megaparsecs. Its light has taken 349.5 million years to travel to Earth.",
                R.drawable.ic1011);
        galaxies.add(g);

        g=new Galaxy("Cartwheel",
                "The Cartwheel Galaxy is a lenticular galaxy and ring galaxy about 500 million light-years away in the constellation Sculptor. It is an estimated 150,000 light-years diameter, and a mass of about 2.9–4.8 × 10⁹ solar masses; it rotates at 217 km/s.",
                R.drawable.cartwheel);
        galaxies.add(g);

        g=new Galaxy("Triangulumn",
                "The Triangulum Galaxy is a spiral Galaxy approximately 3 million light-years from Earth in the constellation Triangulum",
                R.drawable.triangulum);
        galaxies.add(g);

        g=new Galaxy("Small Magellonic Cloud",
                "The Small Magellanic Cloud, or Nubecula Minor, is a dwarf galaxy near the Milky Way. It is classified as a dwarf irregular galaxy.",
                R.drawable.smallamgellonic);
        galaxies.add(g);

        g=new Galaxy("Centaurus A",
                " Centaurus A or NGC 5128 is a galaxy in the constellation of Centaurus. It was discovered in 1826 by Scottish astronomer James Dunlop from his home in Parramatta, in New South Wales, Australia.",
                R.drawable.centaurusa);
        galaxies.add(g);

        g=new Galaxy("Ursa Minor",
                "The Milky Way is the Galaxy that contains our Solar System." +
                        " The descriptive milky is derived from the appearance from Earth of the Galaxy – a band of light seen in the night sky formed from stars",
                R.drawable.ursaminor);
        galaxies.add(g);

        g=new Galaxy("Large Magellonic Cloud",
                " The Large Magellanic Cloud is a satellite galaxy of the Milky Way. At a distance of 50 kiloparsecs, the LMC is the third-closest galaxy to the Milky Way, after the Sagittarius Dwarf Spheroidal and the.",
                R.drawable.largemagellonic);
        galaxies.add(g);

        g=new Galaxy("Milky Way",
                "The Milky Way is the Galaxy that contains our Solar System." +
                        " The descriptive milky is derived from the appearance from Earth of the Galaxy – a band of light seen in the night sky formed from stars",
                R.drawable.milkyway);
        galaxies.add(g);

        g=new Galaxy("Andromeda",
                "The Andromeda Galaxy, also known as Messier 31, M31, or NGC 224, is a spiral Galaxy approximately 780 kiloparsecs from Earth. It is the nearest major Galaxy to the Milky Way and was often referred to as the Great Andromeda Nebula in older texts.",
                R.drawable.andromeda);
        galaxies.add(g);

        g=new Galaxy("Messier 81",
                "Messier 81 is a spiral Galaxy about 12 million light-years away in the constellation Ursa Major. Due to its proximity to Earth, large size and active galactic nucleus, Messier 81 has been studied extensively by professional astronomers.",
                R.drawable.messier81);
        galaxies.add(g);

        g=new Galaxy("Own Nebular",
                " The Owl Nebula is a planetary nebula located approximately 2,030 light years away in the constellation Ursa Major. It was discovered by French astronomer Pierre Méchain on February 16, 1781",
                R.drawable.ownnebular);
        galaxies.add(g);

        g=new Galaxy("Messier 87",
                "Messier 87 is a supergiant elliptical galaxy in the constellation Virgo. One of the most massive galaxies in the local universe, it is notable for its large population of globular clusters—M87 contains",
                R.drawable.messier87);
        galaxies.add(g);

        g=new Galaxy("Cosmos Redshift",
                "Cosmos Redshift 7 is a high-redshift Lyman-alpha emitter Galaxy, in the constellation Sextans, about 12.9 billion light travel distance years from Earth, reported to contain the first stars —formed ",
                R.drawable.cosmosredshift);
        galaxies.add(g);

        g=new Galaxy("StarBust",
                "A starburst Galaxy is a Galaxy undergoing an exceptionally high rate of star formation, as compared to the long-term average rate of star formation in the Galaxy or the star formation rate observed in most other galaxies. ",
                R.drawable.starbust);
        galaxies.add(g);

        g=new Galaxy("Sombrero",
                "Sombrero Galaxy is an unbarred spiral galaxy in the constellation Virgo located 31 million light-years from Earth. The galaxy has a diameter of approximately 50,000 light-years, 30% the size of the Milky Way.",
                R.drawable.sombrero);
        galaxies.add(g);

        g=new Galaxy("Pinwheel",
                "The Pinwheel Galaxy is a face-on spiral galaxy distanced 21 million light-years away from earth in the constellation Ursa Major. ",
                R.drawable.pinwheel);
        galaxies.add(g);

        g=new Galaxy("Canis Majos Overdensity",
                "The Canis Major Dwarf Galaxy or Canis Major Overdensity is a disputed dwarf irregular galaxy in the Local Group, located in the same part of the sky as the constellation Canis Major. ",
                R.drawable.canismajoroverdensity);
        galaxies.add(g);

        g=new Galaxy("Virgo Stella Stream",
                " Group, located in the same part of the sky as the constellation Canis Major. ",
                R.drawable.virgostellarstream);
        galaxies.add(g);

        return galaxies;
    }

    /**
     * Let's create a method to open our detail activity and pass our object.
     * @param galaxy
     */
    private void openDetailActivity(Galaxy galaxy)
    {
        Intent i=new Intent(this,DetailsActivity.class);
        i.putExtra("GALAXY_KEY",galaxy);
        startActivity(i);
    }

    /**
     * Let's implemenent our onItemClick method
     * @param parent
     * @param view
     * @param position
     * @param id
     */
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        Galaxy g=getData().get(position);
        Toast.makeText(MainActivity.this,String.valueOf(position)+". "+ g.getName()+" Chosen.", Toast.LENGTH_SHORT).show();
        openDetailActivity(g);
    }

    /**
     * Let's override our onCreate callback
     * @param savedInstanceState
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mRecyclerView=findViewById(R.id.mRecylcerview);

        mAdapter = new RecyclerAdapter(this, getData());
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
        mRecyclerView.setAdapter(mAdapter);
        mAdapter.setOnItemClickListener(this);
    }
}
다운로드

아래에서 전체 소스 코드를 다운로드하거나 제공된 링크에서 비디오를 볼 수 있습니다.

직접 다운로드
찾아보기

예제 3: Kotlin Android RecyclerView – CheckBox, 이미지, 텍스트 및 ItemClick이 있는 CardView

CheckBox, 이미지, 텍스트 및 ItemClick이 포함된 Kotlin Android RecyclerView는 Tutorial 및 Example을 지원합니다.

이 튜토리얼에서 어떻게 리사이클러뷰로 작업하고 체크박스, 이미지, 텍스트뷰와 함께 사용하고 클릭 이벤트를 지원하는 것과 같은 일반적인 작업을 수행할 수 있는지 보여주고 싶습니다. 이 모든 작업을 단일 MainActivity.kt 파일에서 수행합니다.

동영상 튜토리얼

비디오 자습서를 선호하는 경우 여기를 확인하십시오.

배우는 내용

학습하는 개념은 다음과 같습니다.

  1. Android에서 Kotlin 프로그래밍 언어로 Recyclerview를 사용하는 방법.
  2. Recyclerview와 함께 CheckBox를 사용하고 체크박스 상태를 적절하게 처리하는 방법.
  3. 이미지와 텍스트로 리사이클러뷰를 만드는 방법.
  4. 리사이클러뷰에서 아이템 클릭 이벤트를 지원하는 방법.

사용된 도구

이 프로젝트에 사용한 도구는 다음과 같습니다.

  1. 프로그래밍 언어 : 코틀린
  2. 프레임워크 – 안드로이드
  3. IDE – 안드로이드 스튜디오.
  4. 에뮬레이터 – 녹스 플레이어
  5. 운영체제 : 윈도우 8.1

시작하자.

데모

이 프로젝트의 데모는 다음과 같습니다.

Kotlin RecyclerView 체크박스

(ㅏ). 빌드.gradle

앱 레벨 build.gradle. 여기에 의존성을 추가합니다. 특히 우리는 그 중 세 가지 주요 사항에 관심이 있습니다.

  1. AppCompat – ‘MainActivity’가 파생될 AppCompatActivity를 제공합니다.
  2. 디자인 지원 – RecyclerView를 제공합니다.
  3. CardView – 우리에게 Cardview를 제공합니다.

(ㄴ). 활동_main.xml

이것은 우리의 주요 활동 레이아웃입니다. 우리가 사용하는 구성 요소는 다음과 같습니다.

  1. RelativeLayout – 다른 위젯을 서로 상대적으로 정렬합니다.
  2. TextView – 헤더 텍스트를 렌더링합니다.
  3. RecyclerView – 데이터를 렌더링합니다.
  4. 플로팅 액션 버튼 – 클릭 시 체크된 항목을 보여줍니다.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout

    android_layout_width="match_parent"
    android_layout_height="match_parent"
    tools_context="com.devosha.kotlin_recyclerview_checkbox.MainActivity">

    <TextView
        android_id="@+id/headerTextView"
        android_layout_width="match_parent"
        android_layout_height="wrap_content"
        android_text="Spiritual Teachers"
        android_textAlignment="center"
        android_textAppearance="@style/TextAppearance.AppCompat.Large"
        android_textColor="@color/colorAccent" />

    <androidx.recyclerview.widget.RecyclerView
        android_id="@+id/myRecycler"
        class="androidx.recyclerview.widget.RecyclerView"
        android_layout_width="match_parent"
        android_layout_height="wrap_content"
        android_layout_alignParentLeft="true"
        android_layout_alignParentStart="true"
        android_layout_below="@+id/headerTextView"
        android_layout_marginTop="30dp" />

    <android.support.design.widget.FloatingActionButton
        android_id="@+id/fab"
        android_layout_width="wrap_content"
        android_layout_height="wrap_content"
        android_layout_alignParentBottom="true"
        android_layout_alignParentEnd="true"
        android_layout_alignParentRight="true"
        android_layout_gravity="bottom|end"
        android_src="@android:drawable/ic_dialog_email" />

</RelativeLayout>

(씨). 모델.xml

이 레이아웃은 재활용 보기에 대한 항목 보기를 정의하고 모델링합니다. 기본적으로 단일 SpiritualTeacher 개체에 대한 데이터를 렌더링합니다. 루트에는 CardView가 있습니다. 그러면 다음도 있습니다.

  1. ImageView – SpiritualTeacher 개체에 대한 이미지를 렌더링합니다.
  2. TextView – 그의 이름과 설명을 렌더링합니다.
  3. CheckBox – CardView를 선택 및 선택 해제할 수 있습니다.

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
    android_orientation="horizontal" android_layout_width="match_parent"

    android_layout_margin="5dp"
    card_view_cardCornerRadius="10dp"
    card_view_cardElevation="5dp"
    android_layout_height="match_parent">

    <RelativeLayout
        android_layout_width="match_parent"
        android_layout_height="match_parent">
        <ImageView
            android_layout_width="150dp"
            android_layout_height="150dp"
            android_id="@+id/teacherImageView"
            android_padding="5dp"
            android_src="@drawable/cle" />

        <TextView
            android_layout_width="wrap_content"
            android_layout_height="wrap_content"
            android_textAppearance="?android:attr/textAppearanceLarge"
            android_text="Teacher Name"
            android_id="@+id/nameTextView"
            android_padding="5dp"
            android_textColor="@color/colorAccent"
            android_layout_alignParentTop="true"
            android_layout_toRightOf="@+id/teacherImageView" />

        <TextView
            android_layout_width="wrap_content"
            android_layout_height="wrap_content"
            android_textAppearance="?android:attr/textAppearanceMedium"
            android_text="Teacher Description..."
            android_id="@+id/descritionTextView"
            android_padding="5dp"
            android_layout_alignBottom="@+id/teacherImageView"
            android_layout_toRightOf="@+id/teacherImageView" />

        <CheckBox
            android_layout_width="wrap_content"
            android_layout_height="wrap_content"
            android_id="@+id/myCheckBox"
            android_layout_alignParentRight="true"
            />

    </RelativeLayout>
</androidx.cardview.widget.CardView>

(d). MainActivity.kt

이것은 우리의 주요 활동입니다. 이것은 우리의 유일한 파일이며 여기에서 여러 내부 kotlin 클래스를 정의합니다. 이 클래스는 AppCompatActivity에서 파생됩니다.

데이터 개체 만들기

먼저 SpiritualTeacher라는 내부 클래스를 정의합니다.

   inner class SpiritualTeacher(var name: String?, val quote: String, val image: Int) {
        var isSelected: Boolean = false
    }

그 클래스는 우리의 데이터 객체입니다. 생성자를 통해 매개변수를 받습니다. 또한 CardViews의 선택 상태를 유지하는 간단한 부울 값을 유지 관리하고 있습니다. 사실 이것은 재활용 보기에서 항목을 선택 및 선택 취소할 수 있는 마법입니다. 따라서 우리가 스크롤하고 recyclerview 항목을 재활용하더라도 우리의 recyclerview는 상태를 잃지 않을 것입니다. 이것은 우리가 그것들을 우리 객체의 데이터로 보유하고 있고 재활용의 영향을 받지 않기 때문입니다.

RecyclerVew 어댑터 클래스 생성

일반적으로 어댑터에는 두 가지 주요 역할이 있습니다. 먼저 사용자 정의 레이아웃을 확장하고 두 번째로 결과 위젯에 데이터를 바인딩합니다. 그러나 recyclerview는 항상 항목을 재활용할 수 있도록 허용함으로써 한 걸음 더 나아갑니다. 인플레이션은 비용이 많이 드는 프로세스이고 우리가 리사이클러 뷰의 모든 항목에 대해 수행할 경우 앱에 부정적인 영향을 미치기 때문에 메모리 소비를 절약합니다.

그래서 우리는 어댑터를 만들 것입니다:

    internal class MyAdapter(var c: Context, var teachers: Array<SpiritualTeacher>) : RecyclerView.Adapter<MyAdapter.MyHolder>() {..}

‘RecyclerView.Adapter’ 클래스에서 파생되도록 만들었습니다.

먼저 어댑터 내부에서 확인된 ‘선생님’을 보관할 배열 목록을 만듭니다.

        var checkedTeachers = ArrayList<SpiritualTeacher>()

우리의 model.xml을 View 객체로 확장할 onCreateViewHolder() 메소드 내부에 있습니다. 이를 위해 LayoutInflater 클래스를 사용합니다.

        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyHolder {
            val v = LayoutInflater.from(parent.context).inflate(R.layout.model, null)
            return MyHolder(v)
        }

다음은 전체 소스 코드입니다.

package com.devosha.kotlin_recyclerview_checkbox

import android.content.Context
import android.os.Bundle
import android.support.design.widget.FloatingActionButton
import androidx.appcompat.app.AppCompatActivity
import android.support.v7.widget.DefaultItemAnimator
import android.support.v7.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.CheckBox
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast

import java.util.ArrayList

/**
 * class: MainActivity
 * This class is deriving from <code>androidx.appcompat.app.AppCompatActivity</code>.
 */
class MainActivity : AppCompatActivity() {

    private val teachers: Array<SpiritualTeacher>
        get() =
            arrayOf(SpiritualTeacher("Rumi", "Out beyond ideas of wrongdoing and rightdoing there is a field.I'll meet you there.", R.drawable.rumi),
                    SpiritualTeacher("Anthony De Mello", "Don't Carry Over Experiences from the past", R.drawable.anthony_de_mello),
                    SpiritualTeacher("Eckhart Tolle", "Walk as if you are kissing the Earth with your feet.", R.drawable.eckhart_tolle),
                    SpiritualTeacher("Meister Eckhart", "Man suffers only because he takes seriously what the gods made for fun.", R.drawable.meister_eckhart),
                    SpiritualTeacher("Mooji", "I have lived with several Zen masters -- all of them cats.", R.drawable.mooji),
                    SpiritualTeacher("Confucius", "I'm simply saying that there is a way to be sane. I'm saying that you ", R.drawable.confucius),
                    SpiritualTeacher("Francis Lucille", "The way out is through the door. Why is it that no one will use this method?", R.drawable.francis_lucille),
                    SpiritualTeacher("Thich Nhat Hanh", "t is the power of the mind to be unconquerable.", R.drawable.thich),
                    SpiritualTeacher("Dalai Lama", "It's like you took a bottle of ink and you threw it at a wall. Smash! ", R.drawable.dalai_lama),
                    SpiritualTeacher("Jiddu Krishnamurti", "A student, filled with emotion and crying, implored, 'Why is there so much suffering?", R.drawable.jiddu_krishnamurti),
                    SpiritualTeacher("Osho", "Only the hand that erases can write the true thing.", R.drawable.osho),
                    SpiritualTeacher("Sedata", "Many have died; you also will die. The drum of death is being beaten.", R.drawable.sedata),
                    SpiritualTeacher("Allan Watts", "Where there are humans, You'll find flies,And Buddhas.", R.drawable.allant_watts),
                    SpiritualTeacher("Leo Gura", "Silence is the language of Om. We need silence to be able to reach our Self.", R.drawable.sadhguru),
                    SpiritualTeacher("Rupert Spira", "One day in my shoes and a day for me in your shoes, the beauty of travel lies ", R.drawable.rupert_spira),
                    SpiritualTeacher("Sadhguru", "Like vanishing dew,a passing apparition or the sudden flashnof lightning", R.drawable.sadhguru))
    internal var sb: StringBuilder? = null
    internal lateinit var adapter: MyAdapter

    inner class SpiritualTeacher(var name: String?, val quote: String, val image: Int) {
        var isSelected: Boolean = false
    }

    internal class MyAdapter(var c: Context, var teachers: Array<SpiritualTeacher>) : RecyclerView.Adapter<MyAdapter.MyHolder>() {
        var checkedTeachers = ArrayList<SpiritualTeacher>()

        //VIEWHOLDER IS INITIALIZED
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyHolder {
            val v = LayoutInflater.from(parent.context).inflate(R.layout.model, null)
            return MyHolder(v)
        }

        //DATA IS BOUND TO VIEWS
        override fun onBindViewHolder(holder: MyHolder, position: Int) {
            val teacher = teachers[position]
            holder.nameTxt.text = teacher.name
            holder.posTxt.text = teacher.quote
            holder.myCheckBox.isChecked = teacher.isSelected
            holder.img.setImageResource(teacher.image)

            holder.setItemClickListener(object : MyHolder.ItemClickListener {
                override fun onItemClick(v: View, pos: Int) {
                    val myCheckBox = v as CheckBox
                    val currentTeacher = teachers[pos]

                    if (myCheckBox.isChecked) {
                        currentTeacher.isSelected = true
                        checkedTeachers.add(currentTeacher)
                    } else if (!myCheckBox.isChecked) {
                        currentTeacher.isSelected = false
                        checkedTeachers.remove(currentTeacher)
                    }
                }
            })
        }

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

        internal class MyHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {

            var img: ImageView
            var nameTxt: TextView
            var posTxt: TextView
            var myCheckBox: CheckBox

            lateinit var myItemClickListener: ItemClickListener

            init {

                nameTxt = itemView.findViewById(R.id.nameTextView)
                posTxt = itemView.findViewById(R.id.descritionTextView)
                img = itemView.findViewById(R.id.teacherImageView)
                myCheckBox = itemView.findViewById(R.id.myCheckBox)

                myCheckBox.setOnClickListener(this)
            }

            fun setItemClickListener(ic: ItemClickListener) {
                this.myItemClickListener = ic
            }

            override fun onClick(v: View) {
                this.myItemClickListener.onItemClick(v, layoutPosition)
            }

            internal interface ItemClickListener {

                fun onItemClick(v: View, pos: Int)
            }
        }
    }

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

        adapter = MyAdapter(this, teachers)

        val fab = findViewById(R.id.fab) as FloatingActionButton
        fab.setOnClickListener {
            sb = StringBuilder()

            var i = 0
            while (i < adapter.checkedTeachers.size) {
                val spiritualTeacher = adapter.checkedTeachers[i]
                sb!!.append(spiritualTeacher.name)
                if (i != adapter.checkedTeachers.size - 1) {
                    sb!!.append("n")
                }
                i++

            }

            if (adapter.checkedTeachers.size > 0) {
                Toast.makeText([email protected], sb!!.toString(), Toast.LENGTH_SHORT).show()
            } else {
                Toast.makeText([email protected], "Please Check An Item First", Toast.LENGTH_SHORT).show()
            }
        }

        //RECYCLER
        val rv = findViewById(R.id.myRecycler) as RecyclerView
        rv.layoutManager = LinearLayoutManager(this)
        rv.itemAnimator = DefaultItemAnimator()

        //SET ADAPTER
        rv.adapter = adapter

    }
// end
}

예제 4: Android MySQL – RecyclerView 체크박스 – INSERT,SELECT,SHOW

이것은 체크박스가 있는 안드로이드 mysql 리사이클러뷰 튜토리얼입니다. 우리는 mysql 데이터베이스를 사용하여 텍스트 및 부울 값으로 작업하는 방법을 봅니다.

  • 오늘은 MySQL 및 RecyclerView를 사용하여 부울 및 텍스트 값으로 작업하는 방법을 살펴봅니다.
  • 먼저 MySQL 데이터베이스에 데이터를 삽입합니다.
  • 입력 보기로 사용하는 구성 요소에는 chcekbox, 스피너 및 재료 편집 텍스트가 포함됩니다.
  • 사용자는 편집 텍스트에 좋아하는 우주선의 이름을 입력한 다음 스피너에서 해당 우주선의 추진제를 선택합니다.
  • 그런 다음 해당 기술이 현재 존재하는지 여부에 대한 확인란을 선택/해제합니다.
  • 버튼 클릭 시 해당 데이터를 MySQL에 저장합니다.
  • 검색’ 버튼을 클릭하면 MySQL에서 데이터를 선택하고 이 텍스트와 부울을 CheckBox가 있는 Checked RecyclerView, RecyclerView에 바인딩합니다.

먼저 전체 참조로 다운로드할 수 있도록 위의 주석이 잘 달린 전체 소스 코드가 있다고 말하겠습니다. 우리는 우리가 사용한 PHP 파일을 포함했습니다. 이 파일을 서버의 루트 디렉토리에 저장하고 사용자 이름, 테이블 이름과 같은 항목을 수정합니다. 등.

비디오 튜토리얼(ProgrammingWizards TV 채널)

이에 대한 대안으로 비디오 자습서가 있습니다. 이와 같은 튜토리얼을 선호한다면 YouTube 채널 구독이 좋습니다.

기본적으로 우리는 매일 튜토리얼, 특히 안드로이드를 하는 프로그래밍을 위한 TV를 가지고 있습니다.

Android MySQL RecyclerView CheckBoxes 삽입, 예제 표시 선택

예를 살펴보겠습니다.

안드로이드 MySQL RecyclerView

MySQL 테이블

다음은 mysql 테이블 구조입니다.

테이블 구조

프로젝트 구조

다음은 프로젝트 구조입니다.

프로젝트 구조

1. PHP 코드

다음은 PHP 코드입니다.

(a) 상수.php

서버 이름, 데이터베이스 이름, 사용자 이름 및 암호와 같은 데이터베이스 상수를 보유하는 PHP 클래스. 이러한 자격 증명은 MySQL 데이터베이스에 연결하는 데 필요합니다.

<?php

class Constants
{
    //DATABASE DETAILS
    static $DB_SERVER="localhost";
    static $DB_NAME="galileoDB";
    static $USERNAME="root";
    static $PASSWORD="";
    const TB_NAME="galileoTB";
    //STATEMENTS
    static $SQL_SELECT_ALL="SELECT * FROM galileoTB";
}
(b) CRUD.php

이 PHP 파일을 사용하면 요청을 수신하고 처리하여 HTTP 클라이언트에서 데이터를 수신할 수 있습니다. 우리는 DBAdapater.php 클래스에 정의된 CRUD 작업을 시작하여 이러한 요청을 처리합니다.

<?php

require_once("/DBAdapter.php");
if($_POST['action']=="save"){

         $dbAdapter=new DBAdapter();
         $name=$_POST['name'];
         $propellant=$_POST['propellant'];
         $technologyexists=$_POST['technologyexists'];
        $dbAdapter->insert(array($name,$propellant,$technologyexists));
}
else if($_POST['action']=="update")
{
         $dbAdapter=new DBAdapter();
         $id=$_POST['id'];
         $name=$_POST['name'];
         $propellant=$_POST['propellant'];
         $technologyexists=$_POST['technologyexists'];
        $dbAdapter->update($id,array($name,$propellant,$technologyexists));

}
else if($_POST['action']=="delete")
{
         $dbAdapter=new DBAdapter();
         $id=$_POST['id'];

        $dbAdapter->delete($id);
}
?>
(c) DBAdapter.php

이 PHP 파일에는 MySQL 데이터베이스에서 CRUD 작업을 수행할 수 있는 기능이 포함됩니다. 이러한 작업에는 데이터베이스에서 데이터 삽입 및 검색이 포함됩니다.

<?php

require_once("/Constants.php");
class DBAdapter
{
/*******************************************************************************************************************************************/
/*
   1.CONNECT TO DATABASE.
   2. RETURN CONNECTION OBJECT
*/
    public function connect()
    {

       $con=mysqli_connect(Constants::$DB_SERVER,Constants::$USERNAME,Constants::$PASSWORD,Constants::$DB_NAME);
        if(mysqli_connect_error(!$con))
        {
           // echo "Unable To Connect";
            return null;
        }else
        {

            return $con;
        }
    }
    /*******************************************************************************************************************************************/
/*
   1.INSERT SPACECRAFT INTO DATABASE
 */
    public function insert($s)
    {
        // INSERT
        $con=$this->connect();

        if($con != null)
        {
            $sql="INSERT INTO galileoTB(name,propellant,technologyexists) VALUES('$s[0]','$s[1]','$s[2]')";
            try
            {
                $result=mysqli_query($con,$sql);
                if($result)
                {
                    print(json_encode(array("Success")));
                }else
                {
                    print(json_encode(array("Unsuccessfull")));
                }
            }catch (Exception $e)
            {
               print(json_encode(array("PHP EXCEPTION : CAN'T SAVE TO MYSQL. "+$e->getMessage())));
            }
        }else{
            print(json_encode(array("PHP EXCEPTION : CAN'T CONNECT TO MYSQL. NULL CONNECTION.")));
        }
        mysqli_close($con);
    }
/*******************************************************************************************************************************************/
/*
   1.SELECT FROM DATABASE.
*/
    public function select()
    {
       $con=$this->connect();
        if($con != null)
        {
            $retrieved=mysqli_query($con,Constants::$SQL_SELECT_ALL);
            if($retrieved)
            {
                while($row=mysqli_fetch_array($retrieved))
                {

                   // echo $row["name"] ,"    t | ",$row["propellant"],"</br>";
                   $spacecrafts[]=$row;
                }
                print(json_encode($spacecrafts));
            }else
            {
                 print(json_encode(array("PHP EXCEPTION : CAN'T RETRIEVE FROM MYSQL. ")));
            }
        }else{
            print(json_encode(array("PHP EXCEPTION : CAN'T CONNECT TO MYSQL. NULL CONNECTION.")));
        }
        mysqli_close($con);
    }
/*******************************************************************************************************************************************/
/*
   1.UPDATE  DATABASE.

*/
    public function update($id, $s)
    {
        // UPDATE
        $con=$this->connect();

        if($con != null)
        {
            $sql="UPDATE galileoTB SET name='$s[0]',propellant='$s[1]',technologyexists='$s[2]' WHERE id='$id'";
            try
            {
                $result=mysqli_query($con,$sql);
                if($result)
                {
                    print(json_encode(array("Successfully Updated")));
                }else
                {
                    print(json_encode(array("Not Successfully Updated")));
                }
            }catch (Exception $e)
            {
                 print(json_encode(array("PHP EXCEPTION : CAN'T UPDATE INTO MYSQL. "+$e->getMessage())));
            }
        }else{
            print(json_encode(array("PHP EXCEPTION : CAN'T CONNECT TO MYSQL. NULL CONNECTION.")));
        }
        mysqli_close($con);
    }
/*******************************************************************************************************************************************/
/*
   1.DELETE SPACECRAFT FROM DATABASE.

*/
    public function delete($id)
    {
        $con=$this->connect();

        if($con != null)
        {
//            $name=$_POST['Name'];
//            $pos=$_POST['Position'];
//            $team=$_POST['Team'];
            $sql="DELETE FROM galileoTB WHERE id='$id'";
            try
            {
                $result=mysqli_query($con,$sql);
                if($result)
                {
                    print(json_encode(array("Successfully Deleted")));
                }else
                {
                    print(json_encode(array("Not Successfully Deleted")));
                }
            }catch (Exception $e)
            {
                print(json_encode(array("PHP EXCEPTION : CAN'T DELETE FROM MYSQL. "+$e->getMessage())));
            }
        }else{
            print(json_encode(array("PHP EXCEPTION : CAN'T CONNECT TO MYSQL. NULL CONNECTION.")));
        }
        mysqli_close($con);
    }

}
(d) Index.php

<?php

require_once("/DBAdapter.php");
    $dbAdapter=new DBAdapter();
    $dbAdapter->select();
?>

2. Gradle 스크립트

다음은 build.gradle 파일의 gradle 스크립트입니다.

(ㅏ). build.gradle(앱)

다음은 앱 수준 build.gradle 파일입니다. 종속성을 추가하는 종속성 DSL이 있습니다.

이 파일은 프로젝트의 앱 폴더에 있기 때문에 앱 레벨 build.gradle이라고 합니다.

Android Studio 버전 3 이상을 사용하는 경우 ‘implementation’ 키워드를 사용하고 3 미만 버전을 사용하는 경우 여전히 ‘compile’ 키워드를 사용합니다.

build.gradle 파일을 수정했으면 프로젝트를 동기화해야 합니다. Android Studio는 실제로 그렇게 하라는 메시지를 표시합니다.

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    testImplementation 'junit:junit:4.12'
    implementation 'com.android.support:appcompat-v7:24.2.0'
    implementation 'com.android.support:design:24.2.0'
    implementation 'com.android.support:cardview-v7:24.2.0'
    implementation 'com.amitshekhar.android:android-networking:0.2.0'
}

우리는 Fast Android Networking Library를 HTTP 클라이언트로 사용하고 있습니다. 최신 버전을 사용할 수 있습니다.

삼. 자원

Android 플랫폼은 정적 콘텐츠를 리소스로 추가하는 강력하고 유연한 방법을 제공합니다.

이러한 정적 콘텐츠는 APK 파일에도 패키징됩니다. 정적 콘텐츠는 리소스 또는 자산으로 저장됩니다.

리소스는 지정된 유형에 속합니다. 이러한 유형은 다음과 같을 수 있습니다.

  1. 드로어블.
  2. 레이아웃.
  3. 가치.

레이아웃 리소스부터 살펴보겠습니다.

(ㅏ). 모델.xml

우리의 행 모델 레이아웃.

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
    android_orientation="horizontal" android_layout_width="match_parent"

    android_layout_margin="10dp"
    card_view_cardCornerRadius="5dp"
    card_view_cardElevation="5dp"
    android_layout_height="200dp">

        <LinearLayout
            android_orientation="vertical"
            android_layout_width="match_parent"
            android_layout_height="match_parent">

            <TextView
                android_layout_width="match_parent"
                android_layout_height="wrap_content"
                android_textAppearance="?android:attr/textAppearanceLarge"
                android_text="Name"
                android_id="@+id/nameTxt"
                android_padding="10dp"
                android_textColor="@color/colorAccent"
                android_textStyle="bold"
                android_layout_alignParentLeft="true"
                />

            <TextView
                android_layout_width="wrap_content"
                android_layout_height="wrap_content"
                android_textAppearance="?android:attr/textAppearanceLarge"
                android_text="Propellant....................."
                android_id="@+id/txtPropellant"
                android_padding="10dp"
                android_layout_alignParentLeft="true"
                />
            <CheckBox
                android_layout_width="wrap_content"
                android_layout_height="wrap_content"
                android_textSize="25dp"
                android_id="@+id/chkTechExists"
                android_checked="true" />

    </LinearLayout>

</androidx.cardview.widget.CardView>
(b). 내용_main.xml
(씨). 활동_main.xml

이 레이아웃은 기본 활동의 사용자 인터페이스로 확장됩니다. 이것은 레이아웃을 전달해야 하는 활동의 setContentView() 메서드를 통해 발생합니다.

Activity의 ‘onCreate()’ 메서드 내에서 수행합니다.

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout

    android_layout_width="match_parent"
    android_layout_height="match_parent"
    android_fitsSystemWindows="true"
    tools_context="com.tutorials.hp.mysqlrecyclerbool.MainActivity">

    <android.support.design.widget.AppBarLayout
        android_layout_width="match_parent"
        android_layout_height="wrap_content"
        android_theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android_id="@+id/toolbar"
            android_layout_width="match_parent"
            android_layout_height="?attr/actionBarSize"
            android_background="?attr/colorPrimary"
            app_popupTheme="@style/AppTheme.PopupOverlay" />

    </android.support.design.widget.AppBarLayout>

    <include layout="@layout/content_main" />

    <android.support.design.widget.FloatingActionButton
        android_id="@+id/fab"
        android_layout_width="wrap_content"
        android_layout_height="wrap_content"
        android_layout_gravity="bottom|end"
        android_layout_margin="@dimen/fab_margin"
        android_src="@android:drawable/ic_dialog_email" />

</android.support.design.widget.CoordinatorLayout>

삼. 자바 코드.

Android 앱은 주로 Java 또는 Kotlin으로 작성할 수 있습니다. 그러나 요즘에는 Dart와 같은 언어를 사용하는 Flutter와 같은 많은 프레임워크가 있습니다.

이 수업에서는 Java 프로그래밍 언어를 사용합니다.

우리 프로젝트에는 이러한 수업이 포함될 것입니다.

(ㅏ). 우주선.자바

먼저 가상 우주선의 속성을 정의하겠습니다.

package com.tutorials.hp.mysqlrecyclerbool.mModel;

public class Spacecraft {

    /*
    INSTANCE FIELDS
     */
    private int id;
    private String name;
    private String propellant;
    private int technologyExists;

    /*
    GETTERS AND SETTERS
     */
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public String getPropellant() {
        return propellant;
    }

    public void setPropellant(String propellant) {
        this.propellant = propellant;
    }

    public int getTechnologyExists() {
        return technologyExists;
    }

    public void setTechnologyExists(int technologyExists) {
        this.technologyExists = technologyExists;
    }

    /*
    TOSTRING
     */
    @Override
    public String toString() {
        return name;
    }
}

MySQL 테이블 구조

(b). MySQL클라이언트.자바

우리는 네트워크 호출을 위해 Android 네트워킹 라이브러리를 사용하고 있습니다. 백그라운드 스레드에서 수행하며 사용하기 쉽고 빠릅니다. 쉽게 구문 분석할 수 있는 JSOn 응답을 반환합니다. 아래는 MySQL 클라이언트입니다.

package com.tutorials.hp.mysqlrecyclerbool.mMySQL;

import android.content.Context;
import androidx.recyclerview.widget.RecyclerView;
import android.view.View;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.Toast;

import com.androidnetworking.AndroidNetworking;
import com.androidnetworking.common.Priority;
import com.androidnetworking.error.ANError;
import com.androidnetworking.interfaces.JSONArrayRequestListener;
import com.tutorials.hp.mysqlrecyclerbool.mAdapter.MyAdapter;
import com.tutorials.hp.mysqlrecyclerbool.mModel.Spacecraft;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;

public class MySQLClient {

    //SAVE/RETRIEVE URLS
    private static final String DATA_INSERT_URL="http://10.0.2.2/android/Aristotle/crud.php";
    private static final String DATA_RETRIEVE_URL="http://10.0.2.2/android/Aristotle/index.php";

    //INSTANCE FIELDS
    private final Context c;
    private MyAdapter adapter ;

    public MySQLClient(Context c) {
        this.c = c;

    }
    /*
   SAVE/INSERT
    */
    public void add(Spacecraft s, final View...inputViews)
    {
        if(s==null)
        {
            Toast.makeText(c, "No Data To Save", Toast.LENGTH_SHORT).show();
        }
        else
        {
            AndroidNetworking.post(DATA_INSERT_URL)

                    .addBodyParameter("action","save")
                    .addBodyParameter("name",s.getName())
                    .addBodyParameter("propellant",s.getPropellant())
                    .addBodyParameter("technologyexists",String.valueOf(s.getTechnologyExists()))
                    .setTag("TAG_ADD")
                    .build()
                    .getAsJSONArray(new JSONArrayRequestListener() {
                        @Override
                        public void onResponse(JSONArray response) {

                            if(response != null)
                                try {
                                    //SHOW RESPONSE FROM SERVER
                                    String responseString = response.get(0).toString();
                                    Toast.makeText(c, "PHP SERVER RESPONSE : " + responseString, Toast.LENGTH_SHORT).show();

                                    if (responseString.equalsIgnoreCase("Success")) {
                                        //RESET VIEWS
                                        EditText nameTxt = (EditText) inputViews[0];
                                        Spinner spPropellant = (Spinner) inputViews[1];

                                        nameTxt.setText("");
                                        spPropellant.setSelection(0);
                                    }else
                                    {
                                        Toast.makeText(c, "PHP WASN'T SUCCESSFUL. ", Toast.LENGTH_SHORT).show();

                                    }

                                } catch (JSONException e) {
                                    e.printStackTrace();
                                    Toast.makeText(c, "GOOD RESPONSE BUT JAVA CAN'T PARSE JSON IT RECEIVED : "+e.getMessage(), Toast.LENGTH_SHORT).show();
                                }

                        }

                        //ERROR
                        @Override
                        public void onError(ANError anError) {
                            Toast.makeText(c, "UNSUCCESSFUL :  ERROR IS : "+anError.getMessage(), Toast.LENGTH_SHORT).show();
                        }

                    });

        }
    }

    /*
    RETRIEVE/SELECT/REFRESH
     */
    public void retrieve(final RecyclerView rv)
    {
        final ArrayList<Spacecraft> spacecrafts = new ArrayList<>();

        AndroidNetworking.get(DATA_RETRIEVE_URL)
                .setPriority(Priority.HIGH)
                .build()
                .getAsJSONArray(new JSONArrayRequestListener() {
                    @Override
                    public void onResponse(JSONArray response) {
                        JSONObject jo;
                        Spacecraft s;
                        try
                        {
                            for(int i=0;i<response.length();i++)
                            {
                                jo=response.getJSONObject(i);

                                int id=jo.getInt("id");
                                String name=jo.getString("name");
                                String propellant=jo.getString("propellant");
                                String techExists=jo.getString("technologyexists");

                                s=new Spacecraft();
                                s.setId(id);
                                s.setName(name);
                                s.setPropellant(propellant);
                                s.setTechnologyExists(techExists.equalsIgnoreCase("1") ? 1 : 0);

                                spacecrafts.add(s);
                            }

                            //SET TO RECYCLERVIEW
                            adapter =new MyAdapter(c,spacecrafts);
                            rv.setAdapter(adapter);

                        }catch (JSONException e)
                        {
                            Toast.makeText(c, "GOOD RESPONSE BUT JAVA CAN'T PARSE JSON IT RECEIEVED. "+e.getMessage(), Toast.LENGTH_LONG).show();

                        }

                    }

                    //ERROR
                    @Override
                    public void onError(ANError anError) {
                        anError.printStackTrace();
                        Toast.makeText(c, "UNSUCCESSFUL :  ERROR IS : "+anError.getMessage(), Toast.LENGTH_LONG).show();

                    }

                });

    }

}
(씨). 마이뷰홀더.자바

ViewHolder 클래스.

package com.tutorials.hp.mysqlrecyclerbool.mAdapter;

import androidx.recyclerview.widget.RecyclerView;
import android.view.View;
import android.widget.CheckBox;
import android.widget.TextView;

import com.tutorials.hp.mysqlrecyclerbool.R;

public class MyViewHolder extends RecyclerView.ViewHolder {

    TextView txtName,txtPropellant;
    CheckBox chkTechExists;
    public MyViewHolder(View view) {
        super(view);

         txtName = (TextView) view.findViewById(R.id.nameTxt);
         txtPropellant = (TextView) view.findViewById(R.id.txtPropellant);

         chkTechExists = (CheckBox) view.findViewById(R.id.chkTechExists);
    }
}
(d). 마이어댑터.자바

아래는 RecyclerView.Adapter 클래스입니다. MySQL에는 기본 부울 데이터 유형이 없습니다. 부울 확인란 값을 null 허용 정수로 매핑합니다.

package com.tutorials.hp.mysqlrecyclerbool.mAdapter;

import android.content.Context;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.tutorials.hp.mysqlrecyclerbool.R;
import com.tutorials.hp.mysqlrecyclerbool.mModel.Spacecraft;

import java.util.ArrayList;

public class MyAdapter extends RecyclerView.Adapter<MyViewHolder> {
    /*
    INSTANCE FIELDS
     */
    private Context c;
    private ArrayList<Spacecraft> spacecrafts;

    /*
    CONSTRUCTOR
     */
    public MyAdapter(Context c, ArrayList<Spacecraft> spacecrafts) {
        this.c = c;
        this.spacecrafts = spacecrafts;
    }

    /*
    INITIALIZE VIEWHOLDER
     */
    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v= LayoutInflater.from(c).inflate(R.layout.model,parent,false);
        return new MyViewHolder(v);
    }

    /*
    BIND DATA
     */
    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {

        Spacecraft s=spacecrafts.get(position);

        holder.txtName.setText(s.getName());
        holder.txtPropellant.setText(s.getPropellant());
        holder.chkTechExists.setChecked(s.getTechnologyExists()==1);
    }

    /*
    TOTAL NUM OF SPACECRAFTS
     */
    @Override
    public int getItemCount() {
        return spacecrafts.size();
    }
}
(d). 메인 액티비티.자바

이것은 이름에서 알 수 있듯이 런처 활동입니다. 즉, 사용자가 앱의 아이콘을 클릭하면 이 활동이 먼저 렌더링된다는 점에서 앱의 주요 진입점이 됩니다.

우리는 onCreate()라는 메서드를 재정의합니다. 여기서는 setContentView() 메소드를 통해 기본 레이아웃을 확장하는 것으로 시작합니다.

우리의 주요 활동은 AppCompatActivity에서 파생되기 때문에 실제로 활동입니다.

package com.tutorials.hp.mysqlrecyclerbool;

import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.TextInputEditText;
import androidx.appcompat.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.Spinner;
import android.widget.Toast;

import com.tutorials.hp.mysqlrecyclerbool.mAdapter.MyAdapter;
import com.tutorials.hp.mysqlrecyclerbool.mModel.Spacecraft;
import com.tutorials.hp.mysqlrecyclerbool.mMySQL.MySQLClient;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

    //INSTANCE FIELDS
    private TextInputEditText txtName;
    private CheckBox chkTechnologyExists;
    private Spinner spPropellant;
    private RecyclerView rv;
    private Button btnAdd,btnRetrieve;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        //REFERENCE VIEWS
        this.initializeViews();

        populatePropellants();

        //HANDLE EVENTS
        this.handleClickEvents();

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                rv.setAdapter(new MyAdapter(MainActivity.this,new ArrayList<Spacecraft>()));
            }
        });

    }

    /*
    REFERENCE VIEWS
     */
    private void initializeViews()
    {

        txtName= (TextInputEditText) findViewById(R.id.nameTxt);
        chkTechnologyExists= (CheckBox) findViewById(R.id.techExists);
        spPropellant= (Spinner) findViewById(R.id.sp);
        rv= (RecyclerView) findViewById(R.id.rv);

        btnAdd= (Button) findViewById(R.id.addBtn);
        btnRetrieve= (Button) findViewById(R.id.refreshBtn);

        rv.setLayoutManager(new LinearLayoutManager(MainActivity.this));

    }

    /*
    HANDLE CLICK EVENTS
     */
    private void handleClickEvents()
    {
        //EVENTS : ADD
        btnAdd.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                //GET VALUES
                String name=txtName.getText().toString();
                String propellant=spPropellant.getSelectedItem().toString();
                Boolean technologyexists=chkTechnologyExists.isChecked();

                //BASIC CLIENT SIDE VALIDATION
                if((name.length()<1 || propellant.length()<1  ))
                {
                    Toast.makeText(MainActivity.this, "Please Enter all Fields", Toast.LENGTH_SHORT).show();
                }
                else
                {
                    //SAVE

                    Spacecraft s=new Spacecraft();
                    s.setName(name);
                    s.setPropellant(propellant);
                    s.setTechnologyExists(technologyexists ? 1 : 0);

                    new MySQLClient(MainActivity.this).add(s,txtName,spPropellant);
                }
            }
        });

        //EVENTS : RETRIEVE
        btnRetrieve.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                new MySQLClient(MainActivity.this).retrieve(rv);

            }
        });

    }

    private void populatePropellants()
    {
        ArrayAdapter<String> adapter=new ArrayAdapter<String>(this,android.R.layout.simple_spinner_dropdown_item);

        adapter.add("None");
        adapter.add("Chemical Energy");
        adapter.add("Nuclear Energy");
        adapter.add("Laser Beam");
        adapter.add("Anti-Matter");
        adapter.add("Plasma Ions");
        adapter.add("Warp Drive");

        spPropellant.setAdapter(adapter);
        spPropellant.setSelection(0);

    }
}

AndroidManifest.xml

인터넷 연결에 대한 권한을 추가했는지 확인하십시오.

<?xml version="1.0" encoding="utf-8"?>
<manifest
    package="com.tutorials.hp.mysqlrecyclerbool">

    <uses-permission android_name="android.permission.INTERNET"/>

    <application
        android_allowBackup="true"
        android_icon="@mipmap/ic_launcher"
        android_label="@string/app_name"
        android_supportsRtl="true"
        android_theme="@style/AppTheme">
        <activity
            android_name=".MainActivity"
            android_label="@string/app_name"
            android_theme="@style/AppTheme.NoActionBar">
            <intent-filter>
                <action android_name="android.intent.action.MAIN" />

                <category android_name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

다운로드

이봐, 모든 것은 주석 처리가 잘 되어 있고 이해하기 쉬운 소스 코드 참조에 있으며 아래에서 다운로드할 수 있습니다.

또한 비디오 자습서를 확인하십시오. 더 자세하고 단계별로 설명되어 있습니다.

직접 다운로드
찾아보기