Le_Penseur
[안드로이드 스튜디오] Ch8. 리스트뷰 이벤트처리 (ListView Event Handling 본문
[안드로이드 스튜디오] Ch8. 리스트뷰 이벤트처리 (ListView Event Handling
LePenseur 2019. 8. 25. 15:552019년 8월 25일 (일)
창업의 길로 가기 위한 두번째 걸음, [안드로이드 스튜디오]로 향해보자!
*질적으로 많이 부족한 글입니다. 지적 및 조언 환영합니다.
*이 글에선 "안드로이드 스튜디오"를 줄여서 "안스" 라고 표현합니다. 참고 바랍니다.
우선, 본인은 학원에서 'JAVA' 기초 수업을 선수강했다. 안드로이드 스튜디오를 배우기 위해선 피할 수 없는 언어이기 때문이다.
(물론 Kotlin 도 있지만, 대한민국에선 아직 JAVA의 파워가 어마어마 하다고..)
이번글에서는 저번글에서 배운 이벤트처리를 조금 더 깊게 다가가는 시간을 갖으며, 리스트뷰에 대해서도 알아보고 간다.
<차례>
1. MyCatchEvent
2. ListViewEvent
1. MyCatchEvent
1.1 결과
설명: 결과물은 저번글과 비슷하게 Catch Event 버튼을 클릭하면 빨간색 박스안에 "event" 와 "no event' 가 번갈아 뜬다.
그러나 다른점은, 빨간 박스안에 "Event" 가 뜬 후에 터치(또는 클릭)을 하면서 움직이게 되면 내 손가락(또는 마우스)의 x,y 좌표가 'Result'란에 나오게 된다.
그에 반해 "No Event"상태에서 터치를 할 시에는 Toast형식으로 알림이 "action down!" 이라고 뜨며, 'Result'란에도 "DOWN"이 뜬다.
잘 풀리지 않을때, 밑의 코드를 통해 알아보자.
1.2 코드
1.2.1 activity_main
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Result : "
android:textSize="30dp" />
<Button
android:id="@+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Catch Event!!"
android:textSize="30dp"
android:layout_alignParentBottom="true" />
<TextView
android:id="@+id/textView2"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_centerInParent="true"
android:gravity="center"
android:background="#ff0000"
android:textColor="#000000"
android:textSize="30dp"
/>
</RelativeLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
1.2.2 MainActivity
package com.example.mycatchevent;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
//멤버변수 작업
private Button button;
private TextView textView1,textView2;
private boolean check;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//객체화 작업
textView1 = (TextView)findViewById(R.id.textView1);
textView2 = (TextView)findViewById(R.id.textView2);
button = (Button) findViewById(R.id.button);
//Log.i("check",check + "");
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(check){
textView2.setText("No Event");
// 위에서 논리형 변수 check를 만들었었고, 그걸 이용하는것이다.
// 논리형의 default값은 off다. 따라서 여기 OnClickListener에서 의미하는 바는
// "누르지 않았을때, 또는 반대(-)의 값을 띤다." 는 것이다.
// 그리고 그럴땐 "No Event"(text)라고 뜨도록 설정(set)했다.
// 어디에? 바로 빨간 네모박스(textView2)위에!
}else{
textView2.setText("Event");
// 위와 정확히 반대다. 양(+, on)의 값을 띨때는 "Event"라고 뜨도록 설정했다.
}
check =! check;
// 부정연산자를 이용: 참을 거짓으로, 거짓을 참으로 -> 이 원리를 다시 check에 저장.
// 왜?
}
});
//textView2를 터치할때 이벤트 처리를 할 것 이다.
//그러면 우리는 여기서 OnTouchListener를 사용할 것 이다.
textView2.setOnTouchListener(new View.OnTouchListener() {
//MotionEvent에는 3가지의 상태값이 있다.
//1.Action_DOWN: 손가락을 내린다.
//2.Action_UP: 손가락을 땐다.
//3.Action_MOVE: 손가락을 움직인다.
//MotionEvent의 상태값은 getAction()메소드를 통해서 상태를 구별할 수 있다.
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
String msg = null; //TextView1에 출력될 문자열
int x = 0; //x좌표
int y = 0; //y좌표
switch (motionEvent.getAction()){
case MotionEvent.ACTION_DOWN:
Toast.makeText(MainActivity.this,"Action Down!!!", Toast.LENGTH_SHORT).show();
msg = "Result : DOWN";
break;
case MotionEvent.ACTION_UP:
x = (int) motionEvent.getX();//x축의 좌표를 반환시키는 메소드
y = (int) motionEvent.getY();//y축의 좌표를 반환시키는 메소드
msg = "Result : UP (x : " + x + " , y : " + y + ")";
case MotionEvent.ACTION_MOVE:
x = (int) motionEvent.getX();//x축의 좌표를 반환시키는 메소드
y = (int) motionEvent.getY();//y축의 좌표를 반환시키는 메소드
msg = "Result : UP (x : " + x + " , y : " + y + ")";
break;
}
textView1.setText(msg);
return check;
//반환값이 true이면 "여기서 이벤트 처리가 완료 되었다" 는 뜻.
// 화면 적용을 요구하게 된다.
// false 면 "이벤트 처리가 완료되지 않았다." 라는 걸 뜻한다.
}
});
}
}
2. ListViewEvent
2.1 결과
설명: 결과물의 레이아웃은 간단하다. 위에는 제목, 밑에는 리스트가 들어갈 빈 공간과 함께 리스트를 더해줄 버튼을 추가해주면 된다.
단, 추가되는 리스트들은 이름이 겹치지 않고, 추가되는 순서별로 이름이 정해진다. 1부터 ~00까지.
또 좀더 특징이 있다면, 이번엔 결과물 출력을 위해선 xml파일과 java파일이 각각 한개씩 더 추가가 되어야 한다는 것 이다.
밑의 코드를 보고 이해해보자.
2.2 코드
2.2.1 activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="ListViewEvent"
android:textSize="20dp"
android:gravity="center" />
<ListView
android:id="@+id/myList"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:transcriptMode="alwaysScroll">
<!-- alwaysScroll이 뭐야? 아이템 추가시 Bottom 아이템 위치로 '자동 스크롤'하는 모드
(1) disabled: transcriptMode를 사용하지 않겠다. (디폴트값)
(2) normal: 마지막 아이템이 화면에 표시된 상태에서 데이터 변경을 받은 경우 '자동 스크롤' 하는 모드
(3) notifyDataSetChanged() (데이터 변경 메소드)가 실행된 경우
(4) alwaysScroll: 아이템이 화면에 표시중인 여부와 상관 없이 무조건 스크롤
-->
</ListView>
<Button
android:id="@+id/addBtn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="add"
/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
2.2.2 list_form.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:descendantFocusability="blocksDescendants">
<!-- 리스트의 각 항목들을 구성할 xml파일 입니다.
android:descendantFocusability="blocksDescendants"
: Focuability가 자식의 포커스를 해제하는 기능, 쉽게 생각해서 이쪽에 집중하는 것을 막겠다는 뜻
더 쉽게 말해서, 어플을 처음켰을때 포커스가 제일 나중에 추가된 자식뷰로 가는걸 막는다는 것.
예를 들어 내가 리스트를 100개를 만들었는데, 어플을 킬때마다 첫화면 마지막 리스트 차례인 100으로 포커스가
맞춰지는걸 예방함.
-->
<TextView
android:id="@+id/list_form_txt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="20dp">
</TextView>
</LinearLayout>
2.2.3 MyAdapter.java
package com.example.mylistviewevent;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import org.w3c.dom.Text;
import java.util.ArrayList;
public class MyAdapter extends ArrayAdapter<String>
implements AdapterView.OnItemClickListener {
private Context context;
private ArrayList<String> list;
private ListView myList;
//생성자 (이번엔 받을게 좀 많을거다)
public MyAdapter(Context context, int resource, ArrayList<String> list, ListView myList){
super(context, resource, list);
this.context = context;
this.list = list;
this.myList = myList;
}
//밑의 메소드는 실제 뷰를 만드는 메소드 이다.
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// 인플레이션(xml 레이아웃에 정의된 내용이 메모리에 객체화가 되는 과정)을 해줘야한다.
// 밑이 바로 인플레이션을 하기위한 준비작업이다.
LayoutInflater layoutInflater =
(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
//여기에서 이제 인플레이션이 시작(진행)되는 것 이다.
convertView = layoutInflater.inflate(R.layout.list_form, null);
TextView txt_form = (TextView)convertView.findViewById(R.id.list_form_txt);
String str = list.get(position); // 문자열 값을 빼준다.
txt_form.setText(str);
//원래 같으면 newOnItemClickListener 인데 this를 넣는 이유는 이 클래스 자체가 onclickListener이기 때문이다. 하하!
//그런데 왜 myList안에 '클릭시의 기능' 을 넣어줄까?
//왜냐하면 우리는 텍스트가 아니라 리스트에 신경을 쓰기때문!
myList.setOnItemClickListener(this);
return convertView;
}
//내부클래스를 만드는것이 아니라 이번엔 기존의 것을 상속한다.
//int i : 포지션을 뜻 한다.
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Toast.makeText(context.getApplicationContext(),list.get(i),Toast.LENGTH_LONG).show();
}
}
2.2.3 MainActivity.java
package com.example.mylistviewevent;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Adapter;
import android.widget.Button;
import android.widget.ListView;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
// 멤버변수 생성 (나의 재료)
private Button addBtn;
private ListView myList;
private ArrayList<String> list;
private int cnt = 0;
private MyAdapter adapter = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 객체 생성 (자바는 객체지향 알지?)
addBtn = (Button)findViewById(R.id.addBtn);
myList = (ListView)findViewById(R.id.myList);
list = new ArrayList<String>();
adapter = new MyAdapter(MainActivity.this,R.layout.list_form,list,myList);
//(MainActivity.this (즉, 가장 상위의 view), 아이템으로쓸 레이아웃, 이안에서 실행시킬 리스트, 이녀석이 실행될 뷰)
// setAdapter: Adapter에 연결시키고, 방금 위에 객체화 시킨 adapter를 처리한다.
//아! (괄호안) 은 즉, "처리할 데이터"를 말하는구나!
myList.setAdapter(adapter);
// 자, 이제 버튼을 누르면 어떤 기능이 나오는지 추가하고 마무리해보자.
addBtn.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
//버튼 클릭할때마다 카운트를 증가시키면서 list에 내용을 추가할 것 이다.
cnt++;
list.add("list " + cnt);
if (myList != null) {
adapter.notifyDataSetChanged(); //이걸 써야 list값이 추가 될때 마다 listview를 갱신할수있다.
}
}
});
}
}
'개인(Personal) > 안드로이드 (Andorid Studio)' 카테고리의 다른 글
[안드로이드 스튜디오] Ch10. 버튼 이펙트 & 핵심 수신기(ButtonEffect & KeyListener) (0) | 2019.08.28 |
---|---|
[안드로이드 스튜디오] Ch9. 버튼 클릭 이벤트 처리 & 인플레이터(OnClickListener & Inflater) (0) | 2019.08.27 |
[안드로이드 스튜디오] Ch7. 이벤트 처리(Event Handling) (0) | 2019.08.23 |
[안드로이드 스튜디오] Ch6. 그리드뷰 & 리스트뷰 (GridView & ListView) (1) | 2019.08.22 |
[안드로이드 스튜디오] Ch5. 위젯과 실습 (Widget & Practice) (0) | 2019.08.21 |