자바 안드로이드 정리 - 2

백규현·2021년 10월 19일
0

자바안드로이드

목록 보기
2/2

커스텀뷰에서의 터치 이벤트

  • 싱글터치 일때 :
@Override
 public boolean onTouchEvent(MotionEvent event) {
 	float eventX = event.getX();
 	float eventY = event.getY();
 	switch (event.getAction()) {
 		case MotionEvent.ACTION_DOWN:
 			path.moveTo(eventX, eventY);
 			return true;
 		case MotionEvent.ACTION_MOVE:
 			path.lineTo(eventX, eventY);
 			break;
 		case MotionEvent.ACTION_UP:
 			break;
 		default:
 			return false;
 	}
 	invalidate();
 	return true;
 }

ACTION_DOWN 누르는 동작이 시작됨
ACTION_UP 누르고 있다가 땔때 발생함
ACTION_MOVE 누르는 도중에 움직임
ACTION_CANCEL 터치 동작이 취소됨
ACTION_OUTSIDE 터칠가 현재의 위젯을 벗어남

  • 멀티터치 일때 :
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int index = event.getActionIndex();
        int id = event.getPointerId(index);
        int action = event.getActionMasked();

        switch (action) {
            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_POINTER_DOWN:
                x[id] = (int) event.getX(index);
                y[id] = (int) event.getY(index);
                touching[id] = true;
                break;
            case MotionEvent.ACTION_MOVE:
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_POINTER_UP:
            case MotionEvent.ACTION_CANCEL:
                touching[id] = false;
                break;
        }
        invalidate();
        return true;
    }

추가되는 터치 이벤트
ACTION_POINTER_DOWN 첫 번째 포인터 이외의 포인터에 대하여 발생된다. 포인터 데이터는 getActionIndex()이 반환하는 인덱스에 저장된다.
ACTION_POINTER_UP 마지막 포인터가 아닌 다른 포인터가 화면에서 없어지면 발생된다.

첫번째 터치(index=0,id=0), 두번째 터치(index=1,id=1)가 있다고 할때 만약 첫번째 터치를 때게 된다면, 두번째 터치는 id=1로 유지하고, index는 1 -> 0으로 바뀌게 된다. 이후 세번째 터치를 하면 그 터치는 index=1,id=0으로 부여받게 된다.


컨텍스트 메뉴 종류

  • 플로팅 컨텍스트 메뉴: 사용자가 항목 위에서 오래 누르기를 하면 메뉴가 대화상자처럼 떠서 표시된다.
  • 컨텍스트 액션 모드: 현재 선택된 항목에 관련된 메뉴가 액션바에 표시된다. 여러 항목을 선택하여 특정한 액션을 한꺼번에 적용할 수 있다.

Canvas, Paint

  • Canvas 클래스는 그림을 그리는 캔버스에 해당되고, Paint 클래스는 색상이나 선의 스타일 등과 같은 그리기 속성을 가지고 있는 클래스
  • 주로 View클래스의 onDraw(Canvas canvas)를 오버라이딩하면서 사용한다.

폰트

  • onDraw내부에서

내부 폰트 예제 :

...

Typeface t;
t = Typeface.create(Typeface.DEFAULT, Typeface.NORMAL);
paint.setTypeface(t);
canvas.drawText("DEFAULT 폰트", 10, 400, paint);

외부 폰트 예제 :

...

myFont = Typeface.createFromAsset(getContext().getAssets(), 
"animeace2_ital.ttf");
paint.setTypeface(myFont);

서피스 뷰

  • 서피스뷰는 사용자 인터페이스와는 별도로 애플리케이션에게 그림을 그릴 수 있는 화면을 제공한다.

  • 예제 :

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        MySurfaceView w = new MySurfaceView(this);
        setContentView(w);
    }
}

class Ball {
    int x, y, xInc = 1, yInc = 1;
    int diameter;
    static int WIDTH = 1080, HEIGHT = 1920;

    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))
            xInc = -yInc;

        x += xInc;
        y += yInc;

        paint.setColor(Color.RED);
        g.drawCircle(x,y,diameter,paint);
    }
}

class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback {

    public Ball basket[] = new Ball[10];
    private MyThread thread;

    public MySurfaceView(Context context) {
        super(context);
        SurfaceHolder holder = getHolder();
        holder.addCallback(this);
        thread = new MyThread(holder);

        for (int i=0; i<10; i++)
            basket[i] = new Ball(20);
    }

    public MyThread getThread() {
        return thread;
    }

    @Override
    public void surfaceCreated(@NonNull SurfaceHolder holder) {
        thread.setRunning(true);
        thread.start();
    }

    @Override
    public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) { }

    @Override
    public void surfaceDestroyed(@NonNull SurfaceHolder holder) {
        boolean retry = true;

        thread.setRunning(false);
        while (retry) {
            try {
                thread.join();
                retry = false;
            } catch (InterruptedException e) {
            }
        }
    }

    class MyThread extends Thread {
        private boolean mRun = false;
        private SurfaceHolder mSurfaceHolder;

        public MyThread(SurfaceHolder surfaceHolder) {
            mSurfaceHolder = surfaceHolder;
        }

        @Override
        public void run() {
            while (mRun) {
                Canvas c = null;
                try {
                    c = mSurfaceHolder.lockCanvas(null);
                    c.drawColor(Color.BLACK);
                    synchronized (mSurfaceHolder) {
                        for (Ball b : basket) {
                            b.paint(c);
                        }
                    }
                } finally {
                    if (c != null) {
                        mSurfaceHolder.unlockCanvasAndPost(c);
                    }
                }
            }
        }

        public void setRunning(boolean b) {
            mRun = b;
        }
    }
}

