2025-04-14 23:40:41

안드로이드 커스텀 뷰 요소 만들기

java 코드

package com.inhatc.mobile_programming_practice;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;

public class imgAndroiView extends View {

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

 

 

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:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:textAlignment="center"
    tools:context=".MainActivity">

    <com.inhatc.mobile_programming_practice.imgAndroiView
        android:id="@+id/imgAndroiView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="4dp"
        android:layout_marginTop="4dp"
        android:focusable="true"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@drawable/img_androi" />

</androidx.constraintlayout.widget.ConstraintLayout>

 

 

핵심 포인트

xml 코드의 ImageView를 패키지명.클래스명 으로 설정해주면 커스텀 요소를 사용 가능하다!

 

 

예제 1) 이미지를 화면의 중앙에 오도록 설정하기

 

package com.inhatc.mobile_programming_practice;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;

import androidx.annotation.NonNull;

public class imgAndroiView extends View {

    Drawable imgAndroiView;
    int ix, iy, imgWidth, imgHeight;

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

        imgAndroiView = this.getResources().getDrawable(R.drawable.img_androi);
        imgWidth = imgAndroiView.getIntrinsicWidth();
        imgHeight = imgAndroiView.getIntrinsicHeight();

        ix = 0;
        iy = 0;
    }

    @Override
    public void onDraw(@NonNull Canvas canvas)
    {
        imgAndroiView.setBounds(ix, iy, ix + imgWidth, iy + imgHeight);
        imgAndroiView.draw(canvas);

        super.onDraw(canvas);
    }

    @Override
    public void onSizeChanged(int x, int y, int oldx, int oldy)
    {
        ix = (x - imgWidth) / 2;
        iy = (y - imgHeight) / 2;

        super.onSizeChanged(x, y, oldx, oldy);
    }
}

 

결과

 

핵심 포인트

뷰 요소.getIntrinsicWidth / Height  : 해당 요소의 Width값 / Height 값을 가져오는 메서드

ix = (x - imgWidth) / 2 : 뷰의 중앙에 이미지를 위치시키는 방법.

x 대신 getWidth() 메서드를 사용해도 무관하다.

 

예제 2) 방향키 입력을 통해 이미지 이동시키기

 

java 코드

package com.inhatc.mobile_programming_practice;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.View;
import android.widget.ImageView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

public class imgAndroiView extends View {

    Drawable imgAndroiView;
    int ix, iy, imgWidth, imgHeight;

    public imgAndroiView(Context context, AttributeSet attrs) { ... }

    @Override
    public void onDraw(@NonNull Canvas canvas)
    { ... }

    @Override
    public void onSizeChanged(int x, int y, int oldx, int oldy)
    { ... }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        switch(keyCode)
        {
            case KeyEvent.KEYCODE_DPAD_LEFT:
                ix -= 15;
                if (ix <= 0) ix = 0;
                break;
            case KeyEvent.KEYCODE_DPAD_RIGHT:
                ix += 15;
                if (ix >= getWidth() - imgWidth) ix = getWidth() - imgWidth;
                break;
            case KeyEvent.KEYCODE_DPAD_DOWN:
                iy += 15;
                if (iy >= getHeight() - imgHeight) iy = getHeight() - imgHeight;
                break;
            case KeyEvent.KEYCODE_DPAD_UP:
                iy -= 15;
                if (iy <= 0) iy = 0;
                break;
        }

        this.invalidate();
        return super.onKeyDown(keyCode, event);
    }
}

 

핵심 포인트

뷰의 좌측 상단이 (0, 0) 이므로 좌측으로 이동하면 x를 감소, 우측으로 이동하면 x를 증가

상단으로 움직이려면 y를 감소, 하단으로 움직이려면 y를 증가시키면 된다.

 

또한 이미지의 좌표도 좌측 상단이 (0, 0) 이므로 우측 혹은 하단으로 나가지 못하게 하려면 조건에 이미지의 두께 / 너비를 더해주어야 한다.

 

예제 3 ) 클릭하면 이미지를 해당 위치로 이동시키기

 java 코드

package com.inhatc.mobile_programming_practice;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

public class imgAndroiView extends View { ... }

    @Override
    public void onDraw(@NonNull Canvas canvas)
    { ... }

    @Override
    public void onSizeChanged(int x, int y, int oldx, int oldy)
    { ... }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) { ... }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        ix = (int)event.getX();
        iy = (int)event.getY();
        return super.onTouchEvent(event);
    }
}