국비교육(22-23)

117일차(2)/Android App(74) : Wearable App 예제(1)

서리/Seori 2023. 3. 29. 01:33

117일차(2)/Android App(74) : Wearable App 예제(1)

 

 

- Android Studio 에서 새 가상기기(Wear OS) 만들기

 

 

- 디바이스 관리-새 디바이스 생성하기

 

 

- Wear OS를 선택해준다.

 

- Wear OS Square : 화면이 사각형인 것

- Wear OS Round : 화면이 동그란 것

 

- 시계 화면 모양을 기준으로 가상기기를 생성한다.

 

 

- round를 선택해줌!

 

 

- 두번째 R을 다운받아주기!

- 맨 위의 것은 China Version 이라 언어가 중국어로 나온다.

 

 

- 이렇게 Wearable device의 가상기기를 만들 수 있다.

- 가상기기 생성에 시간이 오래 걸리므로 모듈을 생성하기 전에 만들어 놓으면 좋다.

 

- Wear OS 도 Android와 비슷하다. 모바일 앱과 크게 다르지 않다!

- 작은 화면이라 레이아웃을 구성하는 것만 좀 다를 뿐..

 

 

- 생성이 완료되면 Finish

 

 

- 가상기기의 이름, 기본 방향 등을 정해주면 완료된다.

 

 

- 생성된 가상기기이다.

- 위=>아래로 스크롤 : 설정 정보

 우측으로 스크롤 : 알림 센터

 아래=>위로 스크롤 알림

 좌측으로 스크롤 : 동그란 스탑워치?같은 창 나옴

 

 

- 좌측에서 나오는 창!

 

- 설정:연결, 디스플레이, 제스처, 진동, 보안, 시스템... 등등이 있다.

 

- 시계에서 뒤로가기 기능(백 버튼)을 사용하고 싶다면 보통 우측으로 드래그하면 된다.

 


 

- Wear용 새 모듈 생성

step26wear

 

 

- WearOS 시계를 선택

 

 

- wear의 액티비티 선택 창 : Blank Activity로 선택

 

 

- 시계는 주로 다른 모바일 기기와 페어링해서 쓴다.

- 가상기기 메뉴에서 페어링 관련된 옵션을 제공하고 있다.

- 실 기기로도, 다른 가상기기로도 페어링 가능!

 

 

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.wear.widget.BoxInsetLayout 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:padding="@dimen/box_inset_layout_padding"
    tools:context=".MainActivity"
    tools:deviceIds="wear">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="@dimen/inner_frame_layout_padding"
        app:layout_boxedEdges="all"
        android:orientation="vertical">

        <TextView
            android:id="@+id/text"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@string/hello_world"
            android:textAlignment="center"
            android:textColor="#00ff00"/>
        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="눌러보셈"
            android:id="@+id/myBtn"/>
    </LinearLayout>
</androidx.wear.widget.BoxInsetLayout>

 

 

- 제일 바깥쪽의 BoxInsetLayout 안에 FrameLayout이 들어있다.

 

- 기본값으로 어느정도 padding을 준 것을 확인 가능

 

 

- Wear에서는 크기에 관련된 설정값들을 xml문서로 정리해 두었다.

 

 

- 들어가보면 boxInset의 padding, frameLayout의 padding이 각각 0dp, 5dp라고 지정되어 있다.

 

 

- 사각형인 경우에는 레이아웃을 적당히 맞도록 배치해도 되는데,

 

 

- 스크린이 원형인 경우에는 위와 같이 잘리는 부분들이 생긴다. 그 부분을 감안해 padding을 준 것이다.

 

 

- 원형 안에 잘리는 내용 없이 바로 배치할 수 있도록 padding을 부여한 부분!

 

 

 

MainActivity

package com.example.step26wear;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

import com.example.step26wear.databinding.ActivityMainBinding;

public class MainActivity extends Activity {

