프로젝트 [자문자답 앱] - 문제 조회 화면 이전/다음 문제 이동 기능

유의선·2024년 2월 21일
0

문제 풀이 화면에서만 가능하던 문제 이전/다음 이동 기능을 문제 조회 화면에도 추가하였다.


문제를 조회하는 화면인 activity_list_q.xml 레이아웃에 이전/다음 문제로 이동하는 버튼을 추가하였다.
그에 따라 수정/삭제 버튼의 위치도 조금 조정하였다.

조금 보기 흉한 버튼 배치가 되어버려 나중에 수정할지도 모른다.


문제 목록을 보여주는 ListActivity.java 파일의 코드를 수정하였다.
start/end 변수를 추가해 해당 태그의 문제의 처음과 끝을 저장하였으며,
intent로 보내는 데이터도 그에따라 바꾸었다.

전체적으로 문제 풀이 목록인 SolveActivity.java 파일의 코드와 유사하게 수정하였다.

public class ListActivity extends AppCompatActivity {

    RecyclerView recyclerView;
    QuestionAdapter adapter;
    Spinner spinner;
    String tag;

    int start, end;

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

            recyclerView = findViewById(R.id.RecyclerView);

            LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
            recyclerView.setLayoutManager(layoutManager);
            adapter = new QuestionAdapter();

            adapter.setOnItemClickListener(new OnQuestionClickListener() {
                @Override
                public void onItemClick(QuestionAdapter.ViewHolder holder, View view, int position) {
                    Question item = adapter.getItem(position);

                    Intent intent = new Intent(getApplicationContext(), ListQActivity.class);
                    //intent.putExtra("data", item);
                    //startActivity(intent);

                    intent.putExtra("id", item.getNum());
                    intent.putExtra("tag", tag);

                    intent.putExtra("start", start);
                    intent.putExtra("end", end);

                    startActivity(intent);
                }
            });

            ...

            ArrayAdapter<String> spinnerAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, items);
            spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
            spinner.setAdapter(spinnerAdapter);

            spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
                @Override
                public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                    tag = items.get(position);

                    if(tag.equals("ALL"))
                        loadQuestionListData();
                    else
                        loadQuestionListDataByTag(tag);
                }

                @Override
                public void onNothingSelected(AdapterView<?> parent) {

                }
            });
    }

    // 문제 삭제 후, ListActivity로 돌아왔을 때 삭제된 것이 반영되도록 하기 위해서
    @Override
    protected void onResume() {
        super.onResume();

        recyclerView = findViewById(R.id.RecyclerView);

        LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
        recyclerView.setLayoutManager(layoutManager);
        adapter = new QuestionAdapter();

        adapter.setOnItemClickListener(new OnQuestionClickListener() {
            @Override
            public void onItemClick(QuestionAdapter.ViewHolder holder, View view, int position) {
                Question item = adapter.getItem(position);

                Intent intent = new Intent(getApplicationContext(), ListQActivity.class);
                //intent.putExtra("data", item);
                //startActivity(intent);

                intent.putExtra("id", item.getNum());
                intent.putExtra("tag", tag);

                intent.putExtra("start", start);
                intent.putExtra("end", end);

                startActivity(intent);
            }
        });
        
        ...
        
        ArrayAdapter<String> spinnerAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, items);
        spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        spinner.setAdapter(spinnerAdapter);

        spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                tag = items.get(position);

                if(tag.equals("ALL"))
                    loadQuestionListData();
                else
                    loadQuestionListDataByTag(tag);
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {

            }
        });
    }

    // 리사이클러뷰에 문제 추가 메소드
    public void loadQuestionListData() {
        adapter.deleteAllItem();
        adapter.notifyDataSetChanged();

        int recyclerviewItemsCount = adapter.getItemCount();
        for(int i = 0; i < recyclerviewItemsCount; i++){

        }

        int recordCount = 0;

        String sql = "select _id, TITLE, QUESTION, ANSWER, TAG FROM " + QuestionDatabase.TABLE_QUESTION + " order by _id ASC";

        QuestionDatabase database = QuestionDatabase.getInstance(this);
        if(database != null){
            Cursor cursor = database.rawQuery(sql);

            recordCount = cursor.getCount();

            for(int i = 0; i < recordCount; i++){
                cursor.moveToNext();

                int _id = cursor.getInt(0);
                if(i == 0)
                    start = _id;
                if(i == recordCount -1)
                    end = _id;

                String Title = cursor.getString(1);
                String Question = cursor.getString(2);
                String Answer = cursor.getString(3);
                String Tag = cursor.getString(4);

                adapter.addItem(new Question(_id, Title, Question, Answer, Tag));
            }

            cursor.close();
            adapter.notifyDataSetChanged();
        }

    }

    public void loadQuestionListDataByTag(String tag) {
        adapter.deleteAllItem();
        adapter.notifyDataSetChanged();

        int recordCount = 0;

        String sql = "select _id, TITLE, QUESTION, ANSWER, TAG FROM " + QuestionDatabase.TABLE_QUESTION + " where TAG = '" + tag + "' order by _id ASC";

        QuestionDatabase database = QuestionDatabase.getInstance(this);
        if(database != null){
            Cursor cursor = database.rawQuery(sql);

            recordCount = cursor.getCount();

            for(int i = 0; i < recordCount; i++){
                cursor.moveToNext();

                int _id = cursor.getInt(0);
                if(i == 0)
                    start = _id;
                if(i == recordCount -1)
                    end = _id;

                String Title = cursor.getString(1);
                String Question = cursor.getString(2);
                String Answer = cursor.getString(3);
                String Tag = cursor.getString(4);

                adapter.addItem(new Question(_id, Title, Question, Answer, Tag));
            }

            cursor.close();
            adapter.notifyDataSetChanged();
        }
    }
}

