본문 바로가기
교육 정리/안드로이드 앱 제작(Java)

4일차. 그래픽과 이미지

by Jint 2022. 10. 29.

버츄얼 디바이스 켜기


1. 커스텀 뷰
Graphic1_CustomView_basic1 프로젝트 만들기

※ 사용자 뷰(커스텀 뷰)
1) View 클래스를 상속받아 구현한다.
- 생성자가 반드시 있어야 한다.
생성자1(Context context) - 자바만
생성자2(Context context, AttributeSet attrs) - xml 파일 존재할 때 AttributeSet 객체 필요하다.
- onDraw(Canvas canvas) 메서드를 오버라이딩해서 구현
- onTouchEvent(MotionEvent event) 메서드 오버라이딩해서 구현 
- 필요시 Thread 구현
2) XML에 등록 - AttributeSet attrs 객체가 있는 View(클래스)만 가능
3) Java에서 - setContentView(myView);

- MainActivity.java

package com.example.graphic1_customview_basic1;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;

//View 클래스 상속받아 구현
class MyView extends View {

    int x = 300, y = 100;
    int r, g, b;

    /**
     * 생성자
     * @param context
     * @param a
     * @param y
     */
    public MyView(Context context, int a, int y) {
        super(context);
        this.y += b;
        //색상 추가
        setBackgroundColor(Color.argb(20,50,80,180));
    }

    /**
     * 그리기 - 그래픽
     * canvas : 그림판 - 도형, 이미지, 글자
     * paint : 그리기 도구
     * @param canvas
     */
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //그리기 도구 - Paint 객체생성
        Paint paint = new Paint();

        //랜덤색상 출력
        r  = (int)(Math.random() * 256);
        g = (int)(Math.random() * 256);
        b = (int)(Math.random() * 256);

        //paint 설정
        /*
        - Paint 객체 메서드
          setColor() : 색
          setStrokeWidth() : 선 두께
          setTextSize() : 글자크기
          setAntiAlias(true/false) : 경계선을 부드럽게 처리
          setStyle(Paint.Style.FILL/STROKE/FILL_AND_STROKE) 등
         */
        paint.setColor(Color.rgb(r, g, b));
        paint.setStyle(Paint.Style.STROKE); //Paint.Style.FILL은 채우기
        paint.setStrokeWidth(7); //선의 굵기

        //도형그리기
        /*
        - 점 그리기 : drawPoint(x, y, paint);
        - 직선 그리기 : drawLine(x1, y1, x2, y2, paint);
        - 원 그리기 : drawCircle(중심x, 중심y, 반지름, paint);
        - 원호 그리기 : drawAct(new RectF(x1, y1, x2, y2)내접원, 시작각, 회전각, 중심점사용여부(false), paint);
        - 사각형 그리기 : drawRect(좌상x, 좌상y, 우하x, 우하y, paint);
        - 둥근사각형 그리기 : drawRoundRect(Rect rect, 모서리사각형너비(width), 모서리사각형높이(height), paint);
        - 글자 그리기 : drawText(글자문자열, x, y, paint);
        - 기하학적인 도형 : drawPath(Path path, paint);
          path.moveTo(x, y) : 이동
          path.lineTo(x, y) : 연결해가는 그리기
         */
        canvas.drawCircle(x - 100 , y + 70,80, paint); //원
        canvas.drawArc(new RectF(700,400, 1000,700), 45, 320, true, paint); //원호
   
        //글자쓰기
        paint.setTextSize(50);
        Typeface t = Typeface.create(Typeface.SANS_SERIF, Typeface.ITALIC); //폰트 타입객체 생성
        paint.setTypeface(t); //폰트 타입설정
        canvas.drawText("안드로이드",500,200, paint);

        //경로그리기
        Path path = new Path();
        path.moveTo(500,500);
        path.lineTo(700,700);
        path.lineTo(500,700);
        path.lineTo(500,500);
        canvas.drawPath(path, paint);
        canvas.drawRect(x, y,x+150,y+150, paint);

        //화면을 다시 그리기
        invalidate();

        //스레드를 통해 인터벌 주기
        try {
            Thread.sleep(500);
        }catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * 터치이벤트 추가
     * @param event
     * @return
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        //바닥에 닫으면 맨 위로 좌표 이동
        if(this.getHeight() > y) {
            y = y + 100; //100씩 이동
        }else {
            y = 0;
        }
        return false;
    }

}

public class MainActivity extends AppCompatActivity {

    int x = 0, y = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //사용자 뷰 객체 적용
        MyView w = new MyView(this,50,50);
        setContentView(w);
    }

}

Graphic1_CustomView_basic1 프로젝트 결과 화면

 

 

2. 커스텀 뷰2
Graphic2_CustomView_basic2 프로젝트 만들기

그림판 작성
※ 옵션메뉴 추가
※ 커스텀 뷰를 내부 클래스로 적용
※ 터치이벤트 처리

- MainActivity.java

package com.example.graphic2_customview_basic2;

import static android.graphics.drawable.GradientDrawable.LINE;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.SubMenu;
import android.view.View;

public class MainActivity extends AppCompatActivity {

    final static int LINE = 1, CYCLE = 2, RECT = 3;
    static int shape = LINE;
    static Paint paint = new Paint();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        MyView myView = new MyView(this);
        setContentView(myView);
        setTitle("그림판");
    }

    /**
     * 커스텀 뷰 - 내부클래스
     */
    class MyView  extends View {

        int startX = -1, startY= -1, stopX = -1, stopY = -1 ;

        /**
         * 생성자
         * @param context
         */
        public MyView(Context context){
            super(context);
        }

        /**
         * 그래픽 그리기
         * @param canvas
         */
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);

            paint.setAntiAlias(true);
            paint.setStrokeWidth(5);
            paint.setStyle(Paint.Style.FILL_AND_STROKE);

            switch (shape){
                case LINE:
                    canvas.drawLine(startX, startY, stopX, stopY,paint);
                    break;
                case CYCLE:
                    int radius = (int) Math.sqrt(Math.pow(stopX-startX,2)+Math.pow(stopY - startX, 2));
                    canvas.drawCircle(startX,startY,radius,paint);
                    break;
                case RECT:
                    canvas.drawRect(startX,startY,startX+ Math.abs((stopX-startX)), startY+Math.abs((stopY-startX)), paint);
            }
        }

        /**
         * 터치이벤트 추가
         * @param event
         * @return
         */
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            switch(event.getAction()) {//액션값 읽어오기
                //눌렀을 때
                case MotionEvent.ACTION_DOWN:
                    startX = (int)event.getX();
                    startY = (int)event.getY();
                    break;
                //누르고 이동
                case MotionEvent.ACTION_MOVE:
                //뗐을 때
                case MotionEvent.ACTION_UP:
                    stopX = (int)event.getX();
                    stopY = (int)event.getY();
                    //다시 그려준다.
                    this.invalidate();
                    break;
            }
            return true;
        }
    }

    //-----------------------------------------------------------------------------------------------------------------------------

    /*
    - 옵션메뉴를 작성한다.
    1) 메뉴를 구현 : onCreateOptionsMenu(Menu menu) 메서드 오버라이딩 구현
    2) 메뉴가 선택되었을 때 할 일 : onOptionsItemSelected(@NonNull MenuItem item) 오버라이딩 구현
     */

    /**
     * 메뉴 구현
     * @param menu
     * @return
     */
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);
        //add(그룹ID, itemID, orderID); -> getGroupId(), getItemId(), getOrderId()
        //메인 메뉴
        menu.add(0, 1, 0, "선 그리기");
        menu.add(0, 2,0,"원 그리기");
        menu.add(0, 3,0,"사각형그리기");
        //서브 메뉴 - Menu 객체 생성해서 추가한다.
        Menu sub = menu.addSubMenu("색상변경");
        sub.add(1,4,1,"빨강");
        sub.add(1,4,2,"초록");
        sub.add(1,4,3,"파랑");
        return true;
    }

    /**
     * 메뉴선택시 이벤트처리
     * @param item
     * @return
     */
    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        switch(item.getItemId()) {
            case 1:
                shape = LINE; //shape변수값을 LINE으로 변경
                return true;
            case 2:
                shape = CYCLE; //원
                return true;
            case 3:
                shape = RECT; //사각형
                return true;
            case 4:
                if(item.getOrder() == 1) {
                    paint.setColor(Color.RED);
                }else if(item.getOrder() == 2) {
                    paint.setColor(Color.GREEN);
                }else if(item.getOrder() == 3) {
                    paint.setColor(Color.BLUE);
                }
                break;
        }
        return super.onOptionsItemSelected(item);
    }

}

