코디네이터레이아웃 사용해서 스크롤시 

툴바 및 리사이클러뷰 스크롤시 최상단 및 최하단 터치 감지가 불량일 때가 있다.

최상단 혹은 최하단 스크롤 후 리스트 항목을 클릭이 되지 않아 두번 클릭해야하는데 


안드로이드 sdk 28에서는 정상동작 한다.

이전 버전에서 AppBarLayout.Behavior 에 버그가 있는듯.



android coordinatorlayout recyclerview scroll click

이렇게 검색하니 스택오버플로우에 올라온 글

Click not working on RecyclerView in CoordinatorLayout when scrolling



게시글 중 해당 링크가 있고 수정된 코드 java와 kotlin이 있음.


https://gist.github.com/chrisbanes/8391b5adb9ee42180893300850ed02f2



수정된 코드소스

java

//////////////////////////////////////////////////////////////////////////////////////////

/**

 * Workaround AppBarLayout.Behavior for https://issuetracker.google.com/66996774

 *

 * See https://gist.github.com/chrisbanes/8391b5adb9ee42180893300850ed02f2 for

 * example usage.

 *

 * Change the package name as you wish.

 */

public class FixAppBarLayoutBehavior extends AppBarLayout.Behavior {


    public FixAppBarLayoutBehavior() {

        super();

    }


    public FixAppBarLayoutBehavior(Context context, AttributeSet attrs) {

        super(context, attrs);

    }


    @Override

    public void onNestedScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target,

            int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int type) {

        super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed,

                dxUnconsumed, dyUnconsumed, type);

        stopNestedScrollIfNeeded(dyUnconsumed, child, target, type);

    }


    @Override

    public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child,

            View target, int dx, int dy, int[] consumed, int type) {

        super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed, type);

        stopNestedScrollIfNeeded(dy, child, target, type);

    }


    private void stopNestedScrollIfNeeded(int dy, AppBarLayout child, View target, int type) {

        if (type == ViewCompat.TYPE_NON_TOUCH) {

            final int currOffset = getTopAndBottomOffset();

            if ((dy < 0 && currOffset == 0)

                    || (dy > 0 && currOffset == -child.getTotalScrollRange())) {

                ViewCompat.stopNestedScroll(target, ViewCompat.TYPE_NON_TOUCH);

            }

        }

    }

}


//////////////////////////////////////////////////////////////////////////////////////////


kotlin

//////////////////////////////////////////////////////////////////////////////////////////

/**

 * Workaround AppBarLayout.Behavior for https://issuetracker.google.com/66996774

 *

 *

 * See https://gist.github.com/chrisbanes/8391b5adb9ee42180893300850ed02f2 for

 * example usage.

 *

 * Kotlinised by Erik Huizinga (github: @erikhuizinga).

 */

class FixAppBarLayoutBehavior(context: Context?, attrs: AttributeSet?) :

AppBarLayout.Behavior(context, attrs) {


override fun onNestedScroll(coordinatorLayout: CoordinatorLayout, child: AppBarLayout,

                            target: View, dxConsumed: Int, dyConsumed: Int, dxUnconsumed: Int,

                            dyUnconsumed: Int, type: Int) {

super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed,

dyUnconsumed, type)

stopNestedScrollIfNeeded(dyUnconsumed, child, target, type)

}


override fun onNestedPreScroll(coordinatorLayout: CoordinatorLayout, child: AppBarLayout,

                               target: View, dx: Int, dy: Int, consumed: IntArray, type: Int) {

super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed, type)

stopNestedScrollIfNeeded(dy, child, target, type)

}


private fun stopNestedScrollIfNeeded(dy: Int, child: AppBarLayout, target: View, type: Int) {

if (type == ViewCompat.TYPE_NON_TOUCH) {

val currOffset = topAndBottomOffset

if (dy < 0 && currOffset == 0 || dy > 0 && currOffset == -child.totalScrollRange) {

ViewCompat.stopNestedScroll(target, ViewCompat.TYPE_NON_TOUCH)

}

}

}

}

//////////////////////////////////////////////////////////////////////////////////////////


코드 사용법 

AppBarLayout abl = findViewById(R.id.app_bar);

((CoordinatorLayout.LayoutParams) abl.getLayoutParams()).setBehavior(new FixAppBarLayoutBehavior());



xml 사용법

<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"

        xmlns:app="http://schemas.android.com/apk/res-auto"

        android:layout_width="match_parent"

        android:layout_height="match_parent">


    <android.support.design.widget.AppBarLayout

            android:id="@+id/app_bar"

            android:layout_height="..."

            android:layout_width="..."

            app:layout_behavior="your.package.FixAppBarLayoutBehavior">


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


    <!-- Content -->


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






코틀린 리사이클러뷰 예제



매인액티비티 생성.

MainActivity.kt

//////////////////////////////////////////////////////////////////////////////////////////


class MainActivity : AppCompatActivity() {


    override fun onCreate(savedInstanceState: Bundle?) {

        super.onCreate(savedInstanceState)

        setContentView(R.layout.activity_main)


    }

}

//////////////////////////////////////////////////////////////////////////////////////////



Build.gradle(Module:app)에 com.android.support:recyclerview-v7 모듈 추가

//////////////////////////////////////////////////////////////////////////////////////////

dependencies {

    implementation fileTree(include: ['*.jar'], dir: 'libs')

    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"

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

    implementation 'com.android.support.constraint:constraint-layout:1.1.3'

    testImplementation 'junit:junit:4.12'

    androidTestImplementation 'com.android.support.test:runner:1.0.2'

    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'

//리사이클러뷰 모듈 추가.

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

}

//////////////////////////////////////////////////////////////////////////////////////////


리사이클러뷰에 사용할 데이터 생성.


간단한 데이터 출력 하기위한 클래스 생성.

People.Kt

//////////////////////////////////////////////////////////////////////////////////////////

/**

 * 데이터 클래스 생성 및 초기화

 * 바로 생성자를 넣어서 만들어지게 구현.

 * 코틀린에서는 data class 를 지원 하며

 * java에서 처럼 toString 처리 하지 않아도 됨.

 */

data class People(val name: String, val age: String, val address: String)

//////////////////////////////////////////////////////////////////////////////////////////





리사이클러뷰에 보여줄 row layout 생성.


간단히 name, age, address 보여줌.


listview_row.xml

//////////////////////////////////////////////////////////////////////////////////////////

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

<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:app="http://schemas.android.com/apk/res-auto"

    android:layout_width="match_parent"

    android:layout_height="wrap_content">



    <android.support.constraint.ConstraintLayout

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        android:layout_marginLeft="10dp"

        android:layout_marginTop="10dp"

        android:layout_marginRight="10dp"

        app:layout_constraintTop_toTopOf="parent">



        <TextView

            android:id="@+id/name"

            android:layout_width="match_parent"

            android:layout_height="wrap_content"

            android:text="name"

            app:layout_constraintTop_toTopOf="parent" />


        <TextView

            android:id="@+id/age"

            android:layout_width="match_parent"

            android:layout_height="wrap_content"

            android:text="age"

            app:layout_constraintTop_toBottomOf="@+id/name" />


        <TextView

            android:id="@+id/address"

            android:layout_width="match_parent"

            android:layout_height="wrap_content"

            android:text="address"

            app:layout_constraintTop_toBottomOf="@+id/age" />



    </android.support.constraint.ConstraintLayout>

</android.support.constraint.ConstraintLayout>

//////////////////////////////////////////////////////////////////////////////////////////



뷰홀더 클래스 생성. RecyclerView.ViewHolder 상속

TestHolder_01.kt

//////////////////////////////////////////////////////////////////////////////////////////