문제를 조회하는 화면의 코드인 ListQActivity.java 코드를 수정하였다.

전체적으로 SolveQActivity.java와 거의 유사하게 만들었지만,
문제를 수정하고 돌아왔을 때에도 Cursor와 start/end가 유지되고, 바뀐 내용이 적용되어야 하므로 Resume() 함수를 재정의하였다.

Resume() 함수에는 onCreate() 함수와 같은 내용을 담았다.

public class ListQActivity extends AppCompatActivity {
    public static final int REQUEST_CODE_EDIT = 301;

    int id;
    TextView title;
    TextView question;
    TextView answer;
    TextView tag;

    int start, end;

    String tagNow;

    Cursor cursor = null;

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if(requestCode == REQUEST_CODE_EDIT){
            if(resultCode == RESULT_OK){

                Question dataFromEdit = data.getParcelableExtra("dataFromEdit");

                id = dataFromEdit.getNum();
                title.setText(dataFromEdit.getTitle());
                question.setText(dataFromEdit.getQuestion());
                answer.setText(dataFromEdit.getAnswer());
                tag.setText(dataFromEdit.getTag());

                Toast.makeText(getApplicationContext(),"문제가 수정되었습니다.", Toast.LENGTH_SHORT).show();
            }
        }
    }

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

        title = findViewById(R.id.textTitle);
        question = findViewById(R.id.textQuestion);
        answer = findViewById(R.id.textAnswer);
        tag = findViewById(R.id.textTag);

        answer.setMovementMethod(new ScrollingMovementMethod());

        Button buttonDelete = findViewById(R.id.buttonDelete);
        Button buttonEdit = findViewById(R.id.buttonEdit);
        Button buttonBefore = findViewById(R.id.buttonBeforeList);
        Button buttonAfter = findViewById(R.id.buttonAfterList);

        Intent intent = getIntent();

        if(intent != null){
            Bundle bundle = intent.getExtras();
            /*
            Question data = bundle.getParcelable("data");

            id = data.getNum();
            title.setText(data.getTitle());
            question.setText(data.getQuestion());
            answer.setText(data.getAnswer());
            tag.setText(data.getTag());

             */

            id = bundle.getInt("id");

            start = bundle.getInt("start");
            end = bundle.getInt("end");

            tagNow = bundle.getString("tag");
        }

        // 데이터베이스와 커서를 설정하고, 처음 선택된 문제로 커서를 이동한 후 문제 설정
        initQuestion();

        if(id == start)
            buttonBefore.setEnabled(false);
        if(id == end)
            buttonAfter.setEnabled(false);

        buttonDelete.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                showDeleteMessage();
            }
        });

        buttonEdit.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                Question item = new Question(id, title.getText().toString(), question.getText().toString(), answer.getText().toString(), tag.getText().toString());

                Intent intent = new Intent(getApplicationContext(),EditActivity.class);
                intent.putExtra("data", item);
                startActivityForResult(intent, REQUEST_CODE_EDIT);

            }
        });

        buttonBefore.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                cursor.moveToPrevious();
                setQuestion();

                if(id == start){
                    buttonBefore.setEnabled(false);
                }else{
                    buttonBefore.setEnabled(true);
                }

                if(id == end){
                    buttonAfter.setEnabled(false);
                }else{
                    buttonAfter.setEnabled(true);
                }
            }
        });

        buttonAfter.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                cursor.moveToNext();
                setQuestion();

                if(id == start){
                    buttonBefore.setEnabled(false);
                }else{
                    buttonBefore.setEnabled(true);
                }

                if(id == end){
                    buttonAfter.setEnabled(false);
                }else{
                    buttonAfter.setEnabled(true);
                }
            }
        });
    }

    private void showDeleteMessage(){
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("문제 삭제");
        builder.setMessage("정말로 삭제하시겠습니까?");
        builder.setIcon(android.R.drawable.ic_dialog_alert);

        builder.setPositiveButton("예", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                // 삭제 버튼이 눌렸을 때 이벤트
                deleteQuestion();
                finish();
            }
        });

        builder.setNegativeButton("아니오", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                // 아니오 버튼이 눌렸을 때 이벤트
            }
        });
        AlertDialog dialog = builder.create();
        dialog.show();
    }

    private void deleteQuestion(){
        QuestionDatabase database = QuestionDatabase.getInstance(this);

        String sql = "DELETE FROM " + QuestionDatabase.TABLE_QUESTION + " WHERE _id = " + id;
        database.execSQL(sql);

        /*
        sql = "ALTER TABLE " + QuestionDatabase.TABLE_QUESTION + " AUTO_INCREMENT = " + num;
        database.execSQL(sql);
         */
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        if(cursor != null){
            cursor.close();
            cursor = null;
        }

    }

    @Override
    protected void onResume() {
        super.onResume();
        
        ...
        
    }

    private void setQuestion(){
        id = cursor.getInt(0);
        title.setText(cursor.getString(1));
        question.setText(cursor.getString(2));
        answer.setText(cursor.getString(3));
        tag.setText(cursor.getString(4));
    }

    private void initQuestion() {

        QuestionDatabase database = null;

        if(cursor != null){
            cursor.close();
            cursor = null;
        }

        database = QuestionDatabase.getInstance(this);

        String sql;

        if(tagNow.equals("ALL"))
            sql = "select _id, TITLE, QUESTION, ANSWER, TAG FROM " + QuestionDatabase.TABLE_QUESTION + " order by _id ASC";
        else
            sql = "select _id, TITLE, QUESTION, ANSWER, TAG FROM " + QuestionDatabase.TABLE_QUESTION + " where TAG = '" + tagNow + "' order by _id ASC";

        cursor = database.rawQuery(sql);

        int recordCount = cursor.getCount();

        for(int i = 0; i < recordCount; i++){
            cursor.moveToNext();

            int _id = cursor.getInt(0);

            if(_id == id){
                setQuestion();
                break;
            }
        }
    }
}


이제 문제 조회 화면에서도 목록으로 나가는 일 없이 전후 문제에 바로 접근할 수 있도록 만드는데는 성공했지만 몇가지 문제가 야기되었다.

문제를 수정하고 돌아올 때 지금 문제가 아닌, 목록에서 처음 접근했던 문제의 위치로 화면이 돌아가버린다.
이를 수정하기 위해선 onResume() 함수를 조금 손보거나 수정하고 돌아올 때 intent를 통해 정보 전달이 이루어지도록 수정할 필요를 느꼈다.

또한 이 기능을 추가한 건 문제 조회 화면에서 목록으로 돌아갈 때 태그나 위치가 전부 초기화되버리는게 불편해서 추가한것인데, 결국 목록 화면이 초기화되는 문제는 그대로 남아있다.

0개의 댓글