Graphic2_CustomView_basic2 프로젝트 결과 화면

 

 

3. 커스텀 뷰3 : XML 가져오기 - AttributeSet
Graphic3_CustomView_SeeInXML 프로젝트 만들기

- activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    
    <!--자바로 작성된 클래스를 가져와 구현-->
    <com.example.graphic3_customview_seeinxml.CustomView
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

 

- MainActivity.java

package com.example.graphic3_customview_seeinxml;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

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

}

 

- CustomView.java

package com.example.graphic3_customview_seeinxml;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

public class CustomView  extends View {

    /**
     * 생성자1
     * @param context
     */
    public CustomView(Context context) {
        super(context);
        setBackgroundColor(Color.YELLOW);
    }

    /**
     * 생성자2 - XML에서 구현할 생성자
     * @param context
     * @param attrs
     */
    public CustomView(Context context, AttributeSet attrs) {
        super(context);
        setBackgroundColor(Color.YELLOW);
    }

    //그리기
    float x = 0, y = 0;
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Paint paint = new Paint();
        paint.setColor(Color.RED);
        canvas.drawArc(new RectF(50 + x, 50 + y , 600 + x, 600 + y), 45, 300 - (int)x, true, paint);
        invalidate();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
         x = event.getX();
         y = event.getY();
        return true;
    }

}

Graphic3_CustomView_SeeInXML 프로젝트 결과 화면

 

 

4. 커스텀 뷰4 : 그림판 만들기
Graphic4_CustomView_DrawEX 프로젝트 만들기

res/drawable 경로에 brush.png, eraser.png, new_pic.png, save.png 사진 파일 넣기

- activity_main.xml

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

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="#FFCCCCCC">

    <include layout="@layout/myframe"/>

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal">
        <ImageButton
            android:src="@drawable/new_pic"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
        <ImageButton
            android:src="@drawable/brush"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
        <ImageButton
            android:src="@drawable/eraser"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
        <ImageButton
            android:src="@drawable/save"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
    </LinearLayout>

    <com.example.graphic4_customview_drawex.MyTouchView
        android:id="@+id/drawing"
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:background="#FFFFFFFF"/>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:gravity="center_horizontal">

        <LinearLayout
            android:id="@+id/paint_colors"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:layout_gravity="center_horizontal"
            android:gravity="center_horizontal">

            <ImageButton
                android:layout_width="30dp"
                android:layout_height="30dp"
                android:layout_marginRight="5dp"
                android:background="#FF000000"
                android:tag="#FF000000"
                android:onClick="clicked"/>

            <ImageButton
                android:layout_width="30dp"
                android:layout_height="30dp"
                android:layout_marginRight="5dp"
                android:background="#FFFF0000"
                android:tag="#FFFF0000"
                android:onClick="clicked"/>

            <ImageButton
                android:layout_width="30dp"
                android:layout_height="30dp"
                android:layout_marginRight="5dp"
                android:background="#FFFF6600"
                android:tag="#FFFF6600"
                android:onClick="clicked"/>

            <ImageButton
                android:layout_width="30dp"
                android:layout_height="30dp"
                android:layout_marginRight="5dp"
                android:background="#FFFFCC00"
                android:tag="#FFFFCC00"
                android:onClick="clicked"/>

            <ImageButton
                android:layout_width="30dp"
                android:layout_height="30dp"
                android:layout_marginRight="5dp"
                android:background="#FF009900"
                android:tag="#FF009900"
                android:onClick="clicked"/>

            <ImageButton
                android:layout_width="30dp"
                android:layout_height="30dp"
                android:layout_marginRight="5dp"
                android:background="#FFFFFFFF"
                android:tag="#FFFFFFFF"
                android:onClick="clicked"/>

        </LinearLayout>

    </LinearLayout>

</LinearLayout>

 

- myframe.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:background="#ffffff">

      <!--텍스트뷰를 추가 : style을 만들어서 적용해보자-->
      <TextView style="@style/myTextView"/>

</LinearLayout>

 

- res/values/myTextViewStyle.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="myTextView" >
        <!--<item name="속성명">속성값</item>-->
        <item name="android:layout_width">wrap_content</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="android:text">"그림판"</item>
        <item name="android:textColor">@color/title</item>
        <item name="android:textSize">30sp</item>
        <item name="android:textStyle">bold</item>
        <item name="android:layout_gravity">center</item>
        <item name="android:layout_marginTop">3dp</item>
        <item name="android:layout_marginBottom">3dp</item>
    </style>
</resources>

 

- res/values/colors.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="purple_200">#FFBB86FC</color>
    <color name="purple_500">#FF6200EE</color>
    <color name="purple_700">#FF3700B3</color>
    <color name="teal_200">#FF03DAC5</color>
    <color name="teal_700">#FF018786</color>
    <color name="black">#FF000000</color>
    <color name="white">#FFFFFFFF</color>
    <!--내가만든 색상-->
    <color name="title">#3F51B5</color>
</resources>

 

- res/values/a.xml

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

<!-- 연습용  스타일이다.. 삭제해도 무방하다-->
<resources>
    <style name="myButton">
        <item name="android:layout_width">wrap_content</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="android:text">내가만든버튼</item>
    </style>
</resources>

 

- MyTouchView.java

package com.example.graphic4_customview_drawex;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

public class MyTouchView extends View {

    public Paint paint = new Paint();
    private Path path = new Path();
    private int paintColor = 0xFF000000;
    private Paint canvasPaint;
    private Canvas drawCanvas;
    private Bitmap canvasBitmap;

    /**
     * 생성자1
     * @param context
     */
    public MyTouchView(Context context){super(context);}

    /**
     * 생성자2 - XML에서 구현할 생성자
     * @param context
     * @param attrs
     */
    public MyTouchView(Context context, AttributeSet attrs) {
        super(context, attrs);
        paint.setAntiAlias(true);
        paint.setStrokeWidth(10f);
        paint.setColor(paintColor);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeJoin(Paint.Join.ROUND);
    }

