Android
Android::RecyclerView, Lottie, Animation μ¬μ©ν΄μ λ©λͺ¨μ₯ μ± μμ νκΈ°
λμΊλ¦¬π±
2020. 7. 30. 15:17
λ°μν
β 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"
android:background="@color/colorPrimary"
tools:context=".MainActivity">
<ImageButton
android:id="@+id/main_btn_back"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginLeft="20dp"
android:layout_marginTop="12dp"
android:background="@color/colorPrimaryDark"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:srcCompat="@drawable/ic_arrow_back_black_24dp"
tools:ignore="ContentDescription,RtlHardcoded,VectorDrawableCompat" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/main_lv_memo_list"
android:layout_width="match_parent"
android:layout_height="590dp"
app:layout_constraintTop_toBottomOf="@+id/main_btn_back"
android:layout_marginTop="30dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:scrollbarFadeDuration="0"
android:scrollbarSize="5dp"
android:scrollbarThumbVertical="@color/colorPrimaryDark"
android:scrollbars="vertical"
/>
<TextView
android:id="@+id/main_tv_count"
android:text="15"
android:textColor="@color/colorText"
android:gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
android:layout_marginLeft="170dp"
app:layout_constraintTop_toBottomOf="@id/main_lv_memo_list"
tools:ignore="HardcodedText,RtlHardcoded"/>
<TextView
android:id="@+id/main_tv_explain"
android:text="κ°μ λ©λͺ¨"
android:textColor="@color/colorText"
android:gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="@id/main_tv_count"
app:layout_constraintTop_toBottomOf="@id/main_lv_memo_list"
android:layout_marginLeft="5dp"
tools:ignore="HardcodedText,RtlHardcoded"/>
<ImageButton
android:id="@+id/main_btn_search"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginRight="10dp"
android:layout_marginBottom="12dp"
android:background="@color/colorPrimaryDark"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toLeftOf="@+id/main_btn_add_text"
app:srcCompat="@drawable/ic_search_black_24dp"
tools:ignore="ContentDescription,RtlHardcoded,VectorDrawableCompat" />
<ImageButton
android:id="@+id/main_btn_add_text"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginRight="20dp"
android:layout_marginBottom="12dp"
android:background="@color/colorPrimaryDark"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:srcCompat="@drawable/ic_mode_edit_black_24dp"
tools:ignore="ContentDescription,RtlHardcoded,VectorDrawableCompat" />
</androidx.constraintlayout.widget.ConstraintLayout>
CustomAdapter
package com.example.rvmemoapplication;
import android.content.Context;
import android.content.Intent;
import android.text.Layout;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import org.w3c.dom.Text;
import java.util.ArrayList;
import java.util.List;
// CustomAdapter: ArrayList μ μλ Memo ν΄λμ€ νμ
μ λ°μ΄ν°λ₯Ό RecyclerView μ 보μ¬μ£Όλ μ²λ¦¬λ₯Ό νλ€.
public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.CustomViewHolder>
{
// RecyclerView.Adapter λ₯Ό μμλ°μ μλ‘μ΄ μ΄λν°λ₯Ό λ§λ€ λ μ€λ²λΌμ΄λ ν΄μΌνλ ν¨μ
// : onCreateViewHolder : viewType ννμ μμ΄ν
λ·°λ₯Ό μν λ·° νλ κ°μ²΄ μμ±
// : onBindViewHolder : position μ ν΄λΉνλ λ°μ΄ν°λ₯Ό λ·°νλμ μμ΄ν
λ·°μ νμ
// : getItemCount : μ 체 μμ΄ν
κ°―μ 리ν΄
private ArrayList<Memo> mList;
//(1) 컀μ€ν
리μ€λ μΈν°νμ΄μ€ μ μ - onItemClick, onItemLongClick
public interface OnItemClickListener
{
void onItemClick(View v, int pos);
}
public interface OnItemLongClickListener
{
void onItemLongClick(View v, int pos);
}
//(2) 리μ€λ κ°μ²΄λ₯Ό μ λ¬νλ λ©μλμ μ λ¬λ κ°μ²΄λ₯Ό μ μ₯ν λ³μ(mListener) μΆκ°
private OnItemClickListener mListener =null;
private OnItemLongClickListener mLongListener = null;
public void setOnItemClickListener(OnItemClickListener listener)
{
this.mListener = listener;
}
public void setOnItemLongClickListener(OnItemLongClickListener listener)
{
this.mLongListener = listener;
}
// μμ΄ν
λ·°λ₯Ό μ μ₯νλ λ·°νλ ν΄λμ€
public class CustomViewHolder extends RecyclerView.ViewHolder
{
TextView title;
TextView contents;
public CustomViewHolder(View itemview) {
super(itemview);
// λ·° κ°μ²΄μ λν μ°Έμ‘°
this.title = (TextView)itemview.findViewById(R.id.memo_tv_title);
this.contents = (TextView)itemview.findViewById(R.id.memo_tv_contents);
// this.like = (ImageButton)view.findViewById(R.id.memo_btn_heart);
// (3)λ·°νλκ° λ§λ€μ΄μ§λ μμ μ ν΄λ¦ μ΄λ²€νΈλ₯Ό μ²λ¦¬ν΄μΌ νλ€.
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//리μ¬μ΄ν΄λ¬λ·°μ λ·°νλμλ μμ μ μμΉλ₯Ό νμΈν μ μλ μλ λ©μλ μ 곡
int pos = getAdapterPosition();
if(pos!= RecyclerView.NO_POSITION)
{
mListener.onItemClick(v,pos);
}
}
});
itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
int pos = getAdapterPosition();
if(pos != RecyclerView.NO_POSITION)
{
mLongListener.onItemLongClick(v,pos);
}
return true;
}
});
}
}
// μμ±μμμ λ°μ΄ν° 리μ€νΈ κ°μ²΄λ₯Ό μ λ¬λ°λλ€.
public CustomAdapter(ArrayList<Memo> list)
{
this.mList = list;
}
// μμ΄ν
λ·°λ₯Ό μν λ·°νλ κ°μ²΄ μμ±νμ¬ λ¦¬ν΄νλ€.
@Override
public CustomViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType)
{
Context context = viewGroup.getContext();
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) ;
View view = inflater.inflate(R.layout.item_memo, viewGroup, false);
// View view = LayoutInflater.from(viewGroup.getContext())
// .inflate(R.layout.item_memo,viewGroup, false);
CustomViewHolder viewHolder = new CustomViewHolder(view);
return viewHolder;
}
// position μ ν΄λΉνλ λ°μ΄ν°λ₯Ό λ·°νλμ μμ΄ν
λ·°μ νμ
@Override
public void onBindViewHolder(@NonNull CustomViewHolder viewHolder, int position)
{
viewHolder.title.setText(mList.get(position).getTitle());
viewHolder.contents.setText(mList.get(position).getContents());
}
// μ 체 λ°μ΄ν° κ°―μ 리ν΄
@Override
public int getItemCount() {
// mList λΉμ΄ μμΌλ©΄ 0리ν΄, μλλ©΄ mList μ¬μ΄μ¦ 리ν΄
// return (null != mList ? mList.size():0);
return mList.size();
}
}
MainActivity
package com.example.rvmemoapplication;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.os.Handler;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
ArrayList<Memo> mArrayList;
private CustomAdapter mAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getSupportActionBar().hide();
}
@Override
public void onBackPressed() {
// super.onBackPressed();
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
builder.setNegativeButton("No", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
builder.setMessage("Do you want to quit this app?");
builder.setTitle("Exit Notification");
builder.show();
}
@Override
protected void onResume() {
super.onResume();
mArrayList =new ArrayList<>();
// [Done] 리μ¬μ΄ν΄λ¬λ·°μ μ°κ²°
final RecyclerView mRecyclerView = (RecyclerView)findViewById(R.id.main_lv_memo_list);
LinearLayoutManager mLinearLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLinearLayoutManager);
mAdapter = new CustomAdapter(mArrayList);
mRecyclerView.setAdapter(mAdapter);
// [Done] DBHelper κ°μ²΄ μμ±
String dbName = "Memo0.db";
int dbVersion = 1;
final DBHelper dbHelper;
// [Done] db μμ κ° κ°μ Έμμ Memo ν΄λμ€μ λ΄μ mArrayList μ λ΄κΈ°
dbHelper = new DBHelper(this,dbName,null,dbVersion);
final SQLiteDatabase db = dbHelper.getReadableDatabase();
String sql = "SELECT * FROM Memo0;";
Cursor cursor = db.rawQuery(sql,null);
final TextView memoCount = findViewById(R.id.main_tv_count);
// [Done] λ°μ΄ν° λ°λκ±° κ°μ§ ν μ μκ²λ
mAdapter.notifyDataSetChanged();
memoCount.setText(String.valueOf(cursor.getCount()));
try{
if(cursor.getCount() >0)
{
while(cursor.moveToNext())
{
// DBμ μλ κ°λ€μ String κ°λ€μ Memo ν΄λμ€ μμ±μμ λ΄κΈ°.
Memo m = new Memo(cursor.getString(1),cursor.getString(2));
mArrayList.add(m);
}
}
}finally {
cursor.close();
}
final ImageButton backBtn = findViewById(R.id.main_btn_back);
final ImageButton searchBtn = findViewById(R.id.main_btn_search);
final ImageButton newBtn = findViewById(R.id.main_btn_add_text);
// [Done] λ€λ‘κ°κΈ° λ²νΌ
backBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Animation anim = AnimationUtils.loadAnimation(
getApplicationContext(),
R.anim.scale_anim);
backBtn.startAnimation(anim);
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
builder.setNegativeButton("No", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
builder.setMessage("Do you want to quit this app?");
builder.setTitle("Exit Notification");
builder.show();
}
});
String got_title_from_custom_Dialog;
// κ²μ λ²νΌ
searchBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Animation anim = AnimationUtils.loadAnimation(
getApplicationContext(),
R.anim.scale_anim);
searchBtn.startAnimation(anim);
Handler delayHandler = new Handler();
delayHandler.postDelayed(new Runnable() {
@Override
public void run() {
// TODO
// customDialog = new CustomDialog(this);
// customDialog.show();
//
// private View.OnClickListener searchListener = new View.OnClickListener() {
// @Override
// public void onClick(View v) {
//
// }
// }
}
}, 2000);
}
});
// [Done] μλ‘μ΄ λ©λͺ¨ μΆκ° λ²νΌ
newBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// float deg = newBtn.getRotation() + 80F;
// newBtn.animate().rotation(deg).setInterpolator(new AccelerateDecelerateInterpolator());
Animation anim = AnimationUtils.loadAnimation(
getApplicationContext(),
R.anim.rotate_anim);
newBtn.startAnimation(anim);
Handler delayHandler = new Handler();
delayHandler.postDelayed(new Runnable() {
@Override
public void run() {
// TODO
Intent intent = new Intent(MainActivity.this, DetailActivity.class);
startActivity(intent);
}
}, 2000);
}
});
// [Done] 리μ¬μ΄ν΄ λ·° λ΄μ μμ΄ν
ν΄λ¦μ → edit
mAdapter.setOnItemClickListener(new CustomAdapter.OnItemClickListener() {
@Override
public void onItemClick(View v, int pos) {
Intent intent = new Intent(MainActivity.this, EditActivity.class);
Cursor cursor = (Cursor) dbHelper.getReadableDatabase().query("Memo0",null,null,null,null,null,null);
cursor.moveToPosition(pos);
String t_title = cursor.getString(1);
String c_contents = cursor.getString(2);
intent.putExtra("title",t_title);
intent.putExtra("contents",c_contents);
startActivity(intent);
}
});
// [Done] 리μ¬μ΄ν΄ λ·° λ΄μ μμ΄ν
λ‘±ν΄λ¦μ → μμ μ¬λΆ
mAdapter.setOnItemLongClickListener(new CustomAdapter.OnItemLongClickListener() {
@Override
public void onItemLongClick(View v, final int pos) {
final Cursor cursor = (Cursor) dbHelper.getReadableDatabase().query("Memo0",null,null,null,null,null,null);
cursor.moveToPosition(pos);
final String t_title = cursor.getString(1);
// String c_contents = cursor.getString(2);
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// λ©λͺ¨ μμ μμ
String sql0 ="DELETE FROM Memo0 WHERE title = '"+ t_title +"';";
db.execSQL(sql0);
mArrayList.remove(pos);
mAdapter.notifyDataSetChanged();
memoCount.setText(String.valueOf(mArrayList.size()));
}
});
builder.setNegativeButton("No", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
builder.setMessage("Do you want to delete this memo?");
builder.setTitle("Delete Notification");
builder.show();
}
});
}
}
β μ°Έκ³
Lottieλ₯Ό μ΄μ©ν΄ νλ €ν μ λλ©μ΄μ λ£κΈ°
lottiefiles.com/popular?page=2
postDelayedλ©μλλ₯Ό μ΄μ©ν delay μ²λ¦¬
μλλ‘μ΄λ 리μ¬μ΄ν΄λ¬λ·° κΈ°λ³Έ μ¬μ©λ². (Android RecyclerView)
RecyclerView λ°μ΄ν° μΆκ°/ νΈμ§ μμ
RecyclerView μμ΄ν ν΄λ¦ μ΄λ²€νΈ
RecyclerView μμ
Recyclerview
developer.android.com/jetpack/androidx/releases/recyclerview
ConstraintLayout μ²΄μΈ μ€μ νκΈ°
λ°μν