package net.yanzm.profileapplication; | |
import android.animation.Animator; | |
import android.animation.AnimatorListenerAdapter; | |
import android.animation.AnimatorSet; | |
import android.animation.ObjectAnimator; | |
import android.app.Activity; | |
import android.app.AlertDialog; | |
import android.content.DialogInterface; | |
import android.content.Intent; | |
import android.graphics.Bitmap; | |
import android.net.Uri; | |
import android.os.AsyncTask; | |
import android.os.Bundle; | |
import android.provider.MediaStore; | |
import android.support.annotation.IntDef; | |
import android.support.annotation.NonNull; | |
import android.text.TextUtils; | |
import android.util.Log; | |
import android.view.LayoutInflater; | |
import android.view.MenuItem; | |
import android.view.View; | |
import android.widget.Button; | |
import android.widget.EditText; | |
import android.widget.ImageView; | |
import android.widget.LinearLayout; | |
import android.widget.RadioGroup; | |
import android.widget.Spinner; | |
import android.widget.TextView; | |
import android.widget.Toast; | |
import com.squareup.picasso.Picasso; | |
import java.lang.annotation.Retention; | |
import java.lang.annotation.RetentionPolicy; | |
import java.util.ArrayList; | |
import java.util.List; | |
import java.util.Random; | |
public class MainActivity extends Activity { | |
private static final int REQUEST_CODE_PICK_IMAGE = 1; | |
private ImageView thumbnailView; | |
private EditText nameEditText; | |
private EditText bioEditText; | |
private Spinner experienceSpinner; | |
private RadioGroup eventGroup; | |
private LinearLayout dessertContainer; | |
private Button sendButton; | |
private View progressView; | |
private View profileContainer; | |
@Override | |
protected void onCreate(Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
setContentView(R.layout.activity_main); | |
assert getActionBar() != null; | |
getActionBar().setDisplayHomeAsUpEnabled(true); | |
// ビューの設定 | |
progressView = findViewById(R.id.progress); | |
profileContainer = findViewById(R.id.profile_container); | |
thumbnailView = (ImageView) findViewById(R.id.thumbnail); | |
thumbnailView.setOnClickListener(new View.OnClickListener() { | |
@Override | |
public void onClick(View v) { | |
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); | |
intent.addCategory(Intent.CATEGORY_OPENABLE); | |
intent.setType("image/*"); | |
startActivityForResult(intent, REQUEST_CODE_PICK_IMAGE); | |
} | |
}); | |
nameEditText = (EditText) findViewById(R.id.name); | |
experienceSpinner = (Spinner) findViewById(R.id.experience); | |
bioEditText = (EditText) findViewById(R.id.bio); | |
eventGroup = (RadioGroup) findViewById(R.id.event); | |
dessertContainer = (LinearLayout) findViewById(R.id.dessert_container); | |
findViewById(R.id.add_dessert_button).setOnClickListener(new View.OnClickListener() { | |
@Override | |
public void onClick(View v) { | |
final String[] desserts = getResources().getStringArray(R.array.desserts); | |
new AlertDialog.Builder(MainActivity.this) | |
.setItems(desserts, new DialogInterface.OnClickListener() { | |
@Override | |
public void onClick(DialogInterface dialog, int which) { | |
String item = desserts[which]; | |
final int childCount = dessertContainer.getChildCount(); | |
for (int i = 0; i < childCount; i++) { | |
final View child = dessertContainer.getChildAt(i); | |
String dessert = ((TextView) child).getText().toString(); | |
if (dessert.equals(item)) { | |
Toast.makeText(MainActivity.this, "すでに選択されています", Toast.LENGTH_SHORT).show(); | |
return; | |
} | |
} | |
final TextView tv = (TextView) getLayoutInflater() | |
.inflate(R.layout.dessert_item, dessertContainer, false); | |
tv.setText(desserts[which]); | |
tv.setOnClickListener(new View.OnClickListener() { | |
@Override | |
public void onClick(View v) { | |
new AlertDialog.Builder(MainActivity.this) | |
.setMessage("削除しますか?") | |
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { | |
@Override | |
public void onClick(DialogInterface dialog, int which) { | |
dessertContainer.removeView(tv); | |
} | |
}) | |
.setNegativeButton(android.R.string.cancel, null) | |
.show(); | |
} | |
}); | |
dessertContainer.addView(tv); | |
} | |
}) | |
.show(); | |
} | |
}); | |
sendButton = (Button) findViewById(R.id.send_button); | |
sendButton.setOnClickListener(new View.OnClickListener() { | |
@Override | |
public void onClick(View v) { | |
// バリデーション | |
if (validate()) { | |
send(); | |
} | |
} | |
}); | |
// 画面回転対応 | |
if (savedInstanceState != null) { | |
progressView.setVisibility(View.GONE); | |
return; | |
} | |
// プログレスを表示 | |
progressView.setVisibility(View.VISIBLE); | |
// (同期)編集フォームを非表示or無効化 | |
profileContainer.setVisibility(View.GONE); | |
// 1. サーバーからプロフィールデータを取得 | |
AsyncTask<Void, Void, ProfileData> task = new AsyncTask<Void, Void, ProfileData>() { | |
@Override | |
protected ProfileData doInBackground(Void... params) { | |
return getProfileData(); | |
} | |
@Override | |
protected void onPostExecute(ProfileData profileData) { | |
// 2. プロフィールデータを表示 | |
if (!TextUtils.isEmpty(profileData.imageUrl)) { | |
Picasso.with(MainActivity.this).load(profileData.imageUrl).into(thumbnailView); | |
} | |
nameEditText.setText(profileData.name); | |
bioEditText.setText(profileData.bio); | |
experienceSpinner.setSelection(profileData.experience); | |
int id = -1; | |
switch (profileData.eventStatus) { | |
case 0: | |
id = R.id.attend; | |
break; | |
case 1: | |
id = R.id.not_attend; | |
break; | |
case 2: | |
id = R.id.attend; | |
break; | |
} | |
eventGroup.check(id); | |
for (String dessert : profileData.favoriteDessert) { | |
LayoutInflater inflater = getLayoutInflater(); | |
final TextView tv = (TextView) inflater.inflate(R.layout.dessert_item, dessertContainer, false); | |
tv.setText(dessert); | |
tv.setOnClickListener(new View.OnClickListener() { | |
@Override | |
public void onClick(View v) { | |
new AlertDialog.Builder(MainActivity.this) | |
.setMessage("削除しますか?") | |
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { | |
@Override | |
public void onClick(DialogInterface dialog, int which) { | |
dessertContainer.removeView(tv); | |
} | |
}) | |
.setNegativeButton(android.R.string.cancel, null) | |
.show(); | |
} | |
}); | |
dessertContainer.addView(tv); | |
} | |
// 編集フォームを表示or有効化 | |
profileContainer.setVisibility(View.VISIBLE); | |
final AnimatorSet animatorSet = new AnimatorSet(); | |
animatorSet.playTogether( | |
ObjectAnimator.ofFloat(profileContainer, "alpha", 0f, 1f), | |
ObjectAnimator.ofFloat(progressView, "alpha", 1f, 0f) | |
); | |
animatorSet.addListener(new AnimatorListenerAdapter() { | |
@Override | |
public void onAnimationEnd(Animator animation) { | |
super.onAnimationEnd(animation); | |
animatorSet.removeListener(this); | |
// プログレスを非表示 | |
progressView.setVisibility(View.GONE); | |
} | |
}); | |
animatorSet.start(); | |
} | |
}.execute(); | |
} | |
private static final String KEY_IMAGE_URI = "image_uri"; | |
private static final String KEY_DESSERT_LIST = "dessert_list"; | |
@Override | |
protected void onSaveInstanceState(Bundle outState) { | |
super.onSaveInstanceState(outState); | |
Uri uri = (Uri) thumbnailView.getTag(); | |
if (uri != null) { | |
outState.putString(KEY_IMAGE_URI, uri.toString()); | |
} | |
ArrayList<String> dessertList = new ArrayList<>(); | |
final int childCount = dessertContainer.getChildCount(); | |
for (int i = 0; i < childCount; i++) { | |
final View child = dessertContainer.getChildAt(i); | |
if (child instanceof TextView) { | |
dessertList.add(((TextView) child).getText().toString()); | |
} | |
} | |
outState.putStringArrayList(KEY_DESSERT_LIST, dessertList); | |
} | |
@Override | |
protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) { | |
super.onRestoreInstanceState(savedInstanceState); | |
final String uriString = savedInstanceState.getString(KEY_IMAGE_URI); | |
if (!TextUtils.isEmpty(uriString)) { | |
Uri uri = Uri.parse(uriString); | |
getContentResolver().takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION); | |
try { | |
Bitmap bmp = MediaStore.Images.Media.getBitmap(getContentResolver(), uri); | |
thumbnailView.setImageBitmap(bmp); | |
thumbnailView.setTag(uri); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
} | |
ArrayList<String> dessertList = savedInstanceState.getStringArrayList(KEY_DESSERT_LIST); | |
for (String dessert : dessertList) { | |
LayoutInflater inflater = getLayoutInflater(); | |
final TextView tv = (TextView) inflater.inflate(R.layout.dessert_item, dessertContainer, false); | |
tv.setText(dessert); | |
tv.setOnClickListener(new View.OnClickListener() { | |
@Override | |
public void onClick(View v) { | |
new AlertDialog.Builder(MainActivity.this) | |
.setMessage("削除しますか?") | |
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { | |
@Override | |
public void onClick(DialogInterface dialog, int which) { | |
dessertContainer.removeView(tv); | |
} | |
}) | |
.setNegativeButton(android.R.string.cancel, null) | |
.show(); | |
} | |
}); | |
dessertContainer.addView(tv); | |
} | |
} | |
private boolean validate() { | |
// バリデーション失敗: エラーメッセージ表示 | |
final String name = nameEditText.getText().toString(); | |
if (TextUtils.isEmpty(name)) { | |
Toast.makeText(MainActivity.this, "名前が入力されていません", Toast.LENGTH_SHORT).show(); | |
return false; | |
} | |
final int id = eventGroup.getCheckedRadioButtonId(); | |
if (id != R.id.attend && id != R.id.not_attend && id != R.id.unknown) { | |
Toast.makeText(MainActivity.this, "DroidKaigiが選択されていません", Toast.LENGTH_SHORT).show(); | |
return false; | |
} | |
return true; | |
} | |
private void send() { | |
final Uri imageUri = (Uri) thumbnailView.getTag(); | |
final ProfileData profileData = new ProfileData(); | |
profileData.name = nameEditText.getText().toString(); | |
profileData.bio = bioEditText.getText().toString(); | |
final int position = experienceSpinner.getSelectedItemPosition(); | |
switch (position) { | |
case 0: | |
profileData.experience = ProfileData.EXPERIENCE_U1; | |
break; | |
case 1: | |
profileData.experience = ProfileData.EXPERIENCE_U2; | |
break; | |
case 2: | |
profileData.experience = ProfileData.EXPERIENCE_U3; | |
break; | |
case 3: | |
profileData.experience = ProfileData.EXPERIENCE_U4; | |
break; | |
case 4: | |
profileData.experience = ProfileData.EXPERIENCE_U5; | |
break; | |
case 5: | |
profileData.experience = ProfileData.EXPERIENCE_O5; | |
break; | |
default: | |
return; | |
} | |
final int id = eventGroup.getCheckedRadioButtonId(); | |
switch (id) { | |
case R.id.attend: | |
profileData.eventStatus = ProfileData.EVENT_STATUS_ATTEND; | |
break; | |
case R.id.not_attend: | |
profileData.eventStatus = ProfileData.EVENT_STATUS_NOT_ATTEND; | |
break; | |
case R.id.unknown: | |
profileData.eventStatus = ProfileData.EVENT_STATUS_UNKNOWN; | |
break; | |
default: | |
return; | |
} | |
List<String> favoriteDessert = new ArrayList<>(); | |
final int childCount = dessertContainer.getChildCount(); | |
for (int i = 0; i < childCount; i++) { | |
final View child = dessertContainer.getChildAt(i); | |
if (child instanceof TextView) { | |
favoriteDessert.add(((TextView) child).getText().toString()); | |
} | |
} | |
profileData.favoriteDessert = favoriteDessert; | |
// 送信ボタン無効化 | |
sendButton.setEnabled(false); | |
// プログレスを表示 | |
progressView.setVisibility(View.VISIBLE); | |
progressView.animate().alpha(1f); | |
// 5. データの更新をサーバーに送信 | |
AsyncTask<Void, Void, Boolean> task = new AsyncTask<Void, Void, Boolean>() { | |
@Override | |
protected Boolean doInBackground(Void... params) { | |
if (imageUri != null) { | |
String imageUrl = sendImage(imageUri); | |
if (TextUtils.isEmpty(imageUrl)) { | |
return false; | |
} | |
profileData.imageUrl = imageUrl; | |
} | |
return sendProfileData(profileData); | |
} | |
@Override | |
protected void onPostExecute(Boolean result) { | |
if (isFinishing()) { | |
return; | |
} | |
if (result) { | |
Toast.makeText(MainActivity.this, "更新しました", Toast.LENGTH_SHORT).show(); | |
finish(); | |
} else { | |
Toast.makeText(MainActivity.this, "更新できませんでした", Toast.LENGTH_SHORT).show(); | |
// 送信ボタン有効化 | |
sendButton.setEnabled(true); | |
final ObjectAnimator animator = ObjectAnimator.ofFloat(progressView, "alpha", 1f, 0f); | |
animator.addListener(new AnimatorListenerAdapter() { | |
@Override | |
public void onAnimationEnd(Animator animation) { | |
super.onAnimationEnd(animation); | |
animator.removeListener(this); | |
// プログレスを非表示 | |
progressView.setVisibility(View.GONE); | |
} | |
}); | |
animator.start(); | |
} | |
} | |
}.execute(); | |
} | |
private String sendImage(Uri imageUri) { | |
// ネットワーク通信をダミーするためにスリープ | |
try { | |
Thread.sleep(3000); | |
} catch (InterruptedException e) { | |
e.printStackTrace(); | |
} | |
return "https://pbs.twimg.com/profile_images/542953617108398081/Gs_eKy2k.jpeg"; | |
} | |
Random random = new Random(); | |
private ProfileData getProfileData() { | |
// ネットワーク通信をダミーするためにスリープ | |
try { | |
Thread.sleep(3000); | |
} catch (InterruptedException e) { | |
e.printStackTrace(); | |
} | |
ProfileData profileData = new ProfileData(); | |
profileData.name = random.nextBoolean() ? "Droid" : ""; | |
if (!TextUtils.isEmpty(profileData.name)) { | |
profileData.imageUrl = "https://dl.dropboxusercontent.com/u/7053182/ic_yanzm.jpeg"; | |
profileData.bio = random.nextBoolean() ? "世界をまたにかけるAndroid開発者" : ""; | |
int experience = random.nextInt(6); // 0 〜 5; | |
switch (experience) { | |
case 0: | |
profileData.experience = ProfileData.EXPERIENCE_U1; | |
break; | |
case 1: | |
profileData.experience = ProfileData.EXPERIENCE_U2; | |
break; | |
case 2: | |
profileData.experience = ProfileData.EXPERIENCE_U3; | |
break; | |
case 3: | |
profileData.experience = ProfileData.EXPERIENCE_U4; | |
break; | |
case 4: | |
profileData.experience = ProfileData.EXPERIENCE_U5; | |
break; | |
case 5: | |
profileData.experience = ProfileData.EXPERIENCE_O5; | |
break; | |
} | |
int eventStatus = random.nextInt(3); // 0 〜 2; | |
switch (eventStatus) { | |
case 0: | |
profileData.eventStatus = ProfileData.EVENT_STATUS_ATTEND; | |
break; | |
case 1: | |
profileData.eventStatus = ProfileData.EVENT_STATUS_NOT_ATTEND; | |
break; | |
case 2: | |
profileData.eventStatus = ProfileData.EVENT_STATUS_UNKNOWN; | |
break; | |
} | |
final String[] desserts = getResources().getStringArray(R.array.desserts); | |
int start = random.nextInt(desserts.length); | |
int size = random.nextInt(desserts.length); | |
List<String> favoriteDessert = new ArrayList<>(); | |
for (int i = start; i < start + size && i < desserts.length; i++) { | |
favoriteDessert.add(desserts[i]); | |
} | |
profileData.favoriteDessert = favoriteDessert; | |
} | |
return profileData; | |
} | |
private boolean sendProfileData(ProfileData profileData) { | |
// ネットワーク通信をダミーするためにスリープ | |
try { | |
Thread.sleep(3000); | |
} catch (InterruptedException e) { | |
e.printStackTrace(); | |
} | |
return random.nextBoolean(); | |
} | |
public static class ProfileData { | |
@Retention(RetentionPolicy.SOURCE) | |
@IntDef({EVENT_STATUS_ATTEND, EVENT_STATUS_NOT_ATTEND, EVENT_STATUS_UNKNOWN}) | |
public @interface EventStatus { | |
} | |
public static final int EVENT_STATUS_ATTEND = 0; | |
public static final int EVENT_STATUS_NOT_ATTEND = 1; | |
public static final int EVENT_STATUS_UNKNOWN = 2; | |
@Retention(RetentionPolicy.SOURCE) | |
@IntDef({EXPERIENCE_U1, EXPERIENCE_U2, EXPERIENCE_U3, EXPERIENCE_U4, EXPERIENCE_U5, EXPERIENCE_O5}) | |
public @interface Experience { | |
} | |
public static final int EXPERIENCE_U1 = 0; | |
public static final int EXPERIENCE_U2 = 1; | |
public static final int EXPERIENCE_U3 = 2; | |
public static final int EXPERIENCE_U4 = 3; | |
public static final int EXPERIENCE_U5 = 4; | |
public static final int EXPERIENCE_O5 = 5; | |
String imageUrl; | |
String name; | |
String bio; | |
@Experience | |
int experience = 0; | |
@EventStatus | |
int eventStatus = -1; | |
List<String> favoriteDessert = new ArrayList<>(); | |
} | |
@Override | |
public boolean onOptionsItemSelected(MenuItem item) { | |
if (item.getItemId() == android.R.id.home) { | |
finish(); | |
return true; | |
} | |
return super.onOptionsItemSelected(item); | |
} | |
@Override | |
protected void onActivityResult(int requestCode, int resultCode, Intent data) { | |
if (requestCode == REQUEST_CODE_PICK_IMAGE) { | |
if (resultCode != RESULT_OK) { | |
return; | |
} | |
final Uri uri = data.getData(); | |
getContentResolver().takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION); | |
try { | |
Bitmap bmp = MediaStore.Images.Media.getBitmap(getContentResolver(), uri); | |
thumbnailView.setImageBitmap(bmp); | |
thumbnailView.setTag(uri); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
return; | |
} | |
super.onActivityResult(requestCode, resultCode, data); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment