잡다로그

기존 뷰 상속받아 새로운 뷰 만들기 - 둘째 마당 7장 chapter02~03 본문

App/Android

기존 뷰 상속받아 새로운 뷰 만들기 - 둘째 마당 7장 chapter02~03

날으는다람쥐 2021. 2. 13. 20:35

공부 중 기억해야 할 부분을 기록하기 위한 글입니다. 참고하시고 공부를 위해서는 직접 책을 보시거나 강의를 들으시길 추천합니다 :) 

Do it! 안드로이드 앱 프로그래밍
국내도서
저자 : 정재곤
출판 : 이지스퍼블리싱 2020.01.23
상세보기

07-2 새로운 뷰 만들기

- API에서 제공하는 뷰를 사용해 내가 원하는 기능의 새로운 뷰를 정의하려면 API의 뷰를 상속해야 한다. 

- 개발자가 뷰의 상태에 따라 추가적인 코드를 넣어 뷰의 영역과 크기 등을 조절할 수 있도록 콜백 메서드가 호출된다. 

✔ onMeasure(): 뷰가 스스로의 크기를 정할 때 자동으로 호출되는 콜백 메서드. 뷰를 담고 있는 레이아웃에서 뷰에게 허용하는 여유 공간의 폭과 높이 정보가 파라미터로 전달된다. 

onDraw(): 뷰가 스스로를 레이아웃에 맞게 그릴 때 자동으로 호출되는 콜백 메서드. 

버튼 만들기 실습

1. 버튼 상속해서 새로운 Java 클래스 만들고 생성자 만들기

androix.appcompat.widget 패키지 안에 들어 있는 AppCompatButton에는 버튼을 위한 기능이 미리 정의되어 있다. 

public class MyButton extends AppCompatButton {

    public MyButton(Context context) {
        super(context);
    }

    public MyButton(Context context, AttributeSet attrs) {
        super(context, attrs);

    }

}

2. 뷰가 초기화 (재정의) 될 때 호출될 메서드 만들기

public class MyButton extends AppCompatButton {

    public MyButton(Context context) {
        super(context);

        init(context);
    }

    public MyButton(Context context, AttributeSet attrs) {
        super(context, attrs);

        init(context);
    }

    private void init(Context context) {	//기본 속성값을 지정
        setBackgroundColor(Color.CYAN);
        setTextColor(Color.BLACK);

        float textSize = getResources().getDimension(R.dimen.text_size);
        setTextSize(textSize);
    }

}

여기서 19번째 줄에서 textsize를 정하는데, setTextSize() 메서드를 이용하면 px(픽셀)단위만 설정할 수 있다. 글자 크기는 화면 크기별로 다르게 표현되는 sp단위를 사용하기 위해 XML 파일을 이용한다.  

픽셀 값으로 변환된 값을 반환하는 getDimension()메서드를 사용하여 /app/values/dimens.xml 에 정의된 값을 참조한다. 

//dimens.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <dimen name="text_size">16sp</dimen>
</resources>

3. 필요한 메서드를 정의한다 - onDraw() 와 onThouchEvent() 메서드를 정의한다.

public class MyButton extends AppCompatButton {

   ..중략..

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int action = event.getAction();
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                setBackgroundColor(Color.BLUE);
                setTextColor(Color.RED);

                break;
            case MotionEvent.ACTION_OUTSIDE:
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
                setBackgroundColor(Color.CYAN);
                setTextColor(Color.BLACK);

                break;
        }

        invalidate();

        return true;
    }

}

4. 새로 정의한 버튼 추가하기

이렇게 정의한 새로운 버튼은 XML레이아웃에(activity_main.xml) 추가하거나 소스 코드에서 new 연산자를 사용해 새로운 객체로 만든 후 레이아웃 객체의 addView() 메서드로 추가할 수 있다.

<RelativeLayout>

    <org.techtown.view.MyButton
        android:id="@+id/button"
        android:layout_width="200dp"
        android:layout_height="80dp"
        android:layout_centerInParent="true"
        android:text="시작하기" />

</RelativeLayout>

07-3 레이아웃 정의하고 카드뷰 넣기

- 뷰들을 담아두는 레이아웃은 하나의 XML 레이아웃 파일과 하나의 소스 파일로 구성된다. 

1. XML 레이아웃 파일 만들기

layout1.xml

2. 클래스 파일 만들고 생성자 추가하기

Layout1.java

3. XML 레이아웃 파일을 인플레이션하여 소스 파일(Java class)과 매칭 시키기

public class Layout1 extends LinearLayout {

    public Layout1(Context context) {
        super(context);
        init(context);
    }

    public Layout1(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    private void init(Context context) {
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        inflater.inflate(R.layout.layout1, this, true);
    }


}

LayoutInflater 객체의 inflate() 메서드를 호출하면서 XML 레이아웃 파일을 파라미터로 전달하면 인플레이션이 진행되면서 소스 파일에 설정된다. 

4. 뷰를 찾아 원하는 동작 코딩하기

인플레이션이 끝나면 findViewById() 메서드로 레이아웃 파일에 넣어둔 뷰를 참조할 수 있다. 

5. 제작한 레이아웃을 상속한 새로운 뷰(Layout1.java)를 메인 액티비티에 추가한다. 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout >

    <Button />    
     ..중략..

    <org.techtown.layout.Layout1
        android:id="@+id/layout1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
        
</LinearLayout>

6. 메인에 추가된 Layout1 뷰에 이미지나 글자를 소스 코드에서 추가한다.

MainActivity.java 파일에서 Layout1 뷰를 찾아 참조할 수 있도록 id값을 layout1으로 부여한다.

public class MainActivity extends AppCompatActivity {
    Layout1 layout1;

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

        layout1 = findViewById(R.id.layout1);
        layout1.setImage(R.drawable.profile1);
        layout1.setName("김민수");
        layout1.setMobile("010-1000-1000");

        Button button = findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                layout1.setImage(R.drawable.profile1);
            }
        });

        Button button2 = findViewById(R.id.button2);
        button2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                layout1.setImage(R.drawable.profile2);
            }
        });

    }
}

새로운 뷰 안에 들어있는 이미지나 텍스트뷰의 속성을 바꾸기 위해 메서드를 정의하고 뷰 바깥에서 그 메서드를 호출하면 이미지나 글자를 바꿀 수 있다.

7. 새로 만든 레이아웃의 모양을 카드뷰 모양으로 바꾸려면 원본 XML을 수정한다. 

카드뷰는 다른 뷰들을 담고 있는 레이아웃의 테두리를 카드 모양으로 둥글게 바꿔준다.

새로 만든 layout1.xml 이 CardView 태그 안에 들어가도록 한다. 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout >

    <androidx.cardview.widget.CardView >

        <LinearLayout>
            <ImageView />
            <LinearLayout >
                <TextView />
                <TextView />
            </LinearLayout>
        </LinearLayout>

    </androidx.cardview.widget.CardView>

</LinearLayout>

 

Comments