반응형
공감 및 댓글은 포스팅 하는데 아주아주 큰 힘이 됩니다!! 포스팅 내용이 찾아주신 분들께 도움이 되길 바라며 더 깔끔하고 좋은 포스팅을 만들어 나가겠습니다^^
|
RxJava를 사용해서 타이머를 구현해봤습니다.
5 x 5 판은 RecyclerView에 GridLayoutManager를 set 해서 만들었고,
터치 이벤트는 item들의 좌표를 구해서 좌표에 해당하는 position이
선택되도록 만들었습니다.
데이터바인딩도 사용했습니다.
사이즈는 대충 만들었기 때문에 사용하실 분들은 본인 스크린사이즈에 맞게
사용하셔야 합니다.
java 파일
MainActivity.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | package superbrain.rowan.com.onetofiftygame; import android.databinding.DataBindingUtil; import android.net.Uri; import android.os.Handler; import android.support.annotation.NonNull; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.RecyclerView; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.widget.Button; import android.widget.Toast; import java.util.Vector; import java.util.concurrent.TimeUnit; import io.reactivex.Observable; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.CompositeDisposable; import io.reactivex.disposables.Disposable; import io.reactivex.functions.Action; import io.reactivex.schedulers.Schedulers; import superbrain.rowan.com.onetofiftygame.databinding.ActivityMainBinding; public class MainActivity extends AppCompatActivity { Vector<Integer> _1to25, _26to50; ActivityMainBinding binding; ItemAdapter adapter; Observable<Long> duration; Disposable disposable; int now; Handler handler; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); binding = DataBindingUtil.setContentView(this, R.layout.activity_main); handler = new Handler(); init(); binding.retryBtn.setOnClickListener(view -> { stop(); init(); }); } private void timer() { duration = Observable.interval(10, TimeUnit.MILLISECONDS) .map(milli -> milli += 1L); disposable = duration.subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(s -> { long sec = s / 100; long milli = s % 100; runOnUiThread(() ->binding.timeTxtView.setText(sec + " : " + milli)); }); } private void stop() { CompositeDisposable disposable = new CompositeDisposable(); disposable.add(this.disposable); disposable.dispose(); } @Override protected void onDestroy() { super.onDestroy(); stop(); } private void init() { timer(); binding.gridView.removeOnItemTouchListener(select); now = 1; _1to25 = new Vector<>(); _26to50 = new Vector<>(); for (int i = 1; i <= 25; i++) { _1to25.add(i); _26to50.add(i + 25); } binding.gridView.setLayoutManager(new GridLayoutManager(this, 5)); adapter = new ItemAdapter(this); binding.gridView.setAdapter(adapter); for (int i = 1; i <= 25; i++) { int rand = (int) (Math.random() * _1to25.size()); adapter.init1to25(_1to25.get(rand)); _1to25.remove(rand); adapter.notifyDataSetChanged(); } binding.gridView.addOnItemTouchListener(select); } private RecyclerView.OnItemTouchListener select = new RecyclerView.OnItemTouchListener() { @Override public boolean onInterceptTouchEvent(@NonNull RecyclerView parent, @NonNull MotionEvent evt) { try { switch (evt.getAction()) { case MotionEvent.ACTION_UP: Button child = (Button) parent.findChildViewUnder(evt.getX(), evt.getY()); if (child != null) { int selected = Integer.parseInt(child.getText().toString()); if (selected == now) { int position = parent.getChildAdapterPosition(child); Log.e("position", " => " + selected); if(selected >= 26 && selected == now) adapter.setUpVisible(position); now++; if(_26to50 != null) { int rand = (int) (Math.random() * _26to50.size()); adapter.update26to50(position, _26to50.get(rand)); _26to50.remove(rand); if(_26to50.size() == 0) _26to50 = null; } adapter.notifyItemChanged(position); } else { Toast.makeText(MainActivity.this, "다시 시도해주세요.", Toast.LENGTH_SHORT).show(); } if(now == 51) stop(); } break; } } catch (Exception e) { e.printStackTrace(); } return false; } @Override public void onTouchEvent(@NonNull RecyclerView recyclerView, @NonNull MotionEvent motionEvent) { } @Override public void onRequestDisallowInterceptTouchEvent(boolean b) { } }; } | cs |
ItemAdapter.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | package superbrain.rowan.com.onetofiftygame; import android.content.Context; import android.support.annotation.NonNull; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import java.util.Vector; import superbrain.rowan.com.onetofiftygame.databinding.Item1Binding; public class ItemAdapter extends RecyclerView.Adapter<ItemAdapter.ItemViewHolder> { private Vector<Integer> _1to50 = new Vector<>(); private Vector<Integer> visible = new Vector<>(); Context context; public ItemAdapter(Context context) { this.context = context; for (int i = 0; i < 25; i++) { visible.add(i, View.VISIBLE); } } @NonNull @Override public ItemViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) { Item1Binding binding = Item1Binding.inflate(LayoutInflater.from(context), viewGroup, false); return new ItemViewHolder(binding); } @Override public void onBindViewHolder(@NonNull ItemViewHolder itemViewHolder, int position) { Item1Binding binding = itemViewHolder.binding; int number = _1to50.get(position); binding.numberBtn.setText(String.valueOf(number)); binding.numberBtn.setVisibility(visible.get(position)); //난이도 설정. /*if(number >= 1 && number <=10) { binding.numberBtn.setBackgroundColor(Color.YELLOW); binding.numberBtn.setTextColor(Color.BLACK); } else if (number >= 11 && number <= 20) { binding.numberBtn.setBackgroundColor(Color.GREEN); binding.numberBtn.setTextColor(Color.BLACK); } else if (number >= 21 && number <= 30) { binding.numberBtn.setBackgroundColor(Color.BLUE); binding.numberBtn.setTextColor(Color.WHITE); } else if (number >= 31 && number <= 40) { binding.numberBtn.setBackgroundColor(Color.BLACK); binding.numberBtn.setTextColor(Color.WHITE); } else { binding.numberBtn.setBackgroundColor(Color.RED); binding.numberBtn.setTextColor(Color.WHITE); }*/ } @Override public int getItemCount() { return _1to50.size(); } void init1to25(int number) { _1to50.add(number); } void update26to50(int position, int number) { _1to50.remove(position); _1to50.add(position, number); } void setUpVisible(int position) { visible.remove(position); visible.add(position, View.INVISIBLE); } class ItemViewHolder extends RecyclerView.ViewHolder { Item1Binding binding; ItemViewHolder(Item1Binding binding) { super(binding.getRoot()); this.binding = binding; } } } | cs |
xml 파일
activity_main.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | <?xml version="1.0" encoding="utf-8"?> <layout 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.support.constraint.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <android.support.v7.widget.RecyclerView app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" android:id="@+id/gridView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:overScrollMode="never"/> <TextView android:id="@+id/timeTxtView" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" android:padding="24dp" android:textSize="24sp" android:textColor="@android:color/black" android:layout_width="200dp" android:layout_height="wrap_content" /> <Button android:id="@+id/retryBtn" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" android:layout_width="150dp" android:layout_height="120dp" android:text="재시도" android:textColor="@android:color/black" android:textSize="24sp" android:textStyle="bold"/> </android.support.constraint.ConstraintLayout> </layout> | cs |
item_1.xml
1 2 3 4 5 6 7 8 9 10 11 12 | <?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <Button android:layout_margin="2dp" android:id="@+id/numberBtn" android:layout_width="108dp" android:layout_height="108dp" android:textSize="36sp" android:textStyle="bold" tools:text="1"/> </layout> | cs |
이상입니다. 감사합니다.
소스가 필요하신 분들은 댓글달아주세요.
댓글이 3개이상 달리면 깃허브에 소스 공유하겠습니다.
반응형
'안드로이드' 카테고리의 다른 글
안드로이드 RecyclerView Grid 형태로 쓸 때 아이템들 가로세로 크기 동일하게 만드는 방법. ViewTreeObserver.OnGlobalLayoutListener(), getTreeViewObserver() (0) | 2018.12.03 |
---|---|
안드로이드 이미지 때문에 액티비티 로딩속도가 느릴 때 간단한 해결방법 (0) | 2018.11.30 |
안드로이드 애니메이션 확대 애니메이션 expansion, 축소 애니메이션 reduction (0) | 2018.11.19 |
안드로이드 Dialog 외부 영역 투명하게 만들기 (0) | 2018.11.08 |
안드로이드 Dialog 생성 시 Context 인자에 getApplicationContext() 사용 시 에러 발생 (0) | 2018.11.07 |