**Toast
=>짧은 문자열을 출력하는 작은 대화상자
=> 안드로이드 시스템이 제공 : 앱이 종료되도 출력 가능
=> 플로팅(화면에 떠있는 상태) 형태로 화면 하단에 나타났다가 일정 시간이 지나면 자동으로 사라짐
=> 알림 사항을 전달만 하고 포커스를 받을 수가 없음
1. 생성
Toast.makeText(Context context, int resid, int duration)
Toast.makeText(Context context, CharSequence text, int duration)
=> Context는 Toast는 화면에 출력되는 요소이기 때문에 화면 출력정보를 소유한 Context를 매개변수로 받아야 함
- Context는 화면에 무엇인가를 출력할 때 사용하기 위한 선, 면, 글자, 배경 색상등의 정보를 소유한 객체
- 안드로이드에서는 직접 Context를 생성하는 경우는 거의 없고 Context를 상속 받은 Activity를 이용하여 화면 출력을 함
- Activity에 대한 참조를 얻는 방법은 Activity 클래스 안에서는 this나 Activity.this를 이용
- 이벤트 처리시 anonymous class를 자주 사용, anonymous class는 Activity.this를 이용하여 Activity클래스 객체에 대한 참조 가능
public class SampleActivity{
public void onCreate(){
//this나 SampleActivity/this나 모두 현재 인스턴스에 대한 참조
btn.setOnClickListener(new View.OnClickListener(){
//this는 View.OnClickListener의 인스턴스에 대한 참조
//SampleActivity.this가 SampleActivity의 인스턴스에 대한 참조
});
}
}
=> 안드로이드에서는 getApplicationContext()라는 메소드를 호출하면 시작 Activity에 대한 포인터를 리턴받을수 있음
=> 두번째 매개변수는 출력할 메시지로 string.xml파일에 리소스로 등록하고 그 리소드 id를 설정해도 되고 직접 문자열로 설정해도 됨
- 안드로이드는 String도 많이 사용하지만 String의 상위 인터페이스 문자열 리턴시 리턴문자열의 자료형을 정확하게 파악하여
CharSequence나 Editable이면 toString()을 호출하여 문자열로 변환하여 사용
=> 세번째 매개변수는 토스트를 출력할 시간인데 1/1000초 단위로 설정가능(대부분 Toast.SHORT, Toast.LONG등의 상수 사용)
2. 출력
=> Show()를 호출
3. 기타 메소드
=> setGravity
=> setMargin
=> setText
=> setDuration
=> cancel
=> setView(View view) : View를 설정 - 모양 변경
4. 실습
=> 버튼을 누르면 토스트가 출력되도록 하기
1) 프로젝트를 생성하거나 실행 가능한 Activity를 추가
2) 레이아웃에 버튼을 1개 추가
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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"
android:orientation="vertical"
tools:context=".MainActivity">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="토스트 출력"
android:id="@+id/btnToast"/>
</LinearLayout>
3) Activity.java 파일의 onCreate 메소드 수정
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//xml애 디자인한 뷰 객체 찾아오기
Button btn = (Button)findViewById(R.id.btnToast);
//버튼 클릭시 이벤트
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//토스트 만들기
Toast toast = Toast.makeText(MainActivity.this, "토스트를 출력합니다", Toast.LENGTH_LONG);
//토스트를 화면에 출력
toast.show();
}
});
}
**Snackbar
=> 하단에 고정된 위치에 메시지를 출력해주는 UI
=> 초창기 안드로이드 버전에 없었고 나중에 추가 됨(라이브러리를 추가하여 사용해야 함)
1. 안드로이드에서 추가된 라이브러리 사용
=> 안드로이드는 버전이 업데이트 될때 새로운 UI를 추가하는 경우가 많아 이런 UI사용시 사용
1) File - Project Structure메뉴를 실행
2) 왼쪽 창에서 Modules 하단의 app을 선택
3) 오른쪽 탭에서 dependencies를 선택하고 + 버튼을 눌러 필요한 라이브러리 추가
=> Snackbar는 support.design 라이브러리를 추가하여 사용
2. Snackbar
=> Snackbar는 Action을 통해서 onClick을 설정할 수 있음
- 사용자와의 인터페이스로 이용가능
=> Toast는 Context를 매개변수로 받지만 Snackbar는 View를 매개변수로 받음
1) 생성
- Snackbar.make(View view, CharSequence text, int duration)
- Snackbar.make(View view, int residents, int duration)
2) 출력
- show()
3) 클릭했을 때 동작 지정
setAction(String msg, new View.onClickListener(){
public void onClick(View view){
//클릭시 수행할 내용
});
3. 버튼 클릭시 Snackbar 출력하기
1) support.design 라이브러리를 추가
=>[File] - [ProjectStructure]를 실행
2) dependecies나 module을 선택하고, dependency위의 +버튼을 눌러서 design검색후 support.design을 추가
3) Activity.java 클래스의 onCreate 메소드에서 버튼의 클릭 처리 메소드의 내용을 수정 - 음악재생을 할려면 res 디렉토리에 raw 디렉토리를 만들고 그 안에 space.mp3 파일을 저장하고 해야 됩니다.
//버튼 클릭했을 때 처리
btn.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view){
/*
//토스트 만들기
Toast toast = Toast.makeText(
MainActivity.this,
"토스트를 출력합니다.",
Toast.LENGTH_LONG);
//토스트를 화면에 출력
toast.show();
*/
//스낵바 출
Snackbar.make(view, "스낵바 출력",
Snackbar.LENGTH_LONG)
.setAction("SONG",
new View.OnClickListener(){
public void onClick(View view){
MediaPlayer player =
MediaPlayer.create(
MainActivity.this,
R.raw.spice);
player.start();
}
})
.show();
}
});
**대화상자 - Dialog
=> 사용자에게 전달 사항을 알리고 사용자의 선택을 받아들이는 통신 수단 중의 하나
=> Activity를 화면에 그대로 유지한 채 중앙에 열리므로 메시지를 보여주거나 추가 입력, 선택용으로 사용하기에 적합
1. 생성 및 출력
1) Dialog생성
=> 생성자에 Context를 대입 받아서 생성
2) 모양 설정
- setContextView(View view)로 출력되는 모양 설정
- setTitle(문자열)을 이용해서 제목을 설정
3) 출력
- show()
2. 일반 다이얼로그 출력
1) 사용가능한 Activity 추가
2) 레이아웃 수정
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="대화상자 출력"
android:id="@+id/dlgshow"/>
3) Activity.java 파일의 onCreate 메소드 수정
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dialog_project);
Button dlgshow = (Button)findViewById(R.id.dlgshow);
dlgshow.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
Dialog dlg = new Dialog(DialogProject.this);
//대화 상자 생성
TextView textView = new TextView(DialogProject.this);
textView.setText("대화상자 출력");
//모양 설정
dlg.setContentView(textView);
dlg.setTitle("대화상자");
//출력
dlg.show();
}
});
}
3. AlertDialog
=> Dialog 클래스는 화면 모든 영역을 직접 디자인, AlertDialog는 문자열 메시지, 타이틀바, 아이콘 영역을 미리 만들어두고 사용자가 선
택하여 설정시 생성할 수 있도록 만든 Dialog의 고수준 매핑클래스
=> 생성자는 portected로 되어 있어 직접 호출하지 못하고 Builder를 통해서 생성
=> 설정과 관련된 메소드들은 다시AlertDialog를 리턴하기 때문에 메소드를 연속해서 호출하는 형태로 디자인
- AlertDialog.Builder setMessage(CharSequence message)
- AlertDialog.Builder setTitle(CharSequence title)
- AlertDialog.Builder setIcon(int iconId)
- 이와 유사한 형태의 클래스로는 String이 있음
=> 출력은 Show() 메소드를 이용
=> 어떤 클래스 디자인시, 생성부가 복잡하면 생성자를 private, protect로 숨기고 별도 메소드를 이용하여 생성하도록 만들어 주어야 함
=> 이러한 디자인 패턴을 팩토리 메소드 패턴이라고 함
=> 한 클래스에 설정해야할 내용이 많은 경우 하나의 메소드에서 전부 설정시, 메소드의 모양이 너무 복잡 or 오버로딩 증가 or 별도 클
래스를 만들어야 하는 일이 발생
- 위 경우 Map을 이용해서 설정하는 경우가 있는데 바람직하지 않음
- Map 은 리턴 타입으로 사용하는 것이 좋음
1) 레이아웃에 버튼을 추가
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="AlertDialog"
android:id="@+id/alertdlgshow"/>
2) Activity.java 클래스의 onCreate 메소드에 버튼의 클릭이벤트를 작성하여 AlertDialog를 출력
Button alertdlgshow = (Button)findViewById(R.id.alertdlgshow);
alertdlgshow.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
AlertDialog.Builder dlg = new AlertDialog.Builder(DialogProject.this);
//메소드 체이닝(연쇄적으로 메소드 호출 - 메소드 수행 종료후 호출하므로 메모리 소모가 증가되지 않음)
dlg.setTitle("제목")
.setMessage("내용")
.setIcon(android.R.drawable.ic_dialog_alert)
.show();
}
});
=> 연속적으로 메소드를 호출하는 것을 Method Chaining이라고 함
- 메소드 체이닝을 제작하는 경우 : 작업을 수행시, 설정 할 내용이 많고, 내용이 선택적인 경우
-> 초기 설정시, 순서, 종류들을 전부 기억해야 하므로 체이닝 형태로 설정할 수 있도록 만들어 줌
=> 대화상자에 버튼 배치
- 대화상자에는 사용자의 선택을 알수 있도록 버튼 추가 가능
- AlertDialog에는 버튼을 추가할 수 있는 메소드가 3가지 있는데, 이름만 다르고 사용방법은 모두 동일
- 코딩의 의미를 전달하기 위해 메소드명을 다르게 제작
- setPositiveButton(CharSequence text, DialogInterface.OnClickListener listener)
- setNeutralButton(CharSequence text, DialogInterface.OnClickListener listener)
- setNegativeButton(CharSequence text, DialogInterface.OnClickListener listener)
- 여기서 만들어지는 버튼들은 기본적으로 대화상자를 닫는 기능을 가짐
=> 안드로이드는 Back Button을 가지고 있어 BackButton 제작시 대화상자가 닫힘
- setCancelable(booldean cancelable)을 호출하여 false 대입시 BackButton을 눌러도 대화상자 유지
4. 화면 출력 처리 방식
1) 1초에 1씩 증가하며 텍스트뷰에 숫자를 출력
=> 실행가능한 Activity 생성
=> 레이아웃에 텍스트뷰 1개, 버튼 1개를 배치
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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"
android:orientation="vertical"
tools:context=".DisplayActivity">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="value"
android:id="@+id/tvDisplay"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="대화상자 출력"
android:id="@+id/btn"/>
</LinearLayout>
2) Activity.java 클래스에 작업을 위한 코드를 작성
public class DisplayActivity extends AppCompatActivity {
String msg = "기본";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_display);
final TextView display = (TextView)findViewById(R.id.tvDisplay);
// try{
// //1초마다 출력될 것처럼 보이나 실제로는 보아서 출력하므로 "10"만 보임
// for(int i=1; i<=10; i+=1){
// Thread.sleep(1000);
// display.setText("i=" + i);
// }
// }catch (Exception e){
//
// }
Button btn = (Button)findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
AlertDialog.Builder dlg = new AlertDialog.Builder(DisplayActivity.this);
dlg.setTitle("대화상자 콜백")
.setMessage("대화상자는 어떻게 동작?")
.setPositiveButton("확인", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
msg = "확인";
try{
for(int j=0; j<10; j+=1){
Thread.sleep(1000);
Log.e("j", j+"");
}
}catch (Exception e){}
}
})
.setNegativeButton("취소", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
msg = "취소";
}
})
.show();
//대화상자가 출력됨과 동시에 수행
//대화상자가 닫히고 난 후 수행하는 코드를 만들려면 대화상자의 콜백 메서드를 사용하야 함
display.setText(msg);
}
});
}
}
**GUI 프로그래밍에서의 화면 출력
=> 하나의 메소드 안에 화면 출력하는 코드와 그렇지 않은 코드가 같이 존재하면 화면 출력하는 코드는 오랜시간이 걸리므로 나중에 처리
- 화면 출력 이후 작업을 수행하려는 경우 화면 출력 종료후 수행하기 위해 콜백 메소드에 작성해주어야 함
=> CallBack Mathod: 이벤트 발생시 호출되는 메소드
=> 스레드를 이용하지 않고 주기적으로 화면갱신 수행시 모아서 한꺼번에 처리
- 화면 갱신은 작업시간이 오래걸려 한꺼번에 처리
- GUI 프로그래밍 시 스레드를 만드는 것을 할 수 있어야 하고, main 스레드와 다른 스레드를 구분할 수 있어야 함
- main 스레드에서만 화면 갱신 가능하므로 main 스레드에게 수행할 내용을 전달하는 방식을 반드시 알아야 함
**목록 선택 대화상자
=> AlertDialog는 버튼을 배치하는 메소드를 3개 가지고 있음
- Positive, Neutral, Negative
- 하나의 메소드를 2번 이상 호출하면 마지막에 호출한 것 하나만 유효
- 이러한 이유로 버튼은 3개까지만 배치가 가능
=> 4개 이상의 목록에서 선택하는 대화상자를 만들고자 할 경우 목록 선택 대화상자를 만들어야 함
- 이때는 setItems(CharSequence[] items 또는 int itemsId, DialogInterface.OnClickListener listener)를 호출 해야 함
=> 문자열 배열을 리소스로 만들 때는 values 디렉토리에 arrays.xml 파일에 만들면 됨
=> listener의 onClick 메소드의 2번째 매개변수가 선택한 아이템의 인덱스
=> setItems 대신에 setSingleChoiceItems를 호출하면 목록 옆에 라디오 버튼이 생생되어 하나만 선택할 수 있게 해줌
- 이 메소드는 문자열 배열, 리소스 아이디, ListAdapter, Cursor를 매개변수로 받을 수 있음
=> setMultiChoiceItems 메소드를 호출하면 다중 선택이 가능한 목록 대화상자를 만들 수 있음
- 이 메소드는 Boolean 배열을 매개변수로 받아 선택한 목록들의 인덱스에 해당하는 데이터만 true로 설정
**ProgressDialog
=> 진행상황을 표시해주는 다이얼로그
=> setProgressStyle이라는 메소드를 이용해서 막대모양이나 원 모양의 진행율을 표시할 수 있음
**Date or TimePickerDialog
=> DatePickerDialog : 날짜를 선택할 수 있는 대화상자
=> TimePickerDialog : 시간을 선택할 수 있는 대화상자
=> 스마트 폰은 초단위 설정이 안됨
**Custom Dialog
=> 사용자가 디자인한 뷰를 출력하는 다이얼로그
=> 뷰는 자바코드로 직전 생성해서 설정해도 되지만 layout.xml 파일로 만들어서 작성한 후 전개하여 사용 가능
- 전개 : layout.xml파일로 만든 것을 View 클래스의 객체로 변환하는 작업
1. 로그인 다이얼로그를 만들어서 출력하고 입력한 내용을 확인하는 예제
1) 실행가능한 Activity를 추가(LoginActivity)
2) Activity_login.xml 파일 수정
=> TextView 1개와 대화상자를 출력할 버튼 1개를 추가
=> 실제 작업이라면 로그인을 할 수 있도록 할
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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"
android:orientation="vertical"
tools:context=".LoginActivity">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="\결과"
android:id="@+id/result"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="로그인"
android:id="@+id/login"/>
</LinearLayout>
3) res/layout 디렉토리에 로그인 화면으로 사용할 layout파일을 추가하고 작성
=> login.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:orientation="vertical"
android:padding="5dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="아이디"
android:textSize="20dp"
android:textAlignment="center"
android:layout_marginBottom="30dp"/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/editID"
android:textAlignment="center"
android:hint="ID 입력"/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/editPW"
android:hint="PassWord 입력"
android:textAlignment="center"/>
</LinearLayout>
4) LoginActivity.java 파일에 인스턴스 변수를 선언
=> 버튼과 텍스트 뷰 변수
//화면에 보여지는 버튼과 텍스트 뷰에 대한 변수
Button loginbtn;
TextView result;
5) LoginActivity.java 파일의 onCreate 메소드에 작업 내용을 작성
public class LoginActivity extends AppCompatActivity {
//화면에 보여지는 버튼과 텍스트 뷰에 대한 변
Button loginbtn;
TextView result;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
//뷰 찾아오기
result = (TextView)findViewById(R.id.result);
loginbtn = (Button)findViewById(R.id.login);
//버튼을 눌렀을 때 처리
loginbtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//layout 파일에 만든 뷰를 전개
final LinearLayout linear = (LinearLayout)View.inflate(LoginActivity.this, R.layout.login, null);
//디자인한 뷰를 출력하는 대화상자
new AlertDialog.Builder(LoginActivity.this)
.setTitle("로그인")
.setView(linear)
.setCancelable(false)
.setNegativeButton("취소", null)
.setPositiveButton("확인", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
//anonymous class나 lambda식에서는 자신이 속한 메소드의 지역변수 사용 불가
//사용하고자 하는 변수가 있으면 이 변수를 인스턴스 변수로 만들거나 final 변수로 만들어야 함
//layout파일에 만든 뷰를 전개하
//뷰의 참조를 가져올 경우 부모뷰에서 호출해야 함
//id를 입력하는 EditText는 linear안에 있으므로 linear가 호출해야 함
EditText id = (EditText) linear.findViewById(R.id.editID);
EditText password = (EditText)linear.findViewById(R.id.editPW);
//입력한 내용을 가지고 로그인 시도를 함
//EditText나 TextView에서 가져온 문자열은 자료형이 String이 아니므로 ToString()을 호출하여 문자열로 변환
result.setText("아이디 : " + id.getText().toString() + " 비밀번호 : " + password.getText().toString());
}
})
.show();
}
});
}
}
**EventHandling
=> Event : 시스템 또는 사용자가 발생시키는 사건
- 시스템이 발생시키는 사건(Notification)은 사용자에게 주는 알림의 성격이 강하기 때문에 별도로 부르기도 함
=> EventHandler : Event가 발생하면 호출되는 객체 또는 함수
1. Event 처리 방식
1) Hierachy Event Model : 클래스에 만들어져 있는 메소드를 재정의 하는 구조
=> 상속받은 클래스에서만 사용 가능
=> 이형태의 이벤트 처리 메소드는 이벤트가 발생한 객체를 매개변수로 갖지 않음
- 이 메소드가 구현된 클래스의 객체가 이벤트가 발생한 곳이므로 this이면 이벤트가 발생한 객체
=> 이벤트에 대한 정보를 가지고 있는 객체만 매개변수로 만들어짐
2) Delegation Model : 이벤트를 처리할 객체나 메소드를 지정하는 구조
=> 상속과 상관없이 자신이 처리할 수도 있고 다른 객체에게 위임할 수도 있음
=> 이렇게 이벤트 처리를 위임받은 객체를 Listener라고 함
3) VC#, MFC, Java의 Swing, Java F/X, iOS, MacOSX등의 모든 GUI프로그래밍 에서 동일
- 첫번째 매개변수가 이벤트가 발생한 객체냐, 아니면 이벤트가 발생한 객체에 대한 정보를 가진 객체냐의 차이
**Hierarchy Event Model
=> 상위 클래스가 가진 이벤트 처리 메소드를 재정의 하는 방식
=> View와 Activity 클래스에는 기본적인 이벤트 처리를 위한 메소드가 내장
- boolean onTouchEvent(MotionEvent event) : 터치했을 때 호출되는 메소드
- boolean keyDown(int keyCode, KeyEvent event) : 키보드 눌렀을 때
- boolean keyUp(int keyCode, KeyEvent event) : 키보드에서 뗏을 때
- boolean keyLongPress(int keyCode, KeyEvent event) : 길게 눌렀을 때
- void onBackPressed() : back버튼 눌렀을 때
- boolean onTrackballEvent(MotionEvent event) : 트랙볼 이벤트
=> boolean을 리턴하는 메소드들은 이벤트 발생시 시스템이 무엇인가를 수행하는 이벤트
- 리턴하는 값이 true이면 시스템이 가진 처리를 하는 것, false이면 처리하지 않는 것
Tip!
1. 제너릭
=> 같은 알고리즘이라면 public void swap(int a, int b) -> public void swap<int>(T a, T b) 가 편리
- 여러 메소드를 작성할 필요가 없음
'수업 정리' 카테고리의 다른 글
73일차 수업 정리(Android - 파일 입출력, SQLite) (0) | 2020.07.20 |
---|---|
72일차 수업정리(Android - Timer, Animation, LandScope) (0) | 2020.07.17 |
70일차 수업정리(Android Layout) (0) | 2020.07.15 |
69일차 수업정리(Lambda, Android Interface) (0) | 2020.07.14 |
68일차 수업 정리(Android 구조 및 화면 출력) (0) | 2020.07.13 |