액티비티와 인텐트

  • 애플리케이션 : 한 개 이상의 액티비티들로 구성된다. 액티비티들은 애플리케이션 안에서 느슨하게 묶여 있다.

  • 액티비티 : 애플리케이션을 구성하는 빌딩 블록

  • 태스크 : 스택에 있는 액티비티

  • 액티비티 스택 : back키를 누르면 현재 액티비티를 제거하고 이전 액티비티로 되돌아 간다. 스택안에 같은 액티비티가 여러 개 들어가 있을 수도 있다.

  • 인텐트 : 다른 액티비티를 시작하려면 액티비티의 실행에 필요한 여러가지 정보들을 보내주어야 한다. 정보를 인텐트에 실어서 보낸다.

  • 명시적 인텐트 : 실행하고자 하는 액티비티의 이름을 적어 준다.

startActivity를 사용하는 경우:

Intent in = new Intent(MainActivity.this, SubActivity.class);
startActivityForResult(in);

startActivityForResult를 사용하는 경우:
보내는 쪽

Intent in = new Intent(MainActivity.this, SubActivity.class);
startActivityForResult(in, GET_STRING);
@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == GET_STRING) {
            if (resultCode == RESULT_OK) {
                text.setText(data.getStringExtra("INPUT_TEXT"));
            }
        }
    }

받는 쪽

 Intent intent = new Intent();
 intent.putExtra("INPUT_TEXT", edit.getText().toString());
 setResult(RESULT_OK, intent);
 finish();

이런식으로 onActivityResult에서 requestCode,resultCode를 이용해 코드를 체크 할 수있다. 보통 어떤 엑티비티끼리 통신했는지 확인해기위해 사용한다.

  • 암시적 인텐트
    public void onClick(View view) {
        Intent intent = null;
        switch (view.getId()) {
            case R.id.web:
                intent = new Intent(Intent.ACTION_VIEW,
                        Uri.parse("http://www.google.com"));
                break;
            case R.id.call:
                intent = new Intent(Intent.ACTION_DIAL,
                        Uri.parse("tel:(+82)12345789"));
                break;
            case R.id.map:
                intent = new Intent(Intent.ACTION_VIEW,
                        Uri.parse("geo:37.30,127.2?z=10"));
                break;
            case R.id.contact:
                intent = new Intent(Intent.ACTION_VIEW,
                        Uri.parse("content://contacts/people/"));
                break;
        }
        if (intent != null) {
            startActivity(intent);
        }
    }

멀티태스킹

  • 동시에 여러 태스크를 실행
  • 현재의 태스크를 배경으로 보내고 다른 태스크를 전경에서 시작할 수 있다.

액티비티

  • 실행 상태 : 액티비티가 전경에 위치하고 있으며 사용자의 포커스를 가지고 있다.

  • 일시멈춤 상태 : 다른 액티비티가 전경에 있으며 포커스를 가지고 있지만 현재 액티비티의 일부가 아직도 화면에서 보이고 있는 상태이다.

  • onCreate() : 액티비티가 생성되면서 호출 / 중요한 구성요소들을 초기화

  • onPause(): 사용자가 액티비티를 떠나고 있을 때, 이 메소드가 호출 / 그 동안 이루어졌던 변경사항을 저장

  • 정지 상태 : 액티비티는 배경에 위치한다.

  • 액티비티 생성
    onCreate() -> onStart() -> onResume()

  • 일시멈춤 상태
    onPause() 했다가 onResume()으로 복귀

  • 정지되었다가 다시 실행하는 경우
    onStop() 이 불려지면서 정지 -> 다시 실행 -> onRestart() -> onStart() -> onResume()

  • 액티비티 상태 저장

예제 :

public class MainActivity extends Activity {
    Button button1;
    TextView text;
    int count = 0;
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        if (savedInstanceState != null) {
            count = savedInstanceState.getInt("count");
            text.setText("현재 개수=" + count);
        }
        
        text = (TextView) findViewById(R.id.text);
        button1 = (Button) findViewById(R.id.button1);
        
        button1.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                count++;
                text.setText("현재 개수=" + count);
            }
        });
    }
    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        Log.i("LifeCycle","onSaveInstanceState() 호출");
        outState.putInt("count", count);
    }
}

리소스

  • 기본 리소스 : 장치 구성과 상관없이 기본적으로 사용되는 리소스이다.
  • 대체 리소스 : 대체 리소스는 특정한 장치 구성을 위하여 설계된 리소스이다. 기본 디렉토리 이름에 특정한 장치 구성의 이름을 붙인 디렉토리에 리소스들이 저장.

보안

  • 안드로이드에서 각 애플리케이션은 자신의 프로세스 안에서 실행한다.
  • 애플리케이션은 다른 애플리케이션을 건드릴 수 없다. 이것을 Sandboxing 이라고 한다.
profile
반갑습니다.

0개의 댓글