728x90
반응형

 

처음으로 만들 것은 위 사진과 같이 홈화면과 햄버거메뉴

안드로이드에서는 Navigation Drawer라고 부른다

아마 처음 안드로이드 스튜디오를 했을때 대충 넘어갔던 것 같은데....

https://lektion-von-erfolglosigkeit.tistory.com/122

 

Android Studio(4) - 내비게이션 메뉴 바 만들기

※이 글은 강좌가 아니라 필자가 유튜브로 들은 강의 내용을 이해한대로, 정리되지 않은 채 적는 글입니다 www.youtube.com/playlist?list=PLRx0vPvlEmdB6sCgj_jubp8KPb1ni0VOC 이번엔 Empty Activity가 아니라 Na..

lektion-von-erfolglosigkeit.tistory.com

젠장 과거의 나는 왜 그따구로 써놓은 거지

 

프로젝트 생성

홈화면의 베이스는 Navigation Drawer Activity로 진행

 

이번엔 패키지 이름도 정해주었다

보통 중간은 회사이름 같은거 넣던데 그런거 생각 안해봤기 때문에 일단 블로그 첫 단어로...

 

캘린더뷰

안드로이드 스튜디오에서는 자체적으로 캘린더를 위젯으로 제공하고 있다

 

content_main.xml에 CalendarView를 추가한 뒤 대충 위치를 맞춰주었다

당연한 거지만 실행해보면 날짜는 오늘 날짜로 나온다

 

그러나 문제가 발생했다

Home이 아닌 다른 화면으로 넘어가면 CalendarView가 없어져야하는데 그대로 남아있다...

 

 

 

찾아보니 Navigation Drawer의 기본 동작 방식을 알 수 있었다

먼저 content_main.xml은 실제로 보여지는 화면으로 이 화면을 Fragment들이 서로 바꿔가며 사용한다

즉 번갈아 가면서 사용하는 부분에다가 HomeFragment만 가져야하는 CalendarView를 넣어놓 것

 

content_main.xml의 CalendarView를 지우고 fragment_home.xml에 넣어주었다

위쪽 여백 없이 위치시켜야 content_main.xml에서 딱 맞게 나온다

 

 

ListView

그러면 이제 이걸 추가해보자

ListView를 사용하면 될 것 같긴 한데...

생각보다 잘 안된다

그냥 Activity에 추가하는 것과 다르게 뭔가 좀 안되네

 

일단 binding이 계속 헷갈리게 하니까 없애버리고 찾은 정보를 바탕으로 HomeFragment.java를 수정해주엇다

package com.lektion.gympartner.ui.home;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;

import com.lektion.gympartner.R;

public class HomeFragment extends Fragment {

//    private HomeViewModel homeViewModel;
//    private FragmentHomeBinding binding;

    public View onCreateView(@NonNull LayoutInflater inflater,
                            ViewGroup container, Bundle savedInstanceState) {
//        homeViewModel =
//                new ViewModelProvider(this).get(HomeViewModel.class);
//
//        binding = FragmentHomeBinding.inflate(inflater, container, false);
//        View root = binding.getRoot();

        View view = inflater.inflate(R.layout.fragment_home, container, false);

        final String[] LIST = {"List1", "List2", "List3"};

        ListView listView = (ListView) view.findViewById(R.id.listview1);

        ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, LIST);

        listView.setAdapter(adapter);

        return view;
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        //binding = null;
    }
}

기존의 root와 binding 대신에 view를 하나 만들어서 fragment_home을 보여주게 하고

ListView에 보여질 내용인 LIST

layout에 있는 Listview를 할당하는 listview

listview에 LIST를 넣어주는 ArrayAdapter를 선언

 

리스트가 나오게 되긴 했는데 위치가 참 애매하다

LIST에 몇개 더 추가하고 여러가지 조정해보자

대체 기준이 뭔지 감이 안잡힌다...

 

여러번의 시행착오 끝에 적당한 위치를 찾았다

그리고 테두리, 버튼, 텍스트를 추가한 listview로 만들었다!

 

일단 구조는 아래와 같이 listview자체와 그 안에 들어가는 listitem들도 구성되어 있다.

background_listview.xml

drawable에 추가

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape android:shape="rectangle">
            <stroke android:width = "5dp" android:color = "#000000"/>
            <solid android:color="#ffffff"/>
            <corners android:radius="20dp"/>
        </shape>
    </item>
</layer-list>

모양은 rectangle

테두리는 검은색 5dp

배경은 흰색

둥글게 만들었다

background_listitem.xml

drawable에 추가

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape android:shape="rectangle">
            <stroke android:width = "5dp" android:color="#ffffff"/>
            <padding android:left="5dp"
                android:top="5dp"
                android:right="5dp"
                android:bottom="5dp" />
            <solid android:color="#DFE0E0"/>
            <corners android:radius="10dp"/>
        </shape>
    </item>
</layer-list>

모양은 rectangle

테두리는 흰색 5dp

padding은 상하좌우 5dp

배경은 figma에서 만든 색

조금 둥근 테두리

 

listitem.xml

layout에 추가

<?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"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:layout_height="fill_parent"
        android:layout_width="fill_parent"
        android:orientation="horizontal"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.0"
        android:background="@drawable/background_listitem">

        <Button
            android:id="@+id/button"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:layout_margin="10dp"
            android:background="@drawable/roundbutton" />

        <TextView
            android:id="@+id/textList"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:text="adsfsadfsaf"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="20dp"
            android:textSize="70px" />
    </LinearLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

LinearLayout를 기반으로

Button과 Textview를 각각 추가