    /**
     * 크기가 변화되면 호출되는 메서드
     * @param w
     * @param h
     * @param oldw
     * @param oldh
     */
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        //그림판 캔버스 생성
        canvasBitmap = Bitmap.createBitmap(w,h,Bitmap.Config.ARGB_8888);
        drawCanvas = new Canvas(canvasBitmap);
        canvasPaint =  new Paint(Paint.DITHER_FLAG);
    }

    /**
     * 그래픽
     * @param canvas
     */
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        canvas.drawBitmap(canvasBitmap,0,0,canvasPaint);
        canvas.drawPath(path,paint);
    }

    /**
     * 터치이벤트
     * @param event
     * @return
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float touchX = event.getX();
        float touchY = event.getY();
        switch(event.getAction()) {//getAction() 액션값 가져옴
            //손가락으로 누르면
            case MotionEvent.ACTION_DOWN:
                path.moveTo(touchX, touchY); //이동
                break;
            //이동하면
            case MotionEvent.ACTION_MOVE:
                path.lineTo(touchX,touchY); //그려라
                break;
            //손가락 떼면
            case MotionEvent.ACTION_UP:
                drawCanvas.drawPath(path, paint); //그림 그리고 나서
                path.reset(); //지워라
            default:
                return false;
        }
        invalidate();
        return true;
    }

    /**
     * 컬러설정 메서드 구현
     * @param newColor
     */
    public void setColor(String newColor) {
        invalidate();
        paintColor = Color.parseColor(newColor); //색상값 저장
        paint.setColor(paintColor);
    }

}

 

- MainActivity.java

package com.example.graphic4_customview_drawex;

import androidx.appcompat.app.AppCompatActivity;

import android.graphics.Paint;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageButton;
import android.widget.LinearLayout;

public class MainActivity extends AppCompatActivity {

    MyTouchView myDrawView;
    ImageButton currPaint, erasePaint;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        myDrawView = (MyTouchView) findViewById(R.id.drawing);
        LinearLayout paintLayout = (LinearLayout) findViewById(R.id.paint_colors);
        currPaint = (ImageButton) paintLayout.getChildAt(0);
        erasePaint = (ImageButton) paintLayout.getChildAt(5);
    }

    public void clicked(View view) {
        if(view != currPaint) {
            String color = view.getTag().toString();

            if(view == erasePaint) {
                myDrawView.paint.setStrokeWidth(80f);
            }
            else {
                myDrawView.paint.setStrokeWidth(10f);
            }
            myDrawView.setColor(color);
            currPaint = (ImageButton) view;
        }
    }

}

Graphic4_CustomView_DrawEX 프로젝트 결과 화면

 

 

5. 이미지 그리기 : AttributeSet 객체가 아닌 레이아웃에 추가
Image1_basic 프로젝트 만들기

res/drawable 경로에 left.png, lena.png, minus.png, plus.png, right.png 사진 파일 넣기

- activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical"
    android:gravity="center">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:gravity="center"
        android:background="#DAD8D8">
        <ImageButton
            android:id="@+id/imageButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="expand"
            app:srcCompat="@drawable/plus"/>

        <ImageButton
            android:id="@+id/imageButton2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="shrink"
            app:srcCompat="@drawable/minus"/>

        <ImageButton
            android:id="@+id/imageButton3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="rotateLeft"
            app:srcCompat="@drawable/left"/>

        <ImageButton
            android:id="@+id/imageButton4"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="rotateRight"
            app:srcCompat="@drawable/right"/>
    </LinearLayout>

    <LinearLayout
        android:id="@+id/imageDisplay"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:gravity="center">
    </LinearLayout>

</LinearLayout>

 

- MainActivity.java

package com.example.image1_basic;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;

/*
이미지 사용방법
    1) 방법1 : 이미지를 리소스에 추가해서 사용하는 방법
    - 이미지를 res/drawable폴더에 추가한다.
    - 안드로이드는 확장자를 제외한 파일의 이름을 식별자로 활용한다.

    2) 방법2 : 직접 이미지 파일을  읽어서  그리는 방법
    - 이미지 경로를 이용해서 >> 비트맵으로 읽어오는 방법이다.
    - 게임과 같은 애플리케이션에서는 개발자가 이미지를 직접 그려주는 방법을 선호한다.

    - 순서 1) 비트맵 읽기
    Bitmap bitmap = BitmapFactory.decodeFile(filePath.getAbsolutePath());
    또는 Bitmap bitmap = BitmapFactory.decodeResource(getResource(), R.drawable.이미지)
    - getResource() : 이미지 데이터를 포함하는 애플리케이션 리소스객체
    즉, Resource객체를 가져와서... R.drawable.이미지 객체를 잦아
    디코딩해서  비트맵으로 전환한다.
    - R.drawable.이미지 : 이미지의 리소스 식별자

    - 순서 2) 비트맵 그리기 - drawBitmap()
    . canvas.drawBitmap(Bitmap bitmap, float left, float top, Paint paint)
    - bitmap : 화면에 그릴 비트맵
    - x, y : 그릴 위치
    - patint:  이미지를 변환할  변환행렬이 들어있는 Pait객체 (없으면  null)

    - 확대 축소 - createScaledBitmap
    . Bitmap.createScaledBitmap(bitmap, width, height, flase) :
    - width * height의 크기로 비트맵을 생성한다.

    - 변환 - preScale(float sx, float sy)
    . 도형의 크기를 x와 y축으로 sx, sy만큼 변경한다.
    . M' = M * S(sx, sy)
*/

import androidx.appcompat.app.AppCompatActivity;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import android.os.Bundle;
import android.util.AttributeSet;
import android.view.View;
import android.widget.LinearLayout;

public class MainActivity extends AppCompatActivity {

    float scaleX = 1.0f, scaleY = 1.0f, rotateAngle;
    MyView displayView;

    /**
     * 내부클래스 - 사용자 뷰
     */
    public class MyView extends View {

        public MyView(MainActivity context) {
            super(context);
        }

        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            Paint paint = new Paint();
            //이미지의 중심점
            int centerX = getWidth() / 2;
            int centerY = getHeight() / 2;
            //크기변환
            canvas.scale(scaleX, scaleY, centerX, centerY);
            //회전
            canvas.rotate(rotateAngle, centerX, centerY);
            //비트맵 객체 생성
            Bitmap picture = BitmapFactory.decodeResource(this.getResources(),  R.drawable.lena);
            //이미지 그리기
            canvas.drawBitmap(picture, 0, 0, paint);
        }

    }

    //실행
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        LinearLayout layout = (LinearLayout) findViewById(R.id.imageDisplay);
        //사용자 뷰를 특정한 컨테이너에 추가
        displayView = new MyView(this);
        layout.addView(displayView);
    }

    public void expand(View view) {
        scaleX += 0.3;
        scaleY += 0.3;
        displayView.invalidate();
    }

    public void shrink(View view) {
        scaleX -= 0.3;
        scaleY -= 0.3;
        displayView.invalidate();
    }

    public void rotateLeft(View view) {
        rotateAngle -= 30;
        displayView.invalidate();
    }

    public void rotateRight(View view) {
        rotateAngle += 30;
        displayView.invalidate();
    }

}

Image1_basic 프로젝트 결과 화면

 

 

6. AnimationDrawable - 애니메이션 동작
Image2_Animation1_dawable 프로젝트 만들기

※ 애니메이션 구현
1) drawable 폴더에 animation-list태그를 루트 요소로 갖는 xml파일을 만든다.
2) Java에서 AnimationDrawable 객체를 생성한다.
start() : 애니메이션 객체 시작
stop() : 애니메이션 객체 중지

res/drawable 경로에 frame1.png, frame2.png, frame3.png, frame4.png, frame5.png, frame6.png, frame7.png, frame8.png 사진 파일 넣기

- res/drawable/myanimation.xml

<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="false">
    <!--oneshot이 false면 한번만, true면 무한반복-->

    <!--이미지프레임, 시간(초)-->
    <item android:drawable="@drawable/frame1" android:duration="200"/>
    <item android:drawable="@drawable/frame2" android:duration="200"/>
    <item android:drawable="@drawable/frame3" android:duration="200"/>
    <item android:drawable="@drawable/frame4" android:duration="200"/>
    <item android:drawable="@drawable/frame5" android:duration="200"/>
    <item android:drawable="@drawable/frame7" android:duration="200"/>
    <item android:drawable="@drawable/frame8" android:duration="200"/>

</animation-list>

 

- res/values/mybuttonstyle.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="mybtn">
        <item name="android:layout_width">wrap_content</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="backgroundTint">#3F51B5</item>
        <item name="android:textColor">@color/white</item>
    </style>
</resources>

 

- activity_main.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">

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:layout_gravity="center_horizontal">
        <Button
            android:id="@+id/btnStart"
            style="@style/mybtn"
            android:onClick="mOnClick"
            android:layout_marginRight="5dp"
            android:text="시작"/>
        <Button
            android:id="@+id/btnStop"
            style="@style/mybtn"
            android:onClick="mOnClick"
            android:text="정지"/>
    </LinearLayout>

    <ImageView
        android:id="@+id/imgFrame"
        android:layout_width="300dp"
        android:layout_height="450dp"
        android:layout_marginTop="20dp"
        android:layout_gravity="center"/>

    <EditText
        android:id="@+id/state"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="15dp"
        android:hint="걷고 있습니다."
        android:gravity="center_horizontal"/>

</LinearLayout>

 

- MainActivity.java

package com.example.image2_animation1_dawable;

import androidx.appcompat.app.AppCompatActivity;

import android.graphics.Color;
import android.graphics.drawable.AnimationDrawable;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;

public class MainActivity extends AppCompatActivity {

    AnimationDrawable mAnimation;
    EditText state ;

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

        ImageView imageView = (ImageView)findViewById(R.id.imgFrame);
        state = (EditText)findViewById(R.id.state);
        imageView.setBackgroundResource(R.drawable.myanimation);
        //애니메이션드로우어블 객체 초기화
        mAnimation = (AnimationDrawable)imageView.getBackground();
    }

    /**
     * 버튼 눌렀을 때 호출 메서드
     * @param v
     */
    public void mOnClick(View v) {
        switch(v.getId()) {
            case R.id.btnStart:
                mAnimation.start(); //start() : 애니메이션 시작
                state.setText("걷기시작합니다.");
                state.setTextColor(Color.BLUE);
                break;
            case R.id.btnStop:
                mAnimation.stop(); //stop() : 애니메이션 중지
                state.setText("정지했습니다.");
                state.setTextColor(Color.RED);
                break;
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if(event.getAction() == MotionEvent.ACTION_DOWN) {
            mAnimation.start();
            state.setTextColor(Color.BLUE);
            return true;
        }else if(event.getAction() == MotionEvent.ACTION_UP) {
            mAnimation.stop();
            state.setTextColor(Color.RED);
            return true;
        }
        return super.onTouchEvent(event);
    }

}

Image2_Animation1_dawable 프로젝트 결과 화면

 

 

7. SurfaceView
Image3_SurfaceView1 프로젝트 만들기

※ SurfaceHolder.Callback 함수 구현
- surfaceCreated()
서피스가 준비되면 스레드를 시작한다.
서피스 뷰의 화면이 생성되면 호출된다.
여기에 그림을 그리는 스레드를 생성해 놓는다.
- surfaceDestroyed()
서피스가 파괴되기 직전에 호출된다.
이 메서드가 호출된 뒤에는 더 이상 그릴 수가 없다.
여기에 그림을 그리는 스레드를 종료시킨다.
- surfaceChanged()
서피스가 변경될 때 호출 - 화면의 구조(포맷, 크기 등)가 변경될 때 호출된다.

- activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Button"/>

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button"/>

</LinearLayout>

 

- MainActivity.java

package com.example.image3_surfaceview1;

import android.os.Bundle;
/*
     서피스 뷰(SurfaceView)를 활용한 그리기 (애니메이션)
     . 기존 드로어블뷰의 문제점
     복잡하지 않은 그래픽은 캔버스로 그리면 된다. 하지만 복잡해지면... 안드로이드의 메인스레드의 시간을 너무 빼앗아서
     느려지거나, 멈춤현상처럼 느껴지고, ANR(Application Not Responding) 오류가 발생할 수도 있다.
     . SurfaceView를 활용해서 해결
     별도의 스레드로 그림을 그려서 안드로이드 시스템이 그화면을 복사하게 지원하는 방식

     . 구현방법
     1) activity화면으로 SurfaceView를 설정하고
     2) 새로운 Thread에서 SurfaceView에 그림을 그리면 된다.
     3) ★ 이때....주의할 점은 안드로이드가 Surface를 생성하기 전에 그림을 그리면 안된다.
     그래서 Surface가 생성되고 소멸되는 시점을 그림을 담당하는 스레드에게 알려줘야 한다.
     그러한 목적으로 SurfaceHolder.Callback을 구현한다.
     4) 서피스 뷰 객체는 우리가 직접처리할 수 없고 반드시 SurfaceHolder를 통해서 처리해야 한다.
     -  왜냐하면 안드로이드 시스템이 서피스뷰를 실제장치의 뷰화면으로 부지런히 복사해서 구현하기 때문이다.
     >> SurfaceHolder객체 생성
     SurfaceHolder holder = getHolder();
     >> SurfaceHolder의 콜백메소드 받기
     holder.addCallback(this);

     5) ★어떤 순서로 그림을 그리는지 보자! ★
     ① 그림을 그리기전에 lockCanvas()를 호출해서 서피스뷰의 캔버스를 독점적으로 확보해놓는다.
     ② 캔버스에 그림을 그린다.
     ③ 다 그리고 나면 unlockCanvasAndPost()를 호출해서 사용자가 그려놓은 그대로 서피스뷰를 실제장치로 복사한다.
*/

import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    MySurfaceView view;

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

        view = new MySurfaceView(this);
        setContentView(view);
    }

}

 

- MySurfaceView.java

package com.example.image3_surfaceview1;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import androidx.annotation.NonNull;

class MySurfaceView  extends SurfaceView  implements SurfaceHolder.Callback {//implement 방법 : ctrl + i

    public Ball basket[] = new Ball[20]; //Ball 객체 저장 배열
    private MyThread thread; //내부클래스로 구현된 클래스

    public MySurfaceView(Context context) {
        super(context);
        SurfaceHolder holder = getHolder(); //서피스뷰 홀더 객체를 가져온다.
        holder.addCallback(this); //서피스뷰 홀더의 콜백메서드를 받을 수 있게 서피스뷰 홀더에 콜백메서드 추가한다.
        thread = new MyThread(holder); //스레드 생성
        for(int i=0 ; i < 20 ; i++) {
            basket[i] = new Ball(20);
        }
    }