/**생성자 지정 , 상위클래스 view 넘겨줌.  super(itemView);*/

class TestHolder_01(itemView: View) : RecyclerView.ViewHolder(itemView) {

    // 뷰 홀더를 상속 받고나면 생성자에서 상위 홀더에 view 를 전달.

    

    

    val name: TextView

    val age: TextView

    val address: TextView

    

    

    /**

     * 코틀린사용한 초기화

     * 초기화 블럭.

     */

    init {

        this.name = itemView.findViewById(R.id.name)

        this.age = itemView.findViewById(R.id.age)

        this.address = itemView.findViewById(R.id.address)

    }


    

    /**팩토리 함수 */

    companion object {

        fun newInstance(viewGroup: ViewGroup): TestHolder_01 {

            val view = LayoutInflater.from(viewGroup.context).inflate(R.layout.listview_row, viewGroup, false)

            return TestHolder_01(view)

        }

    }


    fun onBindView(position: Int, list: ArrayList<People>) {

        // 데이터를 화면에 그리기.

        name.text = list[position].name

        age.text = list[position].age

        address.text = list[position].address

    }

}

//////////////////////////////////////////////////////////////////////////////////////////





리사이클러뷰 아답터 생성.

TestAdapter_01.kt

//////////////////////////////////////////////////////////////////////////////////////////

/**생성자에서 리스트를 받아옴.*/

class TestAdapter_01(val list: ArrayList<People>) : RecyclerView.Adapter<TestHolder_01>() {



    override fun onCreateViewHolder(p0: ViewGroup, p1: Int): TestHolder_01 {

        //팩토리함수를 이용한 뷰홀더 생성.

        return TestHolder_01.newInstance(p0)

    }


    override fun getItemCount(): Int {

        return list.size

    }


    override fun onBindViewHolder(p0: TestHolder_01, p1: Int) {

        // 홀더에 정의된 함수로 뷰 그리기

        p0.onBindView(p1, list)

    }

}

//////////////////////////////////////////////////////////////////////////////////////////


activity_main.xml

//////////////////////////////////////////////////////////////////////////////////////////

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

<android.support.constraint.ConstraintLayout 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">


    <android.support.v7.widget.RecyclerView

        android:id="@+id/recyclerView"

        android:layout_width="match_parent"

        android:layout_height="match_parent"

        android:orientation="vertical"

        app:layoutManager="android.support.v7.widget.LinearLayoutManager">


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


</android.support.constraint.ConstraintLayout>

//////////////////////////////////////////////////////////////////////////////////////////



MainActivity.kt

//////////////////////////////////////////////////////////////////////////////////////////

class MainActivity : AppCompatActivity() {


    override fun onCreate(savedInstanceState: Bundle?) {

        super.onCreate(savedInstanceState)

        setContentView(R.layout.activity_main)

//UI그리기

        setupUI()

    }


//data 생성

    fun setData(): ArrayList<People> {


        val list = arrayListOf<People>()

        for (i in 0 until 30) {

            list.add(People("$i name", "$i age", "$i address"))

        }

        list.forEach {

            Log.e("log", "$it")

        }

        return list

    }


    fun setupUI() {

    //아답터 등록 후 끝.

        recyclerView.adapter = TestAdapter_01(setData())

        

    }

}


//////////////////////////////////////////////////////////////////////////////////////////

2-2 펴미션 구현.

상속을 통한 퍼미션 구현.


BaseActivity 소스 추가.

//////////////////////////////////////////////////////////////////////////////////////////

abstract class BaseActivity extends AppCompatActivity {


    abstract int setLayout();


    @Override

    protected void onCreate(@Nullable Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(setLayout());

    }



/**

* 아래 소스 추가 부분.

*/


    /**

     * 앱 퍼미션 권한 사용하기 위하여 상속을 이용

     * 퍼미션 체크가 끝나면 동작할 인터페이스 리스너 생성

     * 퍼미션 체크 메서드 구현.

     * onRequestPermissionsResult 를 동작하고 난뒤 액티비티로 돌아와 나머지 동작 구현 확인.

     * 리스너 등록하여 퍼미션 체크한 액티비티로 돌아가기.

     */


