본문 바로가기
Android

Android [메모앱/서치/리사이클] maxline, ellipsize, addTextChangedListener, github 올리기

by leopard4 2023. 2. 3.

DB 서치

recyclerView 처리

AlertDialog

Serializable (객체를 인텐트로 전달하고자 할때사용하는것)

 

visibility
gone
Tip
atributes ( maxline , ellipsize )

디자인 속성에 

maxline 2 ( 2줄로 보여줘)

ellipsize end ( 줄을 초과하면 ...으로 표시)

 

cardView 라운딩,입체감

cardConerRadius (라운딩)

cardElevaion (입체감주기)

 

main 액티비티

package com.leopard4.memorecycleapp;

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;

import com.leopard4.memorecycleapp.adapter.MemoAdapter;
import com.leopard4.memorecycleapp.data.DatabaseHandler;
import com.leopard4.memorecycleapp.model.Memo;

import java.util.List;

public class MainActivity extends AppCompatActivity {

    Button btnAdd;
    EditText editSearch;
    ImageView imgSearch, imgDelete;


    RecyclerView recyclerView;
    MemoAdapter adapter;
    List<Memo> memoList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        btnAdd = findViewById(R.id.btnAdd);
        editSearch = findViewById(R.id.editSearch);
        imgSearch = findViewById(R.id.imgSearch);
        imgDelete = findViewById(R.id.imgDelete);

        // 리사이클러뷰를 화면에 연결하고,
        // 쌍으로 같이 다니는 코드도 작성
        recyclerView = findViewById(R.id.recyclerView);
        recyclerView.setHasFixedSize(true);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));

        // 버튼을 누르면 메모 생성화면으로 이동
        btnAdd.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                Intent intent = new Intent(MainActivity.this, AddActivity.class);
                startActivity(intent);

            }

    });
        // 검색기능
        imgSearch.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                // 검색어를 가져와서, DB에서 검색
                String search = editSearch.getText().toString().trim();

                // search가 비어있거나, 공백이면 이런코드도 작성할 수 있으나 여기선 필요없다.
//                if(search.isEmpty() || search.equals("")){
//                    return;
//                }
                DatabaseHandler db = new DatabaseHandler(MainActivity.this);
                memoList = db.searchMemo(search);

                // 리사이클러뷰에 어댑터를 연결(화면에 표시)
                adapter = new MemoAdapter(MainActivity.this, memoList);
                recyclerView.setAdapter(adapter);

                // 검색이 끝나면 검색어를 지운다.
                editSearch.setText("");

            }
        });

        // X이미지를 눌르면 메인화면으로 돌아간다.
        imgDelete.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                    // DB에서 데이터를 가져와서, 리사이클러뷰에 뿌려준다.
                    DatabaseHandler db = new DatabaseHandler(MainActivity.this);
                    memoList = db.getAllMemo();

                    // 리사이클러뷰에 어댑터를 연결
                    adapter = new MemoAdapter(MainActivity.this, memoList);
                    recyclerView.setAdapter(adapter);
            }
        });



    }

    @Override
    protected void onResume() {

        // DB에서 데이터를 가져와서, 리사이클러뷰에 뿌려준다.
        DatabaseHandler db = new DatabaseHandler(MainActivity.this);
        memoList = db.getAllMemo();

        // 리사이클러뷰에 어댑터를 연결
        adapter = new MemoAdapter(MainActivity.this, memoList);
        recyclerView.setAdapter(adapter);

        super.onResume();

    }

}

db핸들러

package com.leopard4.memorecycleapp.data;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

import androidx.annotation.Nullable;

import com.leopard4.memorecycleapp.model.Memo;
import com.leopard4.memorecycleapp.util.Util;

import java.util.ArrayList;
import java.util.List;

public class DatabaseHandler extends SQLiteOpenHelper {


    public DatabaseHandler(@Nullable Context context) {
        super(context, Util.DB_NAME, null, Util.DB_VERSION);
    }

    // 테이블 생성
    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {

        String CREATE_MEMO_TABLE = "create table memo ( id integer primary key, title text, content text)";

        sqLiteDatabase.execSQL(CREATE_MEMO_TABLE); // SQL문 실행

    }

    // 기존에 테이블을 삭제하고, 새 테이블을 다시 만든다.
    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
        String DROP_TABLE = "drop table memo";

        sqLiteDatabase.execSQL(DROP_TABLE, new String[]{Util.TABLE_NAME});

        onCreate(sqLiteDatabase);
    }
    // 이제부터는 우리가 앱 동작시키는데 필요한
    // CRUD 관련된 SQL문이 들어간,
    // 메소드를 만들면 된다.

    // 1. 메모 추가하는 메소드(함수) c (create)
    public void addMemo(Memo memo) {
        // 데이터베이스에 쓰기 위한 객체를 생성
        SQLiteDatabase db = this.getWritableDatabase();

        // 쿼리문작성
        String query = "insert into memo (title, content) values ( ? , ?)";
        String[] args = new String[] {memo.getTitle(), memo.getContent()};
        // 데이터베이스에 저장
        db.execSQL(query, args);
        db.close();
    }
    // 2. 메모 읽어오는 메소드(함수) r (read)
    public List<Memo> getAllMemo() {

        // 데이터베이스 읽기 위한 객체 생성
        SQLiteDatabase db = this.getReadableDatabase();

        // 데이터베이스에서 데이터를 읽어오는 SQL문
        String query = "select * from memo order by id desc";

        // SQL문 실행
        Cursor cursor = db.rawQuery(query, null);


        // 데이터베이스에서 읽어온 데이터를
        // Memo 객체에 저장
        List<Memo> memoList = new ArrayList<>();
        if (cursor.moveToFirst()) {
            do {
                int id = cursor.getInt(0);  // 컬럼의 인덱스
                String title = cursor.getString(1);
                String content = cursor.getString(2);

                Log.i("MEMO_TABLE", "id: " + id + ", title: " + title + ", content: " + content);

                // 이 데이터를, 화면에 표시하기 위해서는
                // 메모리에 전부 다 남아있어야 한다!!!
                // 그래서, 이 데이터를, Memo 객체로 만들어서
                Memo memo = new Memo(id, title, content);
                // 이 Contact 객체를, List에 담아둔다.
                memoList.add(memo); // 이미 order by로 역순으로 받아서 0 생략

            } while (cursor.moveToNext());
        }
        db.close();

        return memoList;
    }
    // 3. 메모 수정하는 메소드(함수) u (update)
    public void updateMemo(Memo memo) {
        SQLiteDatabase db = this.getWritableDatabase();

        String query = "update memo " +
                "set title = ?, content = ? " +
                "where id = ? ";
        db.execSQL(query, new String[]{memo.title, memo.content, memo.id + ""});     // flask의 record와 비슷하다.

        db.close();
    }

    // 4. 메모 삭제하는 메소드(함수) d (delete)
    public void deleteMemo(Memo memo) {
        SQLiteDatabase db = this.getWritableDatabase();

        String query = "delete from memo where id = ?";

        String[] args = new String[]{memo.id + ""};  // 파라미터로 넘겨줄 값들을 배열로 만든다.

        db.execSQL(query, args);

        db.close();
    }

    // 검색기능
    List<Memo> memoList = new ArrayList<>();
    public List<Memo> searchMemo(String search) {
        // 데이터 베이스에서 saerch를 찾아서 리턴해주는 메소드
        SQLiteDatabase db = this.getReadableDatabase();

        String query = "select * from memo where title like ? or content like ? order by id desc";
        String[] args = new String[]{"%" + search + "%", "%" + search + "%"};
        Log.i("searchLog", search + " " + args[0] + " " + args[1]);
        Cursor cursor = db.rawQuery(query, args);

        // 데이터베이스에서 읽어온 데이터를
        // Memo 객체에 저장
        if (cursor.moveToFirst()) {            // 커서가 첫번째 행으로 이동
            do {
                int id = cursor.getInt(0);  // 컬럼의 인덱스
                String title = cursor.getString(1);
                String content = cursor.getString(2);

                Log.i("MEMO_TABLE", "id: " + id + ", title: " + title + ", content: " + content);

                // 이 데이터를, 화면에 표시하기 위해서는
                // 메모리에 전부 다 남아있어야 한다!!!
                // 그래서, 이 데이터를, Memo 객체로 만들어서
                Memo memo = new Memo(id, title, content);
                // 이 Memo 객체를, List에 담아둔다.
                memoList.add(memo); // 이미 order by로 역순으로 받아서 0 생략

            } while (cursor.moveToNext());
        }
        db.close();

        return memoList;

    }
}

memo 클래스

package com.leopard4.memorecycleapp.model;

import java.io.Serializable;

public class Memo implements Serializable {

        public int id;
        public String title;
        public String content;

        public Memo() {
        }

        public Memo(String title, String content) {
            this.title = title;
            this.content = content;
        }

        public Memo(int id, String title, String content) {
            this.id = id;
            this.title = title;
            this.content = content;

        }

        public String getTitle() {
            return title;
        }

        public void setTitle(String title) {
            this.title = title;
        }

        public String getContent() {
            return content;
        }

        public void setContent(String content) {
            this.content = content;
        }


        public int getId() {
            return id;
        }

        public void setId(int id) {
            this.id = id;
        }
}

 

memo 어댑터

package com.leopard4.memorecycleapp.adapter;

import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.cardview.widget.CardView;
import androidx.recyclerview.widget.RecyclerView;

import com.leopard4.memorecycleapp.EditActivity;
import com.leopard4.memorecycleapp.R;
import com.leopard4.memorecycleapp.data.DatabaseHandler;
import com.leopard4.memorecycleapp.model.Memo;

import java.util.List;

public class MemoAdapter extends RecyclerView.Adapter<MemoAdapter.viewHolder>{

    Context context;
    List<Memo> memoList;

    int deleteIndex;

    public MemoAdapter(Context context, List<Memo> memoList) {
        this.context = context;
        this.memoList = memoList;
    }

    @NonNull
    @Override
    public MemoAdapter.viewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.memo_row, parent, false);
        return new MemoAdapter.viewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull MemoAdapter.viewHolder holder, int position) {

        Memo memo = memoList.get(position);

        holder.txtTitle.setText(memo.title);
        holder.txtContent.setText(memo.content);

    }

    @Override
    public int getItemCount() {
        return memoList.size();
    }

    public class viewHolder extends RecyclerView.ViewHolder {

        TextView txtTitle;
        TextView txtContent;
        ImageView imgDelete;
        CardView cardView;

        public viewHolder(@NonNull View itemView) {
            super(itemView);

            txtTitle = itemView.findViewById(R.id.txtTitle);
            txtContent = itemView.findViewById(R.id.txtContent);
            imgDelete = itemView.findViewById(R.id.imgDelete);
            cardView = itemView.findViewById(R.id.cardView);

            cardView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    // 클릭한 아이템의 인덱스를 가져온다.
                    int index = getAdapterPosition();
                    Memo memo = memoList.get(index);

                    Intent intent = new Intent(context, EditActivity.class);

                    intent.putExtra("memo", memo);

                    context.startActivity(intent);


                }
            });
            // 삭제버튼을 누르면 alertdialog를 띄워서 삭제할지 물어본다.
            imgDelete.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    // 0) 어느 주소록을 삭제할것인지
                    //    삭제할 주소록을 가져온다 (어떤 행을 눌렀는지 파악한다.)
                    deleteIndex = getAdapterPosition();

                    // 1) 알러트 다이얼로그 나온다.
                    AlertDialog.Builder builder = new AlertDialog.Builder(context);
                    builder.setTitle("삭제");
                    builder.setMessage("정말 삭제하시겠습니까?");
                    builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            // 2) 알러트 다이얼로그에서 Yes 눌렀을때
                            //    데이터베이스에서 삭제
                            DatabaseHandler db = new DatabaseHandler(context);

                            Memo memo = memoList.get(deleteIndex);

                            db.deleteMemo(memo);

                            // 알러트 다이얼로그는 액티비티가 아니므로
                            // 메인액티비티의 onResume 함수가 실행안된다.
                            // 따라서 화면 갱신이 안된다.

                            // 즉, 디비에 저장된 데이터 삭제했으니,
                            // 메모리에 저장된 데이터도 삭제한다.
                            memoList.remove(deleteIndex);
                            // 데이터가 변경되었으니, 화면 갱신하라고 어댑터의 함수호출 (상속받은기능)
                            notifyDataSetChanged();
                        }
                    });
                    // 3) 알러트 다이얼로그에서 No 눌렀을때
                    //    아무것도 안한다.
                    builder.setNegativeButton("No", null);
                    builder.show();
                }

            });

        }
    }
}

edit 액티비티

package com.leopard4.memorecycleapp;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import com.leopard4.memorecycleapp.data.DatabaseHandler;
import com.leopard4.memorecycleapp.model.Memo;

public class EditActivity extends AppCompatActivity {

    EditText editTitle;
    EditText editContent;
    Button btnSave;

    int id;



    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_edit);

        editTitle = findViewById(R.id.editTitle);
        editContent = findViewById(R.id.editContent);
        btnSave = findViewById(R.id.btnSave);

        Memo memo = (Memo) getIntent().getSerializableExtra("memo");
        id = memo.getId();
        editTitle.setText(memo.getTitle());
        editContent.setText(memo.getContent());

        btnSave.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String title = editTitle.getText().toString().trim();
                String content = editContent.getText().toString().trim();


                if (title.isEmpty() || content.isEmpty()) {
                    Toast.makeText(EditActivity.this, "모두입력하세요", Toast.LENGTH_SHORT).show();
                    return;
                }

                Memo memo = new Memo(id, title, content);

                // DB에 저장한다.
                DatabaseHandler db = new DatabaseHandler(EditActivity.this);
                db.updateMemo(memo);

                // 유저한테 잘 저장되었다고, 알려주고
                Toast.makeText(EditActivity.this, "수정되었습니다", Toast.LENGTH_SHORT).show();

                // 액티비티 종료, 메인 액티비티로 돌아간다.(메인액티비티는 뒤에 숨어있었으므로)
                finish();
            }
        });
    }
}

add 액티비티

package com.leopard4.memorecycleapp;

import androidx.appcompat.app.AppCompatActivity;


import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import com.leopard4.memorecycleapp.data.DatabaseHandler;
import com.leopard4.memorecycleapp.model.Memo;

public class AddActivity extends AppCompatActivity {

    EditText editTitle;
    EditText editContent;
    Button btnSave;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_add);

        editTitle = findViewById(R.id.editTitle);
        editContent = findViewById(R.id.editContent);
        btnSave = findViewById(R.id.btnSave);

        btnSave.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                String title = editTitle.getText().toString().trim();
                String content = editContent.getText().toString().trim();

                // 제목과 내용이 모두 있어야 한다!
                if (title.isEmpty() || content.isEmpty()) {
                    Toast.makeText(AddActivity.this, "제목과 내용을 모두 입력해주세요", Toast.LENGTH_SHORT).show();
                    return;
                }

                // 묶어서 처리할 Memo 클래스를 하나 만든다.
                Memo memo = new Memo(title, content);

                // DB에 저장한다. // 힙에있는건 날라가므로
                DatabaseHandler db = new DatabaseHandler(AddActivity.this);
                db.addMemo(memo);

                // 유저한테 잘 저장되었다고, 알려주고
                Toast.makeText(AddActivity.this, "저장되었습니다", Toast.LENGTH_SHORT).show();
                // 액티비티 종료
                finish();

            }
        });

    }
}

util 

package com.leopard4.memorecycleapp.util;

public class Util {
    public static final int DB_VERSION = 1;
    public static final String DB_NAME = "memo_db";
    public static final String TABLE_NAME = "memo";

    // 테이블의 컬럼 관련 상수들
    public static final String KEY_ID = "id";
    public static final String KEY_TITLE = "title";
    public static final String KEY_CONTENT = "content";
}

 

0
검색어를 치는 동시에 검색기능 추가

메인액티비티에  아래코드를 추가하면 된다.

editSearch.addTextChangedListener(new TextWatcher() {
    //
    @Override
    public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

    }

    //
    @Override
    public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {

    }


    @Override
    public void afterTextChanged(Editable editable) {
        // 유저가 입력한 키워드 뽑아서
        String search = editSearch.getText().toString().trim();

        // 2글자 이상 입력했을때만, 검색이 되도록 한다.
        if(search.length() < 2 && search.length() > 0){
            return;
        }
        // 디비에서 가져온후
        DatabaseHandler db = new DatabaseHandler(MainActivity.this);
        memoList = db.searchMemo(search);
        // 화면에 표시
        adapter = new MemoAdapter(MainActivity.this, memoList);
        recyclerView.setAdapter(adapter);
    }
});

 

 

android 스튜디오에서 레파지토리에 올리는방법

메뉴에 vcs share project on github로 이동 / log in with token / share버튼 클릭