    /**
     * 스레드 객체 반환 메서드
     * @return
     */
    public MyThread getThread() {
        return thread;
    }

    //-------------------------------------------------------------------------------------

    @Override
    public void surfaceCreated(@NonNull SurfaceHolder surfaceHolder) {
        //스레드 시작
        thread.setRunning(true); //스레드에 구현해 놓은 메서드 : true, false 제어
        thread.start();
    }

    @Override
    public void surfaceChanged(@NonNull SurfaceHolder surfaceHolder, int format, int  width,  int  height) {   // SurfaceHolder surfaceHolder, int i, int i1, int i2
        //Ball.WIDTH = width;
        //Ball.HEIGHT = height;
    }

    @Override
    public void surfaceDestroyed(@NonNull SurfaceHolder surfaceHolder) {
        boolean retry = true;
        thread.setRunning(false);
        while(retry) {
            try {
                thread.join(); //메인스레드와 통합시켜놓음
                retry = false; //스레드 종료
            }catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    //-------------------------------------------------------------------------------------

    /**
     * 스레드 클래스 구현
     */
    public class MyThread extends Thread {

        private boolean mRun = false;
        private SurfaceHolder mSurfaceHolder;
        public MyThread(SurfaceHolder surfaceHolder) {
            this.mSurfaceHolder = surfaceHolder;
        }

        @Override
        public void run() {
            while(mRun) {
                Canvas canvas = null;
                try {
                    canvas = mSurfaceHolder.lockCanvas(null);
                    canvas.drawColor(Color.BLACK);
                    synchronized (mSurfaceHolder) {
                        for(Ball ball : basket) {
                            ball.paint(canvas);
                        }
                    }
                }finally {
                    //캔버스가 완료되면
                    if(canvas != null) {
                        //캔버스 lock을 푼다 - 메인쪽에서 가져다 카피해서 붙인다.
                        mSurfaceHolder.unlockCanvasAndPost(canvas);
                    }
                }
            }
        }

        /**
         * 스레드 제어할 메서드
         * @param b
         */
        public void setRunning(boolean b) {
            mRun = b;
        }

    }

}

 

- Ball.java

package com.example.image3_surfaceview1;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

class Ball {

    int x, y, xInc = 1, yInc = 1;
    int diameter; //공의 반지름
    static int WIDTH = 1080, HEIGHT = 1550; //움직이는 공간의 크기(화면너비)

    public Ball(int d) {
        this.diameter = d; //반지름
        //벽에 닿았는지 체크
        x = (int)(Math.random() * (WIDTH - d) + 3);
        y = (int)(Math.random() * (HEIGHT - d) + 3);
        
        xInc = (int)(Math.random() * 30 + 1);
        yInc = (int)(Math.random() * 30 + 1);
    }

    public void paint(Canvas g) {
        Paint paint = new Paint();
        if(x < diameter || x > (WIDTH - diameter)) {
            xInc = -xInc;
        }
        if(y < diameter || y > (HEIGHT - diameter)) {
            yInc = -yInc;
        }
        x += xInc; //~Inc: 움직이는 거리
        y += yInc;
        paint.setColor(Color.RED);
        g.drawCircle(x, y, diameter, paint);
    }

}

Image3_SurfaceView1 프로젝트 결과 화면

 

 

8. 메뉴 - xml로 만들기
Menu1_OptionMenu1 프로젝트 만들기
xml로 구현 - inflate(메뉴 xml 파일, menu)

※ 메뉴(Menu)
1) 옵션 메뉴
- 주된 메뉴
- 탐색, 이메일작성, 설정 등에 사용 - 앱 전체에 영향을 주는 작업에 배치
* 생성 절차
(1) menu 폴더를 생성
(2) menu.xml 등록 (자바 코드로도 등록 가능)
(3) Java의 onCreateOptionsMenu(Menu menu) 메서드에서
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.myoptionmenu, menu); //XML을 객체화
inflate() : xml 파일을 자바코드에 접근시켜서 실제 객체로 만들어 사용하게 한다.
Java의 onOptionsItemSelected(MenuItem item) 메서드에서
switch() {...} 활용
2) 컨텍스트 메뉴
특정요소 클릭시에 뜬다.
3) 팝업 메뉴

res/drawable 경로에 pineapple.png, redapple.png, strawberry.png, watermelon.png 사진 파일 넣기

- activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical">

    <TextView
        android:layout_gravity="center"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="과일 옵션메뉴"
        android:textSize="28sp"/>

    <ImageView
        android:id="@+id/img"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="100dp"
        android:src="@drawable/pineapple"/>

</LinearLayout>

 

- res/menu/myoptionmenu.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:app="http://schemas.android.com/apk/res-auto"
      xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/apple"
        android:icon="@android:drawable/btn_star_big_on"
        android:title="사과"/>
    <item
        android:id="@+id/strawberry"
        android:icon="@android:drawable/ic_btn_speak_now"
        android:title="딸기"/>
    <item
        android:id="@+id/watermelon"
        android:icon="@android:drawable/checkbox_on_background"
        android:title="수박"
        app:showAsAction="never"/>
</menu>

 

- MainActivity.java

package com.example.menu1_optionmenu1;

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.ImageView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    ImageView img;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        img =(ImageView)findViewById(R.id.img);
    }

    /**
     * 메뉴등록
     * @param menu
     * @return
     */
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.myoptionmenu, menu); //XML을 객체화
        return true;
    }

    /**
     * 선택했을 때 할 일 등록
     * @param item
     * @return
     */
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch(item.getItemId()) {
            case R.id.apple:
                img.setImageResource(R.drawable.redapple);
                Toast.makeText(this,"사과",Toast.LENGTH_LONG).show();
                break;
            case R.id.strawberry:
                img.setImageResource(R.drawable.strawberry);
                Toast.makeText(getApplicationContext(),"딸기",Toast.LENGTH_LONG).show();
                break;
            case R.id.watermelon:
                img.setImageResource(R.drawable.watermelon);
                Toast.makeText(getApplicationContext(),"수박",Toast.LENGTH_LONG).show();
                break;
        }
        return true;
    }

}

Menu1_OptionMenu1 프로젝트 결과 화면

 

 

9. 메뉴 - Java로 만들기
Menu2_OptionMenu2 프로젝트 만들기
자바로 메뉴를 등록해서 구현하는 옵션메뉴

res/drawable 경로에 mov01.png, mov02.png, mov03.png, mov04.png, mov05.png, mov06.png 사진 파일 넣기

- activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:background="#EEE6A4"
        android:text="자바로 만드는 옵션메뉴"
        android:textSize="26sp"/>

    <ImageView
        android:id="@+id/img"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="fitXY"
        android:src="@drawable/mov06"/>

</LinearLayout>

 

- MainActivity.java

package com.example.menu2_optionmenu2;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.SubMenu;
import android.widget.ImageView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    ImageView img;

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

        img = (ImageView) findViewById(R.id.img);
    }

    /**
     * 메뉴등록
     * @param menu
     * @return
     */
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);
        //메인메뉴 등록
        MenuItem item1 = menu.add(0,1,0,"move1");
        item1.setIcon(R.drawable.ic_launcher_background);
        MenuItem item2 = menu.add(0,2,0,"move2");
        item2.setIcon(R.drawable.ic_launcher_background);
        menu.add(0,3,0,"move3").setIcon(R.drawable.ic_launcher_background);
        //서브메뉴 추가작성방법 - Menu 객체를 추가한후 작성한다.
        Menu sub = menu.addSubMenu("서브영화");
        sub.add(1,4,0,"라디오스타").setIcon(R.drawable.ic_launcher_background);
        sub.add(2,5,0,"비열한거리").setIcon(R.drawable.ic_launcher_background);
        return true;
    }

    /**
     * 선택했을 때 할 일 등록
     * @param item
     * @return
     */
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch(item.getItemId()) {
            case 1:
                img.setImageResource(R.drawable.mov01);
                Toast.makeText(this,"사과",Toast.LENGTH_LONG).show();
                break;
            case 2:
                img.setImageResource(R.drawable.mov02);
                Toast.makeText(getApplicationContext(),"딸기",Toast.LENGTH_LONG).show();
                break;
            case 3:
                img.setImageResource(R.drawable.mov03);
                Toast.makeText(getApplicationContext(),"수박",Toast.LENGTH_LONG).show();
                break;
            case 4:
                img.setImageResource(R.drawable.mov04);
                Toast.makeText(getApplicationContext(),"수박",Toast.LENGTH_LONG).show();
                break;
            case 5:
                img.setImageResource(R.drawable.mov05);
                Toast.makeText(getApplicationContext(),"수박",Toast.LENGTH_LONG).show();
                break;
            case 6:
                img.setImageResource(R.drawable.mov06);
                Toast.makeText(getApplicationContext(),"수박",Toast.LENGTH_LONG).show();
                break;
        }
        return true;
    }

}

Menu2_OptionMenu2 프로젝트 결과 화면

 

 

10. 컨텍스트 메뉴
Menu3_ContextMenu1 프로젝트 만들기

※ 컨텍스트 뷰
특정한 항목에 LongClick 이벤트가 발생되었을 때 적용되는 동작을 구현할 때 사용.
옵션메뉴와 차이점은 누가 메뉴를 소유할 것이냐의 차이다.
옵션메뉴는 액티비티가 소유하고 컨텍스트 뷰는 선택한 뷰가 소유.
사용 메서드
1) registerForContextMenu(TextView 객체) : 뷰 객체를 컨테스트 메뉴로 등록
2) onCreateContextMenu() : 메뉴등록
3) onContextItemSelected() : 메뉴 선택시 할 일

- activity_main.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"
    android:id="@+id/linearLayout01">

    <TextView
        android:id="@+id/TextView01"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="Only I can change my life. No one can do it for me"
        android:textSize="100px"
        android:typeface="serif"/>

</LinearLayout>

 

- MainActivity.java

package com.example.menu3_contextmenu1;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.graphics.Color;
import android.view.ContextMenu;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    TextView text;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        text = (TextView)findViewById(R.id.TextView01);
        //컨텍스트 메뉴를 장착할 뷰(위젯)
        registerForContextMenu(text);
    }

    /**
     * 메뉴 등록
     * @param menu
     * @param v
     * @param menuInfo
     */
    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
        super.onCreateContextMenu(menu, v, menuInfo);
        menu.setHeaderTitle("컨텍스트 메뉴");
        menu.add(0,1,0,"배경색:RED");
        menu.add(0,2,0,"배경색:GREEN");
        menu.add(0,3,0,"배경색:BLUE");
    }

    /**
     * 메뉴가 선택되었을 때
     * @param item
     * @return
     */
    @Override
    public boolean onContextItemSelected(MenuItem item) {
        switch(item.getItemId()) {//getGroupId(), getOrderId()
            case 1:
                text.setBackgroundColor(Color.RED);
                return true;
            case 2:
                text.setBackgroundColor(Color.GREEN);
                return true;
            case 3:
                text.setBackgroundColor(Color.BLUE);
                return true;
            default:
                return super.onContextItemSelected(item);
        }
    }

}

Menu3_ContextMenu1 프로젝트 결과 화면

 

 

11. 팝업 메뉴
Menu4_PopUpMenu1 프로젝트 만들기

- activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginTop="150dp"
        android:onClick="onClick"
        android:text="show popup menu"
        android:textSize="30sp"/>

</LinearLayout>

 

- res/menu/popup.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >

    <item
        android:id="@+id/search"
        android:icon="@android:drawable/ic_menu_search"
        android:title="search"/>
    <item
        android:id="@+id/add"
        android:icon="@android:drawable/ic_menu_add"
        android:title="add"/>
    <item
        android:id="@+id/edit"
        android:icon="@android:drawable/ic_menu_edit"
        android:title="edit">
        <!--서브메뉴설정-->
        <menu>
            <item
                android:id="@+id/share"
                android:icon="@android:drawable/ic_menu_share"
                android:title="share"/>
        </menu>
    </item>

</menu>

 

- MainActivity.java

package com.example.menu4_popupmenu1;

import android.os.Bundle;
import android.view.MenuItem;
import android.view.View;
import android.widget.PopupMenu;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

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

    public void onClick(View textview) {
        //1. 팝업 메뉴 객체 생성
        PopupMenu popup = new PopupMenu(this, textview); //특정 뷰를 지정
        //2. inflate() 메서드로 xml 메뉴 파일을 객체화시켜 메뉴로 등록한다.
        popup.getMenuInflater().inflate(R.menu.popup, popup.getMenu());
        //3. 메뉴를 선택했을 때 이벤트리스너 등록
        popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
            public boolean onMenuItemClick(MenuItem item) {
                Toast.makeText(getApplicationContext(), "클릭된 팝업 메뉴: "+ item.getTitle(), Toast.LENGTH_SHORT).show();
                return true;
            }
        });
        //4. 팝업 보여주기
        popup.show();
    }

}

Menu4_PopUpMenu1 프로젝트 결과 화면

 

 

12. Dialog - Alert
Menu5_Dialog1_Alert 프로젝트 만들기
자바스크립트의 confirm 같은 것이다.

※ 대화상자
사용자에게 메시지 출력
로그인윈도우, 진행현황을 보여줄 때 주로 사용
현재 액티비티 앞에 보여지는 작은 윈도우다.
이 대화상자가 나오면 메인 엑티비티는 제어권을 잃는다.
종료
1) AlertDialog
구현방법1. AlertDialog.Builder 객체를 생성하고 속성을 지정해서 AlertDialog 객체 생성
구현방법2. 제목설정 : setMessage("제목");
구현방법3. 메뉴버튼을 설정한다.
setPositiveButton() : 완료 >> 구현
setNegativeButton() : 취소 >> 구현
setNeutralButton() : 무시
구현방법4. 보여준다 - show()
2) DatePickerDialog / TimePickgerDialog - 앞에서 학습(예약)

- activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/btn1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="100dp"
        android:layout_gravity="center_horizontal"
        android:backgroundTint="#2196F3"
        android:text="결제 하시겠습니까?"
        android:textSize="20sp"
        android:onClick="open"/>

</LinearLayout>

 

- MainActivity.java

package com.example.menu5_dialog1_alert;

import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;