    /**

     * 인터페이스 등록.

     */

    public interface PermissionCheckListener {

        void permissionCheckFinish();

    }


    /**

     * 상속받은 클래스에서 사용할 인터페이스 변수.

     */

    public PermissionCheckListener permissionCheckListener;


    /**

     * 온 크레딧 바로 아래 생성 되어야 한다

     */

    public void setPermissionCheckListener(PermissionCheckListener permissionCheckListener) {

        this.permissionCheckListener = permissionCheckListener;

    }


    private final int PERMISSION_REQUEST = 1000;


    /**

     * 스트링 배열로 퍼미션 체크.

     */


    public boolean permissionCheck(String[] strings) {


        //  변수 사용시 리턴 타입 지정

        // boolean check = false;

        // 변수 사용안하면 바로 리턴 시킴.



        /**안드로이드 마시멜로 이후 퍼미션 체크.*/

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

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

                if (ContextCompat.checkSelfPermission(this, strings[i]) == PackageManager.PERMISSION_DENIED) {

                    ActivityCompat.requestPermissions(this, strings, PERMISSION_REQUEST);

                    // check = true;

                    // break;

                    return true;

                }

            }

        }

//return check;

        return false;

    }


    /**

     * 거부를 했을때 처리

     * 다시보지 않기 체크 후 거부를 하면 설정에서 권한을 허용하도록 요청.

     * 허용하지 않을 경우 앱 사용 을 못함..

     * 처리를 잘못하면 무한 반복할 경우가 생김.

     */


    @Override

    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {


        super.onRequestPermissionsResult(requestCode, permissions, grantResults);



        if (requestCode == PERMISSION_REQUEST) {

            //안드로이드 마시멜로 이후 퍼미션 체크.

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

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

                    if (grantResults[i] == 0) {

                        if (grantResults.length == (i + 1)) {

                            permissionCheckListener.permissionCheckFinish();

                        }

                    } else {

                        // 거부한 이력이 있으면 true를 반환한다.

                        if (shouldShowRequestPermissionRationale(permissions[i])) {

                            ActivityCompat.requestPermissions(this, permissions, PERMISSION_REQUEST);

                            break;


                        } else {

                            new AlertDialog.Builder(this)

                                    .setTitle("다시보지않기 클릭.")

                                    .setMessage(permissions[i] + " 권한이 거부되었습니다 설정에서 직접 권한을 허용 해주세요.")

                                    .setNeutralButton("설정", new DialogInterface.OnClickListener() {


                                        @Override

                                        public void onClick(DialogInterface dialog, int which) {


                                            Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);

                                            intent.setData(Uri.parse("package:" + getPackageName()));

                                            startActivity(intent);

                                            Toast.makeText(getApplicationContext(), "권한 설정 후 다시 실행 해주세요.", Toast.LENGTH_SHORT).show();

                                            finish();

                                        }

                                    })

                                    .setPositiveButton("확인", new DialogInterface.OnClickListener() {


                                        @Override

                                        public void onClick(DialogInterface dialog, int which) {

                                            Toast.makeText(getApplicationContext(), "권한 설정을 하셔야 앱을 사용할 수 있습니다.", Toast.LENGTH_SHORT).show();

                                            finish();

                                        }

                                    })

                                    .setCancelable(false)

                                    .create().show();

                        }// shouldShowRequestPermissionRationale /else

                    } // 권한 거절

                } // for end

            }//Build.VERSION.SDK_INT  end

        }//requestCode  end

    }

}

//////////////////////////////////////////////////////////////////////////////////////////






MainActivity에서 사용 방법.


Manifest에 

<uses-permission android:name="android.permission.CAMERA" />

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

퍼미션 등록 확인.

