728x90
반응형

 

목차

    운동들은 DB에 저장해서 SQLite로 불러오고

    운동에 부위, 운동방식 index 추가

    체크박스 여러개 해서 원하는 운동 볼 수 있게

    ex. 덤벨을 사용하는 등운동

    https://lktprogrammer.tistory.com/170

    저장방식

    운동들은 어떻게 저장하고 불러올까 여러가지 고민을 했었다

     

    SQL은 서버가 필요한 줄 알고 그냥 JSON으로 구상하고 있던 중

    SQLite는 내장메모리에 저장하는 거라는 것을 알게 되었다

     

    그럼 딱히 고민할 필요가 없는데..?

     

    SQLite로 만들자

     

    SQLite

    SQLite는 클라이언트 응용 프로그램에 임베디드되어 동작하는 오픈 소스 DBMS의 일종이라고 한다

    그냥 앞에서 말했듯이 내장메모리에 SQL DB를 만드는 것이다

     

    기본적인 문법은 SQL과 같고 Android Studio에서 함수로 명령어를 실행하면 되는 것 같다

     

    명령어 정리해놓기

    DB 생성 및 삭제

    openOrCreateDatabase(String name, int mode, SQLiteDatabase.CursorFactory factory)

    SQLiteDatabase db = openOrCreateDatabase("DB name", MODE_PRIVATE, null);

    deleteDatabase(String name)

    deleteDatabase("DB name")

    Table

    Table관련 명령어는 SQL의 문법을 그대로 따르되, execSQL(String sql)를 사용한다

    기본적인 SQL 문법들을 알아야 한다

    예전에 적어둔게 있었던 것 같은데...

    db.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_NAME + "(" +
                    "_id INTEGER PRIMARY KEY AUTOINCREMENT," +
                    "name TEXT," +
                    "age INTEGER);");

     

    Layout

    일단 DB에 저장하기 전에 대충 레이아웃을 만들어두자

     

    저번과 같이 ListView를 이용해서 이미지와 텍스트가 있는 list를 만들어 주었다

    list_exercise.xml

    더보기
    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <androidx.appcompat.widget.LinearLayoutCompat
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:orientation="horizontal"
            tools:ignore="MissingConstraints">
    
            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:id="@+id/exerciseImage"
                android:src="@drawable/ic_no_image"
                android:layout_margin="10dp"/>
    
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:id="@+id/exerciseName"
                android:layout_gravity="center"
                android:text="운동이름"
                android:textSize="25dp"
                android:layout_marginLeft="10dp"/>
    
        </androidx.appcompat.widget.LinearLayoutCompat>
    
    </androidx.constraintlayout.widget.ConstraintLayout>

    ListView에 들어갈 Item

     

    fragment_list.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">
    
        <TextView
            android:id="@+id/mini_title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#ECF0F1"
            android:padding="10dp"
            android:text="운동목록"
            android:textSize="25dp"
            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" />
    
        <ListView
            android:id="@+id/exerciseList"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/mini_title"
            app:layout_constraintVertical_bias="0.0"
            tools:ignore="MissingConstraints" />
    
    
    </androidx.constraintlayout.widget.ConstraintLayout>

    Fragment의 레이아웃

     

    ListItem_exercise, ListViewAdapter_exercise

    저번에 만들어두었던 ListItem과 ListViewAdapter가 안맞길래 _뒤에 이름을 달아서 여러개로 만들었다

    더보기
    package com.lektion.gympartner;
    
    public class ListItem_exercise {
        private String name;
        private int preview;
    
        public int getPreview() {
            return preview;
        }
    
        public void setPreview(int preview) {
            this.preview = preview;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }

     

    package com.lektion.gympartner;
    
    import android.content.Context;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.BaseAdapter;
    import android.widget.ImageView;
    import android.widget.TextView;
    
    import java.util.ArrayList;
    
    public class ListViewAdapter_exercise extends BaseAdapter {
        private Context mContext;
        private ArrayList<ListItem_exercise> listItems = new ArrayList<>();
    
        public ListViewAdapter_exercise(Context context)
        {
            this.mContext = context;
        }
    
        @Override
        public int getCount() {
            return listItems.size();
        }
    
        @Override
        public Object getItem(int position) {
            return listItems.get(position);
        }
    
        @Override
        public long getItemId(int position) {
            return position;
        }
    
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            if(convertView == null)
            {
                LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                convertView = inflater.inflate(R.layout.list_exercise,parent,false);
            }
    
            ImageView image = (ImageView) convertView.findViewById(R.id.exerciseImage);
            TextView txt_name = (TextView) convertView.findViewById(R.id.exerciseName);
    
            ListItem_exercise listItem  = listItems.get(position);
    
            txt_name.setText(listItem.getName());
            image.setImageResource(listItem.getPreview());
    
            return convertView;
        }
    
        public void addItem(String name, int preview)
        {
            ListItem_exercise listItem = new ListItem_exercise();
    
            listItem.setName(name);
            listItem.setPreview(preview);
    
            listItems.add(listItem);
        }
    
        public void modifyItem(int position,  String value)
        {
            ListItem_exercise listItem = listItems.get(position);
    
            listItem.setName(value);
        }
    
        public void removeItem(int position)
        {
            listItems.remove(position);
        }
    }

     

    listFragment.java

    더보기
    package com.lektion.gympartner;
    
    import android.os.Bundle;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ListView;
    
    import androidx.annotation.NonNull;
    import androidx.annotation.Nullable;
    import androidx.fragment.app.Fragment;
    import androidx.fragment.app.FragmentActivity;
    
    public class listFragment extends Fragment {
    
        ListView exerciseList;
        ListViewAdapter_exercise adapter;
    
        @Nullable
        @Override
        public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
            View view =  inflater.inflate(R.layout.fragment_list, container, false);
    
            adapter = new ListViewAdapter_exercise(getActivity());
    
            exerciseList = (ListView) view.findViewById(R.id.exerciseList);
            exerciseList.setAdapter(adapter);
    
    
            adapter.addItem("랫풀다운", R.drawable.ic_no_image);
            adapter.addItem("덤벨로우", R.drawable.ic_no_image);
            adapter.addItem("바벨로우", R.drawable.ic_no_image);
            adapter.addItem("풀업", R.drawable.ic_no_image);
            adapter.addItem("벤치프레스", R.drawable.ic_no_image);
            adapter.addItem("인클라인 덤벨 프레스", R.drawable.ic_no_image);
            adapter.addItem("덤벨 플라이", R.drawable.ic_no_image);
            adapter.addItem("디클라인 푸쉬업", R.drawable.ic_no_image);
            adapter.addItem("스쿼트", R.drawable.ic_no_image);
            adapter.addItem("런지", R.drawable.ic_no_image);
            adapter.addItem("레그익스텐션", R.drawable.ic_no_image);
            adapter.addItem("레그컬", R.drawable.ic_no_image);
    
            return view;
        }
    
        @Override
        public void onResume() {
            FragmentActivity activity = getActivity();
            if(activity != null)
            {
                ((MainActivity) activity).setActionBarTitle("운동목록");
            }
            super.onResume();
        }
    }

    당장은 테스트만 하기 때문에 일단 운동을 list에 표시만 하는 코드다

     

     

    이제 저 addItem 부분을 DB에서 받아와서 하는 코드로 바꿔보자

     

    운동 데이터 유형

    운동 데이터가 포함해야할 것들은 id, 운동이름, 운동부위, 운동도구 정도가 있겠다

    id 운동이름 운동부위 운동도구
    1 랫풀다운 머신
    2 벤치프레스 가슴 바벨
    3 스쿼트 하체 바벨
    4 해머컬 이두 덤벨

    운동부위에 따라 정렬가능할 수 있고 리스트에 운동도구를 작게 표시하자

     

    Tabbed Activity

    다시 UI 초안을 보면 운동부위에 따라 여러가지 선택버튼(?)이 있다

    이걸 구현해보자

     

    일단 안드로이드 스튜디오에서 제공하는 Tabbed Activity를 추가해봤다

    역시나 binding을 쓴다...

     

    ViewPager

    viewpager는 listview에 대응된다

    똑같이 adapter를 사용하여 View를 만든다

    https://ju-hy.tistory.com/55

     

    fragment_list

    먼저 다시 layout를 수정해주자

    상단의 버튼을 만들고 그 아래에 viewpager를 추가해준다

    더보기
    <?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">
    
        <TextView
            android:id="@+id/mini_title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#ECF0F1"
            android:padding="10dp"
            android:text="운동목록"
            android:textSize="25dp"
            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" />
    
        <LinearLayout
            android:id="@+id/linear"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="1dp"
            android:orientation="horizontal"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.0"
            app:layout_constraintStart_toStartOf="@id/mini_title"
            app:layout_constraintTop_toBottomOf="@+id/mini_title"
            app:layout_constraintVertical_bias="0">
    
            <Button
                android:id="@+id/btn1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="3dp"
                android:layout_weight="1"
                android:text="등" />
    
            <Button
                android:id="@+id/btn2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="3dp"
                android:layout_weight="1"
                android:text="가슴" />
    
            <Button
                android:id="@+id/btn3"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="3dp"
                android:layout_weight="1"
                android:text="어깨" />
    
            <Button
                android:id="@+id/btn4"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="3dp"
                android:layout_weight="1"
                android:text="하체" />
    
            <Button
                android:id="@+id/btn5"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="3dp"
                android:layout_weight="1"
                android:text="이두" />
    
            <Button
                android:id="@+id/btn6"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="3dp"
                android:layout_weight="1"
                android:text="삼두" />
        </LinearLayout>
    
        <androidx.viewpager.widget.ViewPager
            android:id="@+id/pager"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="1.0"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/linear"
            app:layout_constraintVertical_bias="0.0" />
    
    </androidx.constraintlayout.widget.ConstraintLayout>

    각각 버튼을 누르면 그 운동부위 리스트를 보여줄 예정이다

     

    listFragment_1~6

    제대로 된 방법을 발견하지 못해 하드코딩으로 한다

    각각 운동부위마다 listFragmet를 만들어서 viewpager가 로딩하게끔 한다

    더보기
    package com.lektion.gympartner;
    
    import android.content.ContentValues;
    import android.database.Cursor;
    import android.os.Bundle;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ListView;
    import android.widget.RelativeLayout;
    
    import androidx.annotation.Nullable;
    import androidx.fragment.app.Fragment;
    
    import com.lektion.gympartner.R;
    
    public class listFragment_1 extends Fragment {
    
        ListView exerciseList;
        ListViewAdapter_exercise adapter;
    
        public listFragment_1() {
            //?
        }
    
        @Override
        public void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
        }
    
        @Nullable
        @Override
        public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
            View view =  inflater.inflate(R.layout.viewfragment, container, false);
    
            adapter = new ListViewAdapter_exercise(getActivity());
    
            exerciseList = (ListView) view.findViewById(R.id.exerciseList);
            exerciseList.setAdapter(adapter);
    
            DatabaseManager databaseManager = DatabaseManager.getInstance(getContext());
            ContentValues addRowValue = new ContentValues();
    
            databaseManager.clearDB("exercise");
    
            addRowValue.put("name", "벤치프레스");
            addRowValue.put("category","가슴");
            addRowValue.put("tool","바벨");
    
            databaseManager.insert(addRowValue);
    
            addRowValue.put("name", "덤벨프레스");
            addRowValue.put("category","가슴");
            addRowValue.put("tool","덤벨");
    
            databaseManager.insert(addRowValue);
    
            addRowValue.put("name", "푸쉬업");
            addRowValue.put("category","가슴");
            addRowValue.put("tool","맨몸");
    
            databaseManager.insert(addRowValue);
    
            String[] columns = new String[] {"_id", "name", "category", "tool"};
    
            Cursor cursor = databaseManager.query(columns, null, null, null, null, null);
    
            if(cursor != null)
            {
                while(cursor.moveToNext())
                {
                    ListItem_exercise _data = new ListItem_exercise();
    
                    _data.setPreview(R.drawable.ic_no_image);
                    _data.setName(cursor.getString(1));
                    _data.setCategory(cursor.getString(2));
                    _data.setTool(cursor.getString(3));
    
                    adapter.listItems.add(_data);
                }
            }
    
            return view;
        }
    }

    리스트 추가는 똑같이 해준다

    또 각각의 layout를 만들어주어야 한다

    어차피 각기 다른게 없으니 그냥 layout은 하나만 만들어도 된다

     

    viewfragment.xml

    딱히 별건 없고 listview만 추가한다

    더보기
    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <ListView
            android:id="@+id/exerciseList"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:clipToPadding="false"
            android:paddingBottom="48dp" />
    
    </RelativeLayout>

     

    listFragment.java

    이제 메인 파일을 수정해주자

    아까도 말했듯이 적당한 방법을 찾지 못해 결국 하드코딩으로 만들었다

    각각 Fragment를 생성하고 각각 adapter에 추가하고 각각 버튼을 가져와서 각각 onClick를 넣어준다...

    더보기
    package com.lektion.gympartner;
    
    import android.os.Bundle;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.Button;
    import android.widget.FrameLayout;
    
    import androidx.annotation.NonNull;
    import androidx.annotation.Nullable;
    import androidx.fragment.app.Fragment;
    import androidx.fragment.app.FragmentActivity;
    import androidx.viewpager.widget.ViewPager;
    
    import java.util.ArrayList;
    
    public class listFragment extends Fragment {
    
    
        @Nullable
        @Override
        public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
            View view =  inflater.inflate(R.layout.fragment_list, container, false);
    
            ViewPager pager = view.findViewById(R.id.pager);
            pager.setOffscreenPageLimit(3);
    
            PagerAdapter adapter = new PagerAdapter(getActivity().getSupportFragmentManager(), 1);
    
            listFragment_1 f1 = new listFragment_1();
            listFragment_2 f2 = new listFragment_2();
            listFragment_3 f3 = new listFragment_3();
            listFragment_4 f4 = new listFragment_4();
            listFragment_5 f5 = new listFragment_5();
            listFragment_6 f6 = new listFragment_6();
    
            adapter.addItem(f1);
            adapter.addItem(f2);
            adapter.addItem(f3);
            adapter.addItem(f4);
            adapter.addItem(f5);
            adapter.addItem(f6);
    
            pager.setAdapter(adapter);
    
            Button b1 = view.findViewById(R.id.btn1);
            Button b2 = view.findViewById(R.id.btn2);
            Button b3 = view.findViewById(R.id.btn3);
            Button b4 = view.findViewById(R.id.btn4);
            Button b5 = view.findViewById(R.id.btn5);
            Button b6 = view.findViewById(R.id.btn6);
    
            b1.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    pager.setCurrentItem(0);
                }
            });
            b2.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    pager.setCurrentItem(1);
                }
            });
            b3.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    pager.setCurrentItem(2);
                }
            });
            b4.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    pager.setCurrentItem(3);
                }
            });
            b5.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    pager.setCurrentItem(4);
                }
            });
            b6.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    pager.setCurrentItem(5);
                }
            });
    
    
            return view;
        }
    
        @Override
        public void onResume() {
            FragmentActivity activity = getActivity();
            if(activity != null)
            {
                ((MainActivity) activity).setActionBarTitle("운동목록");
            }
            super.onResume();
        }
    }

     

    슬라이드로 이동하거나 버튼으로 이동할 수 있게 되었다

     

    까먹고 안한 운동도구도 리스트에 보이게 하자

     

    list_exercise.xml

    운동도구를 표시할 TextView 추가한다

    더보기
    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <androidx.appcompat.widget.LinearLayoutCompat
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:orientation="horizontal"
            tools:ignore="MissingConstraints">
    
            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:id="@+id/exerciseImage"
                android:src="@drawable/ic_no_image"
                android:layout_gravity="center"
                android:layout_margin="10dp"/>
    
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:id="@+id/exerciseName"
                android:text="운동이름"
                android:textSize="25dp"
                android:layout_gravity="center"
                android:layout_marginLeft="10dp"/>
    
            <View
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_weight="1" />
    
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:id="@+id/exerciseTool"
                android:layout_gravity="bottom"
                android:layout_margin="10dp"
                android:text="운동도구" />
    
        </androidx.appcompat.widget.LinearLayoutCompat>
    
    </androidx.constraintlayout.widget.ConstraintLayout>

    ListViewAdapter_exercise.java

    운동도구에 getTool를 통해 text를 지정한다

    더보기
    package com.lektion.gympartner;
    
    import android.content.Context;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.BaseAdapter;
    import android.widget.ImageView;
    import android.widget.TextView;
    
    import androidx.annotation.Nullable;
    
    import org.w3c.dom.Text;
    
    import java.util.ArrayList;
    
    public class ListViewAdapter_exercise extends BaseAdapter {
        private Context mContext;
        public ArrayList<ListItem_exercise> listItems = new ArrayList<>();
    
        public ListViewAdapter_exercise(Context context)
        {
            this.mContext = context;
        }
    
        @Override
        public int getCount() {
            return listItems.size();
        }
    
        @Override
        public Object getItem(int position) {
            return listItems.get(position);
        }
    
        @Override
        public long getItemId(int position) {
            return position;
        }
    
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            if(convertView == null)
            {
                LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                convertView = inflater.inflate(R.layout.list_exercise,parent,false);
            }
    
            ImageView image = (ImageView) convertView.findViewById(R.id.exerciseImage);
            TextView txt_name = (TextView) convertView.findViewById(R.id.exerciseName);
            TextView txt_tool = (TextView) convertView.findViewById(R.id.exerciseTool);
    
            ListItem_exercise listItem  = listItems.get(position);
    
            txt_name.setText(listItem.getName());
            txt_tool.setText(listItem.getTool());
            image.setImageResource(listItem.getPreview());
    
            return convertView;
        }
    
        public void addItem(String name, int preview )
        {
            ListItem_exercise listItem = new ListItem_exercise();
            listItem.setName(name);
            listItem.setPreview(preview);
    
            listItems.add(listItem);
        }
    
        public void modifyItem(int position,  String value)
        {
            ListItem_exercise listItem = listItems.get(position);
    
            listItem.setName(value);
        }
    
        public void removeItem(int position)
        {
            listItems.remove(position);
        }
    }

     

    정상적으로 표시되는 것을 확인

     

    대충이지만 운동목록을 만들었다

    검색은 나중에...

     

     

    다음엔 루틴을 만들어보자...