    private TextView mTextView;
    private ActivityMainBinding binding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //바인딩 객체를 얻어내고
        binding = ActivityMainBinding.inflate(getLayoutInflater());
        //바인딩 객체를 이용해서 화면 구성을 하고
        setContentView(binding.getRoot());
        //TextView의 참조값을 얻어와서 필드에 저장
        mTextView = binding.text;

        //버튼에 리스너 등록
        binding.myBtn.setOnClickListener(v -> {
            //TextView 조작하기
            binding.text.setText("Clicked!");
        });
    }
}

 

 

- 기본적으로 뷰 바인딩을 사용한다.

- 액티비티의 두 단어를 거꾸로 조합한 바인딩 객체가 자동으로 생긴다.

 

 

- 이 기본 앱을 run해보기!

 

 

- 이렇게 기본 화면이 나타남!

 

 

- 패딩을 이렇게 사방으로 5dp씩 가지고 있다. 그래서 알아서 레이아웃 배치를 해준다.

- 레이아웃은 사각형 시계 쪽이 쉽다.

 

 

- values>strings 폴더 안에 앱 안에 들어갈 글자를 따로 배치해 놓았다.

 

 

- 이것을 프로젝트로 바꿔서 보면 프로젝트 구조를 보기가 좀 더 쉽다.

 (필요한 것만 보려면 android로 보면 된다)

 

 

- src 안에서 코딩하면 된다. 똑같다!

 

 

- res 에 values 폴더가 2개 있다.

- values 폴더(디폴트)는 사각형 시계일때 사용하는 자원

  values-round 는 동그란 화면일때 가져다 쓰는 자원! 폴더명 자체가 다르다.

 

 

- activity_main.xml 수정하기

 

 

- 리니어 레이아웃으로 바꿔도 똑같다. 위에서 쌓이는 구조로 바뀌었다.

 

 

- 버튼을 만들면 이렇게 출력된다.

- box inset을 쓰고 기본 padding이 들어있다는 것만 아니면 일반 안드로이드의 코딩과 별 차이가 없다.

 

 

- 버튼에 리스너 등록

 

 

- 안드로이드의 "텍스트" 가운데 정렬은 text-Alignment 사용

- 다른 요소들은 gravity를 사용

 

 

 

 

- 버튼을 클릭하면 버튼 위의 input에 Clicked! 가 표시되도록 만들어보았다.

 

 


 

- 새 모듈 생성

step26listview

 

 

- WearOS로 생성하기

 

 

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.wear.widget.BoxInsetLayout 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:padding="@dimen/box_inset_layout_padding"
    tools:context=".MainActivity"
    tools:deviceIds="wear">

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="@dimen/inner_frame_layout_padding"
        app:layout_boxedEdges="all">

        <androidx.wear.widget.WearableRecyclerView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/recyView"
            android:scrollbars="vertical"/>

    </FrameLayout>
</androidx.wear.widget.BoxInsetLayout>

 

<androidx.wear.widget.WearableRecyclerView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/recyView"
            android:scrollbars="vertical"/>

 

- FrameLayout 안에 이렇게 WearableRecyclerView 요소를 작성해주기

- 스크롤바는 수직으로!

 

 

 

MainActivity

package com.example.step26listview;

import android.app.Activity;
import android.os.Bundle;

import androidx.wear.widget.WearableLinearLayoutManager;
import androidx.wear.widget.WearableRecyclerView;

import com.example.step26listview.databinding.ActivityMainBinding;

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

public class MainActivity extends Activity {

    private ActivityMainBinding binding;

    WearableRecyclerView recyView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        binding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

        recyView=binding.recyView;

        //아이템이 가운데 정렬되도록 설정
        recyView.setEdgeItemsCenteringEnabled(true);
        //레이아웃 매니저 설정
        recyView.setLayoutManager(new WearableLinearLayoutManager(this));

        //출력할 Data(모델)
        List<String> names=new ArrayList<>();
        names.add("바나나");
        names.add("딸기");
        names.add("복숭아");
        names.add("사과");
        names.add("오렌지");
        names.add("무화과");
        names.add("포도");
        names.add("레몬");
        names.add("라임");
        //RecyclerView에 연결할 아답타 객체 생성
        RecyAdapter adapter=new RecyAdapter(names);
        //RecyclerView에 아답타 연결
        recyView.setAdapter(adapter);