import android.content.DialogInterface;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

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

    public void open(View view) {
        AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
        alertDialogBuilder.setMessage("결제를 진행하시겠습니까? ");
        alertDialogBuilder.setPositiveButton("예", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                Toast.makeText(getApplicationContext(), "결제가 완료되었습니다.", Toast.LENGTH_SHORT).show();
            }
        });
        alertDialogBuilder.setNegativeButton("아니오", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                Toast.makeText(MainActivity.this,"결제가 취소되었습니다.", Toast.LENGTH_SHORT ).show();
                //finish(); //이것을 적용하면 액티비티가 종료된다.
            }
        });
        AlertDialog alertDialog = alertDialogBuilder.create(); //Builder의 create()활용해서 객체생성한다.
        alertDialog.show();
    }

}

Menu5_Dialog1_Alert 프로젝트 결과 화면

 

 

13. Dialog - ListAlert
Menu6_Dialog2_ListAlert 프로젝트 만들기

- activity_main.xml

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

    <Button
        android:id="@+id/btn1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="100dp"
        android:layout_gravity="center_horizontal"
        android:backgroundTint="#2196F3"
        android:text="색상을 선택하시겠습니까?"
        android:textSize="20sp"
        android:onClick="open"/>

</LinearLayout>

 

- MainActivity.java

package com.example.menu6_dialog2_listalert;

import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;

import android.content.DialogInterface;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    LinearLayout layout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        layout = (LinearLayout)findViewById(R.id.backColor);
    }

    public void open(View view) {
        final CharSequence[] items = {"Red", "Green", "Blue"};
        AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
        //제목
        alertDialogBuilder.setTitle("색상을 선택하시오 ");
        //-------------------------------------------------------------------------------------------------
        //리스트 달기
        alertDialogBuilder.setSingleChoiceItems(items,-1, new DialogInterface.OnClickListener() {//checkedItem -1은 아직 선택되지 않음
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {//배열 인덱스 가져옴
                if(i == 0) {
                    layout.setBackgroundColor(Color.RED);
                }else if(i == 1) {
                    layout.setBackgroundColor(Color.GREEN);
                }else if(i == 2) {
                    layout.setBackgroundColor(Color.BLUE);
                }
                Toast.makeText(getApplicationContext(),items[i],  Toast.LENGTH_SHORT).show();
            }
        });
        //-------------------------------------------------------------------------------------------------

        alertDialogBuilder.setPositiveButton("선택", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                Toast.makeText(getApplicationContext(), "색상선택이 되었습니다", Toast.LENGTH_SHORT).show();
            }
        });

        alertDialogBuilder.setNegativeButton("취소", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                layout.setBackgroundColor(Color.WHITE);
                Toast.makeText(MainActivity.this,"색상선택이 취소되었습니다..",Toast.LENGTH_SHORT ).show();
                //finish(); // 이것을 적용하면 액티비티가 종료된다.
            }
        });
        
        AlertDialog alertDialog = alertDialogBuilder.create();
        alertDialog.show();
    }
    
}

Menu6_Dialog2_ListAlert 프로젝트 결과 화면

 

 

14. CustomDialog
Menu7_CustomDialog1_LogIn 프로젝트 만들기
사용자 지정 Dialog

※ 사용자 다이얼로그
사용자가 직접 만든 창

- activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical|center_horizontal"
        android:backgroundTint="#2196F3"
        android:onClick="onClick"
        android:text="로그인" >
    </Button>

</LinearLayout>

 

- custom_dialog.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="300dp"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <EditText
        android:id="@+id/username"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="username" >
        <requestFocus />
    </EditText>

    <EditText
        android:id="@+id/password"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="password"
        android:inputType="textPassword" >
    </EditText>

    <LinearLayout
        android:id="@+id/linearLayout1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center">
        <Button
            android:id="@+id/login"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:backgroundTint="#00BCD4"
            android:layout_marginRight="5dp"
            android:text="로그인" >
        </Button>
        <Button
            android:id="@+id/cancel"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:backgroundTint="#FF5722"
            android:text="취소" >
        </Button>
    </LinearLayout>

</LinearLayout>

 

- MainActivity.java

package com.example.menu7_customdialog1_login;

import androidx.appcompat.app.AppCompatActivity;

import android.app.Dialog;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity implements  View.OnClickListener {

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

    /**
     * 이벤트 메서드
     * @param v
     */
    @Override
    public void onClick(View v) {
        Dialog  loginDialog = new Dialog(this);

        loginDialog.setContentView(R.layout.custom_dialog);
        loginDialog.setTitle("로그인 화면");

        Button login = (Button)loginDialog.findViewById(R.id.login);
        Button cancel = (Button)loginDialog.findViewById(R.id.cancel);

        EditText username = (EditText)loginDialog.findViewById(R.id.username);
        EditText password = (EditText)loginDialog.findViewById(R.id.password);

        //login 버튼을 눌렀을 때 리스너
        login.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (username.getText().toString().trim().length() > 0  && password.getText().toString().trim().length() > 0) {
                    Toast.makeText(getApplicationContext(), "로그인 성공",   Toast.LENGTH_LONG).show();
                    loginDialog.dismiss();
                }else {
                    Toast.makeText(getApplicationContext(), "다시 입력하시오",
                    Toast.LENGTH_LONG).show();
                }
            }
        });
        
        //cancel 버튼을 눌렀을 때 리스너
        cancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                loginDialog.dismiss(); //dismiss() : 사용자 다이얼로그 닫기
            }
        });
        
        //보여주기
        loginDialog.show();
    }

}

Menu7_CustomDialog1_LogIn 프로젝트 결과 화면

 

 

15. Fragment
View1_Fragment 프로젝트 만들기

※ 프래그먼트
액티비티 안의 작은 조각(서브 액티비티)라 한다.
특징1. 자신만의 레이아웃을 가질 수 있다.
특징2. 자신만의 생명주기 콜백 메서드를 가질 수 있다.
특징3. 액티비티가 실행되는 동안에 프래그먼트를 액티비티에 추가하거나 삭제할 수 있다.
특징4. 하나의 프래그먼트는 여러 액티비티에서 공유할 수 있다.
특징5. 생명주기는 호스트 액티비티의 수명주기와 연관된다.

- activity_main.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"
    android:layout_margin="5dp">

    <Button
        android:id="@+id/button1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:backgroundTint="#C6C3C3"
        android:onClick="setFrag1"
        android:text="프래그먼트1"
        android:textColor="#000000"/>

    <Button
        android:id="@+id/button2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:backgroundTint="#C6C3C3"
        android:onClick="setFrag2"
        android:text="프래그먼트2"
        android:textColor="#000000"/>

    <!--프래그먼트 뷰를 겹쳐놓으려고 FrameLayout으로 설정-->
    <FrameLayout
        android:id="@+id/fame_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#52DAEC"/>

</LinearLayout>

 

- MainActivity.java

package com.example.view1_fragment;

import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;

import android.os.Bundle;
import android.view.View;

public class MainActivity extends AppCompatActivity {

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