다른 속성들은 많은 실패 끝에 도달한 것들...

 

fragment_home.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"
    tools:context=".ui.home.HomeFragment">

    <CalendarView
        android:id="@+id/calendarView2"
        android:layout_width="414dp"
        android:layout_height="407dp"
        android:clickable="false"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.491"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.155" />

    <ListView
        android:id="@+id/listview1"
        android:layout_width="333dp"
        android:layout_height="152dp"
        android:background="@drawable/background_listview"
        android:padding="20dp"
        android:dividerHeight="0px"
        android:divider="#ffffff"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.929" />

</androidx.constraintlayout.widget.ConstraintLayout>

ListView의 background를 만들었던 background_listview.xml로 설정

divider(구분 가로줄) 안보이게 설정

padding을 안넣으면 listitem들이 말 그대로 선넘는다...

 

HomeFragment

package com.lektion.gympartner.ui.home;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;

import com.lektion.gympartner.R;

public class HomeFragment extends Fragment {

//    private HomeViewModel homeViewModel;
//    private FragmentHomeBinding binding;

    public View onCreateView(@NonNull LayoutInflater inflater,
                            ViewGroup container, Bundle savedInstanceState) {
//        homeViewModel =
//                new ViewModelProvider(this).get(HomeViewModel.class);
//
//        binding = FragmentHomeBinding.inflate(inflater, container, false);
//        View root = binding.getRoot();

        View view = inflater.inflate(R.layout.fragment_home, container, false);

        final String[] LIST = {"List1", "List2", "List3", "List4", "List5", "List6", "List7"};

        ListView listView = (ListView) view.findViewById(R.id.listview1);

        ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(), R.layout.listitem, R.id.textList, LIST);

        listView.setAdapter(adapter);

        return view;
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        //binding = null;
    }
}

ArrayAdapter 선언 부분에서 (getActivity(), [리스트에 보여지는 layout], [LIST값이 할당될 textView], LIST)로 변경

 

Header 추가하기

이제 listview 위쪽에 위치할 날짜와 추가버튼을 만들어두자

listview_header.xml로 새로운 layout을 만들고 TextView와 버튼을 추가했다

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="horizontal" android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:id="@+id/title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="3dp"
            android:text="날짜"
            android:textSize="20dp"
            android:layout_weight="4" />

        <Button
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:layout_margin="10dp"
            android:background="@drawable/plus"/>
    </LinearLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

 

적당히 추가는 된 것 같은데 스크롤할 때 같이 움직이고 있다...

 

Header는 포기하고 따로 추가하기로 했다

 

fragment_home.xml에 TextView를 추가

id는 date로 정해줬다

위치는 언제나 그렇듯이 대충...

 

이후 HomeFragment.java에 관련 코드 추가

	TextView dateText;
    CalendarView calendarView;
    Calendar calendar;
   
        ...
        
        calendar = Calendar.getInstance();
        dateText = (TextView)view.findViewById(R.id.date);
        calendarView = (CalendarView) view.findViewById(R.id.calendar);

        String date = calendar.get(Calendar.YEAR) + "년 " + (calendar.get(Calendar.MONTH)+1) + "월 " + calendar.get(Calendar.DAY_OF_MONTH) + "일";
        dateText.setText(date);

        calendarView.setOnDateChangeListener(new CalendarView.OnDateChangeListener() {
            @Override
            public void onSelectedDayChange(@NonNull CalendarView view, int year, int month, int dayOfMonth) {
                String date = year + "년 " + (month+1) + "월 " + dayOfMonth + "일";
                dateText.setText(date);
            }
        });
        
        ...

첫 실행에는 Calendar를 이용해서 오늘 날짜로 TextView를 설정

이후 클릭으로 날짜가 바뀌면 그 날짜로 변경

 

이제 플러스 버튼 추가

drawable 폴더에 사용할 이미지를 추가하고 background로 설정해준다

    <Button
        android:layout_width="20dp"
        android:layout_height="20dp"
        android:background="@drawable/plus"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.859"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.718" />

그리고 확인을 위해 Toast를 하나 달아줬다

 

        plusButton = (Button) view.findViewById(R.id.plus);

        plusButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(getActivity(),"루틴 추가창으로", Toast.LENGTH_SHORT).show();
            }
        });

 

제목 변경

마지막으로 제목에 날짜를 적어두자

 

아래 코드를 추가

getActivity().setTitle(calendar.get(Calendar.YEAR) + "." + (calendar.get(Calendar.MONTH)+1));

 

사진과 같이 Fragment의 제목이 날짜로 변경되었다

 

여기서 끝인줄 알았으나...

다른 Fragment에 갔다오면 제목이 그대로인 경우가 발생했다

 

해결을 위해 MainActivity에서 새 함수를 작성

    public void setActionBarTitle(String title)
    {
        ActionBar actionBar = getSupportActionBar();
        if(actionBar != null)
        {
            actionBar.setTitle(title);
        }
    }

그리고 이 함수를 Fragment의 onResume에다 추가하면 된다

    @Override
    public void onResume() {
        super.onResume();

        SimpleDateFormat format = new SimpleDateFormat("yyyy.MM", Locale.KOREA);
        FragmentActivity activity = getActivity();
        if(activity != null)
        {
            ((MainActivity) activity).setActionBarTitle(format.format(calendar.getTime()));
        }
    }

이왕하는 거 format도 맞춰봤다

 

이제 홈화면이 대충 완성되었다

다음에는 메뉴를 Navigation Bar쪽을 좀 수정하면서 Fragment들을 만들 예정이다