//////////////////////////////////////////////////////////////////////////////////////////

public class MainActivity extends BaseActivity {


    @Override

    int setLayout() {

        // BaseActivit에서 만들어 놓은 추상 메서그 구현.

        // setContentView(R.layout.activity_main);

        // 추상메서드로 구현.

        return R.layout.activity_main;

    }


    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);


        /**

         * 리스너 등록

         * 퍼미션 검사가 끝나고 또는 검사 체크 후 구현 될 부분

         */

        setPermissionCheckListener(new PermissionCheckListener() {

            @Override

            public void permissionCheckFinish() {


                Log.e("log", "start Activity");

            }

        });


        /**

         * Manifest 에서 uses-permission 에 등록한 퍼미션 을 배열로 전달

         * 권한 승인을 해야할려면 true 권한 승인이 모두 완료 되어 있다면 false

         * 권한 체크가 되어 있다면 지나간다.

         */

        if (permissionCheck(new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE})) {

            return;

        }


        /**퍼미션 체크 리스너 등록*/

        permissionCheckListener.permissionCheckFinish();

    }

}

//////////////////////////////////////////////////////////////////////////////////////////



상속을 이용한 퍼미션 권한 체크 확인 완료.



'Android > source code' 카테고리의 다른 글

TabLayout 예제  (0) 2018.11.08
코디네이터레이아웃에 리사이클러뷰 스크롤시 터치 오류  (0) 2018.10.17
Android RecyclerView 예제  (0) 2018.10.15
동적 레이아웃 등록(xml)  (0) 2018.10.11
액티비티  (0) 2018.09.18

리사이클러뷰 프로젝트.


매인 액티비티(Empty Activity) 생성.

/////////////////////////////////////////////////////////////////////////////////////////

public class MainActivity extends AppCompatActivity {


    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);


    }

}

/////////////////////////////////////////////////////////////////////////////////////////


Build.gradle(Module:app)에 com.android.support:recyclerview-v7 모듈 추가

/////////////////////////////////////////////////////////////////////////////////////////

dependencies {

    implementation fileTree(include: ['*.jar'], dir: 'libs')

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

    implementation 'com.android.support.constraint:constraint-layout:1.1.3'

    testImplementation 'junit:junit:4.12'

    androidTestImplementation 'com.android.support.test:runner:1.0.2'

    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'

    implementation 'com.github.bearkinf:AndroidLogPrintUtil_Java:1.1.1'

    //리사이클러뷰 모듈 추가.

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

}

/////////////////////////////////////////////////////////////////////////////////////////


리사이클러뷰에 사용할 데이터 생성.

간단한 데이터 출력 하기위한 클래스 생성.

/////////////////////////////////////////////////////////////////////////////////////////

public class People {

    private String name;

    private String age;

    private String address;

    /**

     * 기본 생성자.

     */

    public People() {

    }


    public People(String name) {

        this.name = name;

    }


    public People(String name, String age) {

        this.name = name;

        this.age = age;

    }


    public People(String name, String age, String address) {

        this.name = name;

        this.age = age;

        this.address = address;

    }


    public String getName() {

        return name;

    }


    public void setName(String name) {

        this.name = name;

    }


    public String getAge() {

        return age;

    }


    public void setAge(String age) {

        this.age = age;

    }


    public String getAddress() {

        return address;

    }


    public void setAddress(String address) {

        this.address = address;

    }



    @Override

    public String toString() {

        return "name : " + getName() + " , age : " + getAge() + " , address : " + getAddress();

    }

}

/////////////////////////////////////////////////////////////////////////////////////////



리사이클러뷰에 보여줄 row layout 생성.

간단히 name, age, address 보여줌.

test_list_row.xml

/////////////////////////////////////////////////////////////////////////////////////////

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