    /**
     * 버튼에 따른 이벤트 메서드1
     * @param v
     */
    public void setFrag1(View v) {
        //1. 프래그먼트 매니저 객체를 가져온다 - getSupportFragmentManager()
        FragmentManager manager = getSupportFragmentManager();
        //2. 프래그먼트 매니저 객체에서 프래그먼트 트랜젝션 객체 가져옴
        FragmentTransaction ft = manager.beginTransaction();
        Fragment1 f1 = new Fragment1();
        //3. 프래그먼트 교체
        ft.replace(R.id.fame_container, f1, "첫번째프래그먼트");
        //4. 커밋처리
        ft.commit();
        //ft.commitAllowingStateLoss(); //상태에 대한 손실을 우려해서 즉시 실행하고자 할 때 사용
        //ft.commitNow(); //현재 제출하려 하는 트랜젝션만 실행처리, back stack에 추가할 트랜젝션을 사용할 수 없다.
    }

    /**
     * 버튼에 따른 이벤트 메서드2
     * @param v
     */
    public void setFrag2(View v) {
        FragmentManager manager = getSupportFragmentManager();
        FragmentTransaction ft = manager.beginTransaction();
        Fragment2  f2 = new Fragment2();
        ft.replace(R.id.fame_container, f2, "두번째프래그먼트");
        //ft.commit();
        ft.commitAllowingStateLoss();
        // ft.commitNow();
    }

}

 

- activity_fragment1.xml

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

    <ImageView
        android:id="@+id/imgView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:src="@drawable/m10_clothes8"
        android:background="#6CBDCA87"/>

</FrameLayout>

 

- Fragment1.java

package com.example.view1_fragment;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

import android.app.Activity;
import android.app.Fragment;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;

import java.io.File;

public class Fragment1 extends androidx.fragment.app.Fragment {

    ImageView imageView;

    /**
     * 프래그먼트가 액티비티와 연결될 경우 호출
     * 여기서 액티비티가 전달된다.
     * @param context
     */
    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
    }

    /**
     * ★ 프래그먼트를 생성할 때 호출
     * 프래그먼트가 일시정지나 중단된 후 재개되었을 때 유지해야할 정보(Bundle savedInstanceState 매개변수)
     * 초기화 작업 적용
     * @param savedInstanceState
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    /**
     * ★ 자신의 뷰를 그리기위해 호출
     * 레이아웃을 inflate 해서 생성
     * @param inflater
     * @param container
     * @param savedInstanceState
     * @return
     */
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.activity_fragment1, container, false);
    }
    
    @Override
    public void onActivityCreated( Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
    }

    /**
     * 액티비티가 시작되는 상태에 들어가면서 호출
     * 여기서부터 사용자에게 보여진다.
     */
    @Override
    public void onStart() {
        super.onStart();
    }

    /**
     * 사용자와 상호작용을 시작한다.
     * onPause() 메서드를 호출하고 다시 재개되면 onResume() 메서드를 호출하게 된다.
     */
    @Override
    public void onResume() {
        super.onResume();
    }

    /**
     * ★ 사용자가 프래그먼트를 떠나면 호출
     * 사용자가 다시 오지 않을 수도 있으므로 현재 사용자 세션을 넘어 지속해야 하는 변경사항을 여기서 저장해 놓는다.
     */
    @Override
    public void onPause() {
        super.onPause();
    }

    @Override
    public void onStop() {
        super.onStop();
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    @Override
    public void onDetach() {
        super.onDetach();
    }

}

 

- activity_fragment2.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="250dp"
    android:layout_height="250dp"
    android:layout_gravity="right|center_vertical">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#2196f3"
        android:gravity="center"
        android:text="프래그먼트"
        android:textSize="30dp"
        android:textStyle="bold"
        android:textColor="#fff"/>

</FrameLayout>

 

- Fragment2.java

package com.example.view1_fragment;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class Fragment2 extends Fragment {

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
    }

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

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.activity_fragment2, container, false);
    }

    @Override
    public void onActivityCreated( Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
    }

    @Override
    public void onStart() {
        super.onStart();
    }

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

    @Override
    public void onPause() {
        super.onPause();
    }

    @Override
    public void onStop() {
        super.onStop();
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    @Override
    public void onDetach() {
        super.onDetach();
    }

}

View1_Fragment 프로젝트 결과 화면

 

 

16. Fragment2
View2_Fragment2 프로젝트 만들기
프래그먼트는 액티비티 단위로 된다.

res/drawable 경로에 soul.png 사진 파일 넣기

- activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:gravity="center_horizontal">

        <Button
            android:id="@+id/btn1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:backgroundTint="#00BCD4"
            android:layout_marginRight="5dp"
            android:text="프래그먼트1"
            android:onClick="setFrag"/>

        <Button
            android:id="@+id/btn2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:backgroundTint="#00BCD4"
            android:text="프래그먼트2"
            android:onClick="setFrag"/>

    </LinearLayout>

    <!--프래그먼트 추가할 위젯-->
    <FrameLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="400dp"
        android:layout_margin="15dp"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:onClick="moveToSub"
        android:text="서브창가기"/>

</LinearLayout>

 

- MainActivity.java

package com.example.view2_fragment2;

import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {

    Sub sub;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        sub = new Sub();
    }

    public void setFrag(View v) {
        FragmentManager manager = getSupportFragmentManager();
        FragmentTransaction ft = manager.beginTransaction();
        switch (v.getId()) {
            case R.id.btn1:
                //Intent : 현재 액티비티 정보 가지고 다음 페이지로 정보 넘겨줌
                Intent intent = new Intent(getApplicationContext(), Sub.class); //Intent(this, 이동할 페이지(Java))
                ft.replace(R.id.container, new Fragment1(), "myfrag1");
                ft.commit();
                break;
            case R.id.btn2:
                ft.replace(R.id.container, new Fragment2(), "myfrag2");
                ft.commitAllowingStateLoss();
                break;
        }
    }

    //서브창가기 인텐트
    public void moveToSub(View v) {
        Intent intent = new Intent(this, Sub.class);
        startActivity(intent);
    }

}

 

- sub.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="서브창"/>

    <Button
        android:id="@+id/end"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="end"
        android:layout_gravity="center"
        android:text="종료"/>

</LinearLayout>

 

- Sub.java

package com.example.view2_fragment2;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;

import androidx.appcompat.app.AppCompatActivity;

public class Sub extends AppCompatActivity {

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

    public void end(View v) {
        Intent intent = getIntent();
        finish();
    }

}

 

- fragment1.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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"
    android:layout_margin="15dp"
    android:background="#ff0000">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="내가만든 조각화면1"/>

</FrameLayout>

 

- Fragment1.java

package com.example.view2_fragment2;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

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

public class Fragment1 extends Fragment {

   public  Fragment1() {}

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState) {
       LayoutInflater inflater1 = getLayoutInflater();
       View fragment1 = inflater1.inflate(R.layout.fragment1,container,false); //container : activity_main.xml의 FrameLayout을 말한다.
       return fragment1;
    }

}

 

- fragment2.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        android:background="#FFEB3B"
        android:text="내가만든 조각화면2"
        android:textSize="20sp"/>

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:src="@drawable/soul"
        android:scaleType="fitCenter"/>

</LinearLayout>

 

- Fragment2.java

package com.example.view2_fragment2;

import android.app.Activity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

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

public class Fragment2 extends Fragment {

    Activity c = getActivity();

    Fragment2() {}

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment2, container, false);
    }

}

 

- AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.view2_fragment2">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.View2_Fragment2">
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <!--서브창은 등록해야한다.-->
        <activity android:name=".Sub" />
    </application>

</manifest>

View2_Fragment2 프로젝트 결과 화면

댓글