안드로이드 5기 2017년 강의 정리 1 (오준석의 생존코딩)
https://www.youtube.com/watch?v=MjtlPTUUL74&list=PLxTmPHxRH3VWSF7kMcsIaTglWUJZpWeQ9&index=1
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki
1일차
2일차 RelativeLayout
3일차 커피앱 코딩
5일차 액티비티끼리 데이터 주고 받기
6일차 암시적 인텐트와 인텐트 필터
7일차 옵션 메뉴
8일차 WebView
9일차 ArrayAdapter, SimpleAdapter
10일차 BaseAdapter
1. 1일차
textSize 는 sp 를 써라 (시스템에서 textSize 변경시 같이 변경됨)
길이는 dp 를 써라.
ImageView 의 scaleType 은 centerCrop 권장
리소스 파일 이름은 숫자로 시작하면 안되고 소문자로만 구성해야한다.
drawable 폴더는 메모리를 더 사용하므로 drawable-hdpi 폴더를 만들어서 사용하라.
# LinearLayout 에서 가중치(weight) 주기가중치를 줄 속성에 0dp 에 준다.
layout_height=”0dp” layout_height=”0dp” layout_height=”0dp” |
2. 2일차
RelativeLayout
글을 오른쪽부터 쓰는 나라를 위해서 Left, Right 가 아니라 Start, End 를 써라.
layout_toLeftOf
layout_above
layout_toRightOf
layout_below
layout_toStartOf
layout_toEndOf
layout_alignParentLeft
layout_alignParentTop
layout_alignParentRight
layout_alignParentBottom
layout_centerHorizontal
layout_centerVertical
layout_centerInParent
layout_alignParentStart
layout_alignParentEnd
layout_alignLeft
layout_alignTop
layout_alignRight
layout_alignBottom
layout_alignBaseline
RelativeLayout (개발자를 위한 레시피)
https://recipes4dev.tistory.com/126
3. 3일차 커피앱 코딩
Live Templates
File – Settings – Editor – Live Templates
ld : Log.d(TAG, “$cursor”); // statement, Reformat according to style
public static final String TAG = MainActivity.class.getSimpleName();
Andorid Logcat 색상 지정
File – Settings – Editor – Color Scheme – Android Logcat
4. 5일차 액티비티끼리 데이터 주고 받기
# 암시적 인텐트를 검색하려면 common intents 를 검색하라.
https://developer.android.com/guide/components/intents-common#java
# 암시적 인텐트를 사용해서 이메일 보내기
public void composeEmail(String[] addresses, String subject) {
Intent intent = new Intent(Intent.ACTION_SENDTO);
intent.setData(Uri.parse("mailto:")); // only email apps should handle this
intent.putExtra(Intent.EXTRA_EMAIL, addresses);
intent.putExtra(Intent.EXTRA_SUBJECT, subject);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}
}
# 암시적 인텐트를 사용해서 전화 걸기
<uses-permission android:name=”android.permission.CALL_PHONE” />
public void dialPhoneNumber(String phoneNumber) {
Intent intent = new Intent(Intent.ACTION_DIAL);
intent.setData(Uri.parse("tel:" + phoneNumber));
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}
}
4. 안드로이드5일차 액티비티끼리 데이터 주고 받기 2
https://developer.android.com/training/basics/intents/result#java
# StartActivityForResultActivity.java
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/java/com/example/myapplication/activities/StartActivityForResultActivity.java
# TargetActivity.java
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/java/com/example/myapplication/activities/TargetActivity.java
4가지 컴포넌트는 AndoridManifest.xml 에 선언되어야 사용할 수 있다.
# 보내는 액티비티
@Override
public void onClick(View v) {
Intent intent = new Intent(this, TargetActivity.class);
intent.putExtra("value", mValueEditText.getText().toString());
// startActivity(intent);
// 주거니 받거니
startActivityForResult(intent, REQUEST_CODE_EXAMPLE);
}
// 받을 때 호출 되는 콜백 메서드
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE_EXAMPLE && resultCode == RESULT_OK && data != null) {
Log.d(TAG, "onActivityResult: " + requestCode);
Log.d(TAG, "onActivityResult: " + resultCode);
Log.d(TAG, "onActivityResult: " + data);
String result = data.getStringExtra("result");
int value = data.getIntExtra("int", -1);
Toast.makeText(this, result + ", int: " + value, Toast.LENGTH_SHORT).show();
} else if (requestCode == REQUEST_CODE_NEW_MEMO) {
} else if (requestCode == REQUEST_CODE_UPDATE_MEMO) {
}
}
# 받는 액티비티
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_target);
if (getIntent() != null) {
String value = getIntent().getStringExtra("value");
mValueTextView.setText(value);
}
}
@Override
public void onClick(View v) {
// 결과 전달
Intent intent = new Intent();
intent.putExtra("result", "이것은 내가 지정한 문구다");
intent.putExtra("int", 50);
setResult(RESULT_OK, intent);
finish();
}
4. 안드로이드5일차 연습문제 풀이
# IntentExamActivity.java
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/java/com/example/myapplication/activities/IntentExamActivity.java
# IntentExamActivity2.java
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/java/com/example/myapplication/activities/IntentExam2Activity.java
public class IntentExamActivity extends AppCompatActivity implements View.OnClickListener {
public static final int REQUEST_CODE = 1000;
private EditText mIdEditText;
private EditText mPasswordEditText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_intent_exam);
mIdEditText = (EditText) findViewById(R.id.id_edit);
mPasswordEditText = (EditText) findViewById(R.id.password_edit);
findViewById(R.id.login_button).setOnClickListener(this);
}
@Override
public void onClick(View v) {
Intent intent = new Intent(this, IntentExam2Activity.class);
intent.putExtra("id", mIdEditText.getText().toString());
intent.putExtra("password", mPasswordEditText.getText().toString());
startActivityForResult(intent, REQUEST_CODE);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE
&& resultCode == RESULT_OK
&& data != null) {
String text = data.getStringExtra("result");
Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
}
}
}
public class IntentExam2Activity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_intent_exam2);
if (getIntent() != null) {
String id = getIntent().getStringExtra("id");
String password = getIntent().getStringExtra("password");
Toast.makeText(this, "id = " + id + ", pw = " + password, Toast.LENGTH_SHORT).show();
}
}
public void onClick(View view) {
String text = ((Button) view).getText().toString();
Intent intent = new Intent();
intent.putExtra("result", text);
setResult(RESULT_OK, intent);
finish();
}
}
5. 6일차 암시적 인텐트와 인텐트 필터
# 공통 인텐트
https://developer.android.com/guide/components/intents-common#java
# ImplicitActivity.java
ActionBar 는 오래전에 나와서 클릭도 안되고 활용성이 없어서 사용을 안한다.
이 후에 활용성이 좋은 Toolbar 가 나왔다.
public class ImplicitActivity extends AppCompatActivity implements View.OnClickListener {
private EditText mPhoneEditText;
private EditText mUrlEditText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_implicit);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
mPhoneEditText = (EditText) findViewById(R.id.phone_edit);
mUrlEditText = (EditText) findViewById(R.id.url_edit);
findViewById(R.id.phone_button).setOnClickListener(this);
findViewById(R.id.url_button).setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.phone_button:
String phoneNumber = mPhoneEditText.getText().toString();
dialPhone(phoneNumber);
break;
case R.id.url_button:
String url = mUrlEditText.getText().toString();
showUrl(url);
break;
}
}
private void showUrl(String url) {
if (!url.startsWith("http://")) {
url = "http://" + url;
}
Uri webpage = Uri.parse(url);
Intent intent = new Intent(Intent.ACTION_VIEW, webpage);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}
}
private void dialPhone(String phoneNumber) {
Intent intent = new Intent(Intent.ACTION_DIAL);
intent.setData(Uri.parse("tel:" + phoneNumber));
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
} else {
Toast.makeText(this, "수행할 앱이 없어요", Toast.LENGTH_SHORT).show();
}
}
}
5. 6일차 로그인 연습문제 풀이
# SignUpExamActivity.java
# SignUpExamTargetActivity.java
public class SignUpExamActivity extends AppCompatActivity implements View.OnClickListener {
public static final int REQUEST_CODE_SIGN_UP = 1000;
private EditText mIdEditText;
private EditText mPassEditText;
private EditText mPass2EditText;
private EditText mEmailEditText;
private RadioGroup mGenderGroup;
private ArrayList<EditText> mEditTextList;
private String mGenger;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sign_up_exam);
mEditTextList = new ArrayList<>();
mIdEditText = (EditText) findViewById(R.id.id_edit);
mPassEditText = (EditText) findViewById(R.id.pass_edit);
mPass2EditText = (EditText) findViewById(R.id.pass2_edit);
mEmailEditText = (EditText) findViewById(R.id.email_edit);
mEditTextList.add(mIdEditText);
mEditTextList.add(mPassEditText);
mEditTextList.add(mPass2EditText);
mEditTextList.add(mEmailEditText);
mGenderGroup = (RadioGroup) findViewById(R.id.gender_group);
mGenderGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
mGenger = ((RadioButton)findViewById(checkedId)).getText().toString();
}
});
findViewById(R.id.reset_button).setOnClickListener(this);
findViewById(R.id.sign_up_button).setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.reset_button:
reset();
break;
case R.id.sign_up_button:
signUp();
break;
}
}
private boolean isValid() {
for (EditText editText : mEditTextList) {
if (TextUtils.isEmpty(editText.getText().toString())) {
return false;
}
}
if (mGenderGroup.getCheckedRadioButtonId() == -1) {
return false;
}
return true;
}
private void signUp() {
if (!isValid()) {
Toast.makeText(this, "모두 입력 해 주셔야 합니다", Toast.LENGTH_SHORT).show();
} else if (!isValidPassword()) {
Toast.makeText(this, "비밀번호가 다릅니다", Toast.LENGTH_SHORT).show();
} else {
// 가입
Intent intent = new Intent(this, SignUpExamTargetActivity.class);
intent.putExtra("id", mIdEditText.getText().toString());
intent.putExtra("pass", mPassEditText.getText().toString());
intent.putExtra("email", mEmailEditText.getText().toString());
intent.putExtra("gender", mGenger);
startActivityForResult(intent, REQUEST_CODE_SIGN_UP);
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE_SIGN_UP &&
resultCode == RESULT_OK) {
Toast.makeText(this, "확인 버튼을 누르셨습니다", Toast.LENGTH_SHORT).show();
}
}
private boolean isValidPassword() {
return mPassEditText.getText().toString().equals(mPass2EditText.getText().toString());
}
private void reset() {
for (EditText editText : mEditTextList) {
editText.setText("");
}
mGenderGroup.clearCheck();
}
}
public class SignUpExamTargetActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sign_up_exam_target);
if (getIntent() != null) {
String id = getIntent().getStringExtra("id");
String pass = getIntent().getStringExtra("pass");
String email = getIntent().getStringExtra("email");
String gender = getIntent().getStringExtra("gender");
String result = String.format("아이디 : %s\n비밀번호 : %s\n이메일 : %s 성별 : %s",
id,
pass,
email,
gender);
TextView resultTextView = (TextView) findViewById(R.id.result_text);
resultTextView.setText(result);
}
findViewById(R.id.ok_button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
setResult(RESULT_OK);
finish();
}
});
}
}
6. 7일차 옵션 메뉴
https://developer.android.com/guide/topics/ui/menus#java
# menu/menu_main.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_setting"
android:icon="@mipmap/ic_launcher"
android:title="설정"
app:showAsAction="always" />
<item
android:id="@+id/action_menu2"
android:title="Item2" />
<item
android:id="@+id/action_menu3"
android:title="Item3" />
</menu>
# MainActivity.java
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_setting:
Toast.makeText(this, "설정 아직 미구현", Toast.LENGTH_SHORT).show();
return true;
case R.id.action_menu2:
sound();
return true;
case R.id.action_menu3:
startChronometer();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
private Chronometer mChronometer; ... // onCreate() 안에 작성.. mChronometer = (Chronometer) findViewById(R.id.timer); mChronometer.setOnChronometerTickListener(new Chronometer.OnChronometerTickListener() { @Override public void onChronometerTick(Chronometer chronometer) { Log.d(TAG, "onChronometerTick: " + chronometer.getText().toString()); sound(); } });
private void startChronometer() {
mChronometer.setBase(SystemClock.elapsedRealtime());
mChronometer.start();
}
private void sound() {
MediaPlayer mediaPlayer = MediaPlayer.create(this, R.raw.monkey);
mediaPlayer.start();
}
7. 8일차 WebView
# WebBrowserActivity.java
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/java/com/example/myapplication/activities/WebBrowserActivity.java
# activity_web_browser.xml
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/res/layout/activity_web_browser.xml
public class WebBrowserActivity extends AppCompatActivity {
private EditText mUrlEditText;
private WebView mWebView;
private Button mSearchButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_web_browser);
mUrlEditText = (EditText) findViewById(R.id.url_edit);
mWebView = (WebView) findViewById(R.id.web_view);
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
// 일반적
// mWebView.setWebViewClient(new WebViewClient());
// 기능 확장
mWebView.setWebViewClient(new WebViewClient() {
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
Toast.makeText(WebBrowserActivity.this, "로딩 완료", Toast.LENGTH_SHORT).show();
}
});
mSearchButton = (Button) findViewById(R.id.search_btn);
mSearchButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mWebView.loadUrl(mUrlEditText.getText().toString());
}
});
// 키보드 이벤트 검출
mUrlEditText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
// 버튼을 코드로 누르기
mSearchButton.callOnClick();
// 키보드 내리기
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(mUrlEditText.getWindowToken(), 0);
}
return true;
}
});
}
// 뒤로 가기 키 캐치
@Override
public void onBackPressed() {
if (mWebView.canGoBack()) {
mWebView.goBack();
} else {
super.onBackPressed();
}
}
}
– 9일차 ArrayAdapter, SimpleAdapter
# ListViewActivity.java
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/java/com/example/myapplication/ListViewActivity.java
# activity_list_view.xml
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/res/layout/activity_list_view.xml
# ArrayAdapter, SimpleAdapter (구글 검색)
# ArrayAdapter
ArrayList<String> mDataList = new ArrayList<>();
for (int i = 0; i < 50; i++) {
mDataList.add("item " + i);
}
ArrayAdapter<String> adapter =
new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mDataList);
ListView listView = findViewById(R.id.listview);
listView.setAdapter(adapter);
listView.setOnItemClickListener((parent, view, position, id) -> {
String selected_item = (String)parent.getItemAtPosition(position);
mDataList.remove(selected_item);
adapter.notifyDataSetChanged();
});
# SimpleAdapter
ListView listView = findViewById(R.id.listview);
ArrayList<HashMap<String, String>> dataList = new ArrayList<>();
HashMap<String, String> mapData = new HashMap<>();
mapData.put("name", "홍길동");
mapData.put("city", "광주광역시");
dataList.add(mapData);
mapData = new HashMap<String, String>();
mapData.put("name", "임꺽정");
mapData.put("city", "서울특별시");
dataList.add(mapData);
mapData = new HashMap<String, String>();
mapData.put("name", "김두한");
mapData.put("city", "대전광역시");
dataList.add(mapData);
SimpleAdapter adapter = new SimpleAdapter(this, dataList,
android.R.layout.simple_list_item_2,
new String[] {"name", "city"},
new int[] {android.R.id.text1, android.R.id.text2});
listView.setAdapter(adapter);
# ArrayList, ArrayAdapter와 ListView – 1. 기본적인 사용 방법
https://webnautes.tistory.com/1190
# Using an ArrayAdapter with ListView
https://guides.codepath.com/android/Using-an-ArrayAdapter-with-ListView
# [Android] ListView와 SimpleAdapter
https://m.blog.naver.com/draming/20158837275
# Custom SimpleAdapter Tutorial With Example In Android Studio
https://abhiandroid.com/ui/custom-simpleadapter.html
8. 10일차 BaseAdapter
# WeatherActivity.java
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/java/com/example/myapplication/activities/WeatherActivity.java
# adapters/WeatherAdapter.java
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/java/com/example/myapplication/adapters/WeatherAdapter.java
# models/Weather.java
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/java/com/example/myapplication/models/Weather.java
# item_weather.xml
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/res/layout/item_weather.xml
# activity_weather.xml
https://github.com/suwonsmartapp/MyFirstAndroidApp5ki/blob/master/app/src/main/res/layout/activity_weather.xml
# 사진 파일은 drawable-hdpi 폴더에 넣어라. drawable 폴더에 넣으면 메모리를 더 많이 차지한다.
# 뷰홀더 사용 이유
listview 는 뷰를 재사용한다.
뷰를 재사용할 때마다 findViewById 를 하게되면 효율성이 떨어지므로 뷰홀더를 사용한다.
# AdapterView 는 ListView, GridView, Spinner 세 개를 주로 사용한다.
# item_weather.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="8dp">
<ImageView
android:id="@+id/weather_image"
android:layout_width="100dp"
android:layout_height="100dp"
android:scaleType="centerCrop"
android:src="@mipmap/ic_launcher" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/location_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="지역"
android:textSize="36sp" />
<TextView
android:id="@+id/temperature_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:text="기온"
android:textSize="24sp" />
</LinearLayout>
</LinearLayout>
# activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_weather"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Spinner
android:id="@+id/spinner"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<ListView
android:id="@+id/list_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<GridView
android:id="@+id/grid_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:numColumns="3" />
</LinearLayout>
# models/Weather.java
public class Weather {
private int imageRes;
private String weather;
private String country;
private String temperature;
public Weather(int imageRes, String country, String temperature) {
this.imageRes = imageRes;
this.country = country;
this.temperature = temperature;
}
public int getImageRes() {
return imageRes;
}
public void setImageRes(int imageRes) {
this.imageRes = imageRes;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getTemperature() {
return temperature;
}
public void setTemperature(String temperature) {
this.temperature = temperature;
}
public String getWeather() {
return weather;
}
public void setWeather(String weather) {
this.weather = weather;
}
@Override
public String toString() {
final StringBuffer sb = new StringBuffer("Weather{");
sb.append("country='").append(country).append('\'');
sb.append(", imageRes=").append(imageRes);
sb.append(", weather='").append(weather).append('\'');
sb.append(", temperature='").append(temperature).append('\'');
sb.append('}');
return sb.toString();
}
}
# adapters/WeatherAdapter.java
public class WeatherAdapter extends BaseAdapter {
private static final String TAG = WeatherAdapter.class.getSimpleName();
private Context mContext;
private List<Weather> mData;
public WeatherAdapter(Context context, List<Weather> data) {
mContext = context;
mData = data;
}
// 아이템 갯수
@Override
public int getCount() {
return mData.size();
}
// position번째 아이템
@Override
public Object getItem(int position) {
return mData.get(position);
}
// postion번째 id
@Override
public long getItemId(int position) {
return position;
}
// position번째의 레이아웃
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
// convertView : 재사용 되는 뷰
if (convertView == null) {
viewHolder = new ViewHolder();
// 뷰를 새로 만들 때
convertView = LayoutInflater.from(mContext)
.inflate(R.layout.item_weather, parent, false);
// 레이아웃 들고 오기
ImageView imageView = convertView.findViewById(R.id.weather_image);
TextView locationTextView = convertView.findViewById(R.id.location_text);
TextView temperatureTextView = convertView.findViewById(R.id.temperature_text);
// 뷰 홀더에 넣는다
viewHolder.weatherImage = imageView;
viewHolder.locationTextView = locationTextView;
viewHolder.temperatureTextView = temperatureTextView;
convertView.setTag(viewHolder);
} else {
// 재사용 할 때
viewHolder = (ViewHolder) convertView.getTag();
}
Log.d(TAG, "getView: " + position);
// 데이터
Weather weather = mData.get(position);
// 화면에 뿌리기
viewHolder.weatherImage.setImageResource(weather.getImageRes());
viewHolder.locationTextView.setText(weather.getCountry());
viewHolder.temperatureTextView.setText(weather.getTemperature());
// 홀수 줄은 빨간 색
if (position % 2 == 1) {
convertView.setBackgroundColor(Color.RED);
} else {
convertView.setBackgroundColor(Color.WHITE);
}
// 클릭 된 아이템이면 노란색
if (mSeletedPosition == position) {
convertView.setBackgroundColor(Color.YELLOW);
}
return convertView;
}
// -1이면 선택된게 없다
private int mSeletedPosition = -1;
public void setSelect(int position) {
mSeletedPosition = position;
}
// findViewById로 가져온 View 들을 보관
private static class ViewHolder {
ImageView weatherImage;
TextView locationTextView;
TextView temperatureTextView;
}
}
# MainActivity.java
public class MainActivity extends AppCompatActivity implements AdapterView.OnItemClickListener, AdapterView.OnItemLongClickListener {
private ListView mListView;
private GridView mGridView;
private Spinner mSpinner;
private WeatherAdapter mAdapter;
private List<Weather> mWeatherList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mListView = findViewById(R.id.list_view);
mGridView = findViewById(R.id.grid_view);
mSpinner = findViewById(R.id.spinner);
// 날씨 데이터
mWeatherList = new ArrayList<>();
mWeatherList.add(new Weather(R.drawable.sunny, "수원", "27도"));
mWeatherList.add(new Weather(R.drawable.blizzard, "안양", "23도"));
mWeatherList.add(new Weather(R.drawable.cloudy, "안산", "24도"));
mWeatherList.add(new Weather(R.drawable.rainy, "평택", "22도"));
mWeatherList.add(new Weather(R.drawable.snow, "서울", "26도"));
mWeatherList.add(new Weather(R.drawable.sunny, "부산", "21도"));
mWeatherList.add(new Weather(R.drawable.sunny, "도쿄", "10도"));
mWeatherList.add(new Weather(R.drawable.sunny, "워싱턴", "5도"));
mWeatherList.add(new Weather(R.drawable.snow, "평양", "6도"));
mWeatherList.add(new Weather(R.drawable.snow, "베이징", "12도"));
mWeatherList.add(new Weather(R.drawable.rainy, "수원", "49도"));
mWeatherList.add(new Weather(R.drawable.rainy, "수원", "27도"));
mWeatherList.add(new Weather(R.drawable.blizzard, "수원", "27도"));
mWeatherList.add(new Weather(R.drawable.blizzard, "수원", "27도"));
mWeatherList.add(new Weather(R.drawable.sunny, "수원", "27도"));
mWeatherList.add(new Weather(R.drawable.sunny, "수원", "27도"));
mWeatherList.add(new Weather(R.drawable.sunny, "수원", "27도"));
mWeatherList.add(new Weather(R.drawable.sunny, "수원", "27도"));
// 어댑터
mAdapter = new WeatherAdapter(this, mWeatherList);
// 어댑터를 뷰에 설정
mListView.setAdapter(mAdapter);
mGridView.setAdapter(mAdapter);
mSpinner.setAdapter(mAdapter);
// 이벤트
mListView.setOnItemClickListener(this);
mListView.setOnItemLongClickListener(this);
mGridView.setOnItemClickListener(this);
mGridView.setOnItemLongClickListener(this);
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
mAdapter.setSelect(position);
// 데이터가 변경됨을 알려줌 = 다시 그려라
mAdapter.notifyDataSetChanged();
}
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
// 롱 클릭시 해당 아이템 삭제
mWeatherList.remove(position);
// 어댑터에 변경을 통지 = 다시 그려라
mAdapter.notifyDataSetChanged();
return true;
}
}