<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:app="http://schemas.android.com/apk/res-auto"

    android:layout_width="match_parent"

    android:layout_height="wrap_content">


    <android.support.constraint.ConstraintLayout

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        android:layout_marginLeft="10dp"

        android:layout_marginTop="10dp"

        android:layout_marginRight="10dp"

        app:layout_constraintTop_toTopOf="parent">


        <TextView

            android:id="@+id/name"

            android:layout_width="match_parent"

            android:layout_height="wrap_content"

            android:text="name"

            app:layout_constraintTop_toTopOf="parent" />


        <TextView

            android:id="@+id/age"

            android:layout_width="match_parent"

            android:layout_height="wrap_content"

            android:text="age"

            app:layout_constraintTop_toBottomOf="@+id/name" />


        <TextView

            android:id="@+id/address"

            android:layout_width="match_parent"

            android:layout_height="wrap_content"

            android:text="address"

            app:layout_constraintTop_toBottomOf="@+id/age" />

    </android.support.constraint.ConstraintLayout>

</android.support.constraint.ConstraintLayout>

/////////////////////////////////////////////////////////////////////////////////////////


뷰홀더 클래스 생성. RecyclerView.ViewHolder 상속

/////////////////////////////////////////////////////////////////////////////////////////

public class TestHolder_1 extends RecyclerView.ViewHolder {


    private TextView name;

    private TextView age;

    private TextView address;

    /**

     * 팩토리 함수 생성.

     * new 하는 것을 줄여준다.

     */

    public static TestHolder_1 newInstance(ViewGroup viewGroup) {

    // 뷰 생성 후 홀더에 등록 하여 객채 생성.

        View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.test_list_row, viewGroup, false);

        return new TestHolder_1(view);

    }


    /**

     * 생성자 초기화

     */

    public TestHolder_1(View itemView) {

        super(itemView);


        name = itemView.findViewById(R.id.name);

        age = itemView.findViewById(R.id.age);

        address = itemView.findViewById(R.id.address);

    }


    public void onBindView(int position, ArrayList<People> list) {

        //화면을 그려주는 곳.

        name.setText(list.get(position).getName());

        age.setText(list.get(position).getAge());

        address.setText(list.get(position).getAddress());


    }

}

/////////////////////////////////////////////////////////////////////////////////////////


리사이클러뷰 아답터 생성.

/////////////////////////////////////////////////////////////////////////////////////////


public class TestAdapter_1 extends RecyclerView.Adapter<TestHolder_1> {

    

    private ArrayList<People> list;

    

    /**생성자 (어레이리스트를 인자로 받음.(초기화됨))*/

    public TestAdapter_1(ArrayList<People> list) {

        this.list = list;

    }


    @NonNull

    @Override

    public TestHolder_1 onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {

        //팩토리 함수를 이용한 홀더 객체 생성.

        return TestHolder_1.newInstance(viewGroup);

    }


    @Override

    public void onBindViewHolder(@NonNull TestHolder_1 testHolder_1, int i) {

        // 홀더에 정의된 함수로 뷰 그리기

        testHolder_1.onBindView(i, list);

    }


    @Override

    public int getItemCount() {

        //리스트 갯수 반환.

        return list.size();

    }

}

/////////////////////////////////////////////////////////////////////////////////////////



리사이클러뷰 레이아웃 등록.

activity_main.xml

/////////////////////////////////////////////////////////////////////////////////////////

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

<android.support.constraint.ConstraintLayout 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">


<!-- 레이아웃 매니저 등록, 수직으로 정렬지정-->

    <android.support.v7.widget.RecyclerView

        android:id="@+id/recyclereView"

        android:layout_width="match_parent"

        android:layout_height="match_parent"

        android:orientation="vertical"

        app:layoutManager="android.support.v7.widget.LinearLayoutManager">


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


</android.support.constraint.ConstraintLayout>

/////////////////////////////////////////////////////////////////////////////////////////



매인 액티비티 소스 완성 

/////////////////////////////////////////////////////////////////////////////////////////

public class MainActivity extends AppCompatActivity {


//리사이클러뷰 등록.

    private RecyclerView recyclerView;

// 아답터 등록.

    private TestAdapter_1 adapter_1;


    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);


        LogPrintUtil.setDebug(BuildConfig.DEBUG ? LogPrintUtil.All : LogPrintUtil.None);

        LogPrintUtil.setTag("bear");

        LogPrintUtil.w("start");


//레이아웃 설정.

        setupUI();


    }



    /**

     * UI 생성

     */

    private void setupUI() {

    

        recyclerView = findViewById(R.id.recyclereView);

        adapter_1 = new TestAdapter_1(makeData());

        recyclerView.setAdapter(adapter_1);

    }


    /**

     * 보여줄 데이터 생성.

     */

    private ArrayList<People> makeData() {


        ArrayList<People> list = new ArrayList<>();

        for (int i = 0; i < 40; i++) {

            People p = new People(i + "a", i + "age", i + "address");

            list.add(p);

        }

        return list;

    }

}


/////////////////////////////////////////////////////////////////////////////////////////





리사이클러뷰 기본 예제 끝.

 




안드로이드 레이아웃 동적 구성.



xml 레이아웃을 이용하여 view 등록 


    private void setupUI() {

// 임시 데이터 생성.

ArrayList<String> list = new ArrayList<>();


        for (int i = 0; i < 5; i++) {

            list.add("i data  ==" + i);

        }

        

        // 데이터 만큼 뷰 등록.        

        for (int i = 0; i < list.size(); i++) {

        

            View view = LayoutInflater.from(this).inflate(R.layout.layout_sub, main_Layout, false);

            

            main_Layout.addView(view);


            TextView first = view.findViewById(R.id.first_textview);

            TextView second = view.findViewById(R.id.second_textview);

            TextView third = view.findViewById(R.id.third_textview);


            first.setText("list   :" + list.get(i));


            view.setTag("" + list.get(i));


            view.setOnClickListener(new View.OnClickListener() {

                @Override

                public void onClick(View v) {

                    Log.e("bear", "tag : " + v.getTag());

                }

            });

        }

    }

        

        



////////////////////////////////////////////////////////////////////////////////////////

layout_sub.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="match_parent"

    android:layout_gravity="center"

    android:layout_margin="10dp"

    android:layout_weight="1"

    android:background="#ccc"

    android:gravity="center"

    android:orientation="vertical">


    <LinearLayout

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        android:orientation="horizontal">


        <TextView

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:layout_marginLeft="5dp"

            android:text="1 :" />


        <TextView

            android:id="@+id/first_textview"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:layout_marginLeft="5dp"

            android:text="1" />


    </LinearLayout>


    <LinearLayout

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        android:orientation="horizontal">


        <TextView

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:layout_marginLeft="5dp"

            android:text="2 : " />


        <TextView

            android:id="@+id/second_textview"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:layout_marginLeft="5dp"

            android:text="2" />


    </LinearLayout>



    <LinearLayout

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        android:orientation="horizontal">


        <TextView

            android:layout_width="wrap_content"


            android:layout_height="wrap_content"

            android:layout_marginLeft="5dp"

            android:text="3 : " />


        <TextView

            android:id="@+id/third_textview"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:layout_marginLeft="5dp"

            android:text="3" />



    </LinearLayout>

</LinearLayout>


activity_main.xml

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

<android.support.constraint.ConstraintLayout 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">



    <LinearLayout

        android:id="@+id/main_layout"

        android:layout_width="match_parent"

        android:layout_height="match_parent"

        android:orientation="vertical"

        app:layout_constraintBottom_toBottomOf="parent"

        app:layout_constraintLeft_toLeftOf="parent"

        app:layout_constraintRight_toRightOf="parent"

        app:layout_constraintTop_toTopOf="parent">


    </LinearLayout>


</android.support.constraint.ConstraintLayout>




+ Recent posts