        recyView.setHasFixedSize(true);
    }
}

 

 

- recyView 바인딩 해주기

 

 

//아이템이 가운데 정렬되도록 설정
recyView.setEdgeItemsCenteringEnabled(true);
//레이아웃 매니저 설정
recyView.setLayoutManager(new WearableLinearLayoutManager(this));

 

- 아이템이 가운데 오도록 설정해 주어야 한다.

- 원형에는 잘리는 부분이 생기므로 필요!

 

 

- 이런 형태로 RecyclerView에 친구목록을 출력하고, 클릭하면 정보를 보여주도록 할 것이다!

 

 

 

- 리스트뷰를 사용하는 것이라고 생각하기! 구조는 똑같다.

- 데이터를 아답타에, 아답타를 RecyclerView에 연결하면 데이터가 View에 출력된다.

 

 

RecyAdapter

package com.example.step26listview;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import java.util.List;

public class RecyAdapter extends RecyclerView.Adapter<RecyAdapter.ViewHolder> {

    //모델
    private List<String> localDataSet;

    //생성자의 인자로 모델을 전달받아서 필드에 저장
    public RecyAdapter(List<String> dataSet){
        localDataSet=dataSet;
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        //res/layout/cell.xml 문서를 전개해서 View 객체를 만들고
        View view= LayoutInflater.from(parent.getContext())
                .inflate(R.layout.cell, parent, false);
        //해당 View 객체를 이용해서 ViewHolder 객체를 생성해서 리턴한다.
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        //ViewHolder가 가지고있는 TextView의 참조값을 얻어와서
        //position에 해당하는 데이터를 출력한다.
        holder.getTextView().setText(localDataSet.get(position));
    }

    @Override
    public int getItemCount() {
        //모델의 개수를 리턴
        return localDataSet.size();
    }

    //ViewHolder 내부 클래스
    public static class ViewHolder extends RecyclerView.ViewHolder {
        private final TextView textView;

        public ViewHolder(View view) {
            super(view);
            textView = (TextView) view.findViewById(R.id.textView);
        }

        public TextView getTextView() {
            return textView;
        }
    }

}

 

 

- RecyclerView.Adapter<> 를 상속받아서 만든 아답타!

 

 

- 이 Adapter 안에서 클래스를 정의한다.

- static 클래스를 하나 만들어주고, RecyclerView.Adapter<> 의 제네릭 타입을 정의한다.

 

- 필요한 추상메소드도 오버라이드!

 

- 연결할 텍스트뷰를 하나 만들어 주어야 한다.(ListView의 cell역할)

 

 

- layout-new-LayoutResource File 으로 생성

 

 

- 리니어 레이아웃으로 cell 생성

 

cell.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/textView"
        android:textAlignment="center"/>
</LinearLayout>

 

 

- 이것이 시계에서 하나하나 돌리면서 보여줄 셀이 된다.

 

 

- 생성자의 인자로 모델을 전달받아서 필드에 넣는다.

- ViewHolder 객체를 만들어서 리턴해준다.

 

 

- onCreateViewHolder 안에서 cell을 전개해서 View를 만들고, 리턴해서 나온 값을 ViewHolder 내부클래스에 전달한다

 

 

 

- 아래 메소드를 사용해서 값을 얻어오는 것이다.

 (private로 되어있어서 필드에 직접 접근할 수가 없다)

 

 

- 리스트의 친구들(아이템)이 회전되어 하나씩 보인다.

 

recyView.setHasFixedSize(true);

 

- RecyclerView 안의 아이템의 크기를 일정하게 한다(크기 명시하기)

- 이렇게 명시해두면 매번 새로 그리는 (성능이 떨어지는) 작업을 하지않아도 된다.

 

 

 

- 이렇게 리스트를 출력해준다.

 

- 화면이 좁아서 UI가 특이한 편이다. UI 사용법만 잘 익히면 안드로이드 앱과 큰 차이가 없다.