2015.02.25 23:07


Android ACTIVITY 전환시 액티비티의 History 관련 설정

일반적인 경우, 안드로이드 용 어플리케이션을 작성하게 되면 여러가지 Activity 들을 생성하게 됩니다. 이때, 가장 골치가 아픈 일 중 하나는 바로 Activity 와 Activity 간의 Flow 를 설계하고 이를 적절하게 구현하는 일입니다. (특히 안드로이드를 사용해보지도 않은 UX 팀과 함께 일하게 되는 경우라면 더욱 그러합니다...)

 기본적으로 안드로이드 플랫폼 상에서 Activity 는 또 다른 Activity 를 시작할 수 있고, 각각의 Activity 는 차곡 차곡 Task 라고 불리우는 Activity Stack 에 쌓이게 됩니다. 사용자는 일반적으로 Back 버튼을 이용해서 현재 화면상에 보이는 Activity 를 종료 시키고, 바로 직전에 사용된 Activity 로 돌아갈 수 있습니다. 안드로이드 펍의 회색님의 말을 빌리자면, 인터넷 브라우저를 통해 웹페이지를 검색하는 것과 유사한 방식입니다. 

 하지만 이러한 방법만으로는 효과적인 UX Flow 를 구축하는데 어려움이있습니다. 다행히, 구글에서는 Activity 를 호출할 때 사용되는 Intent 에 적절한 플래그 값을 설정해서 Activity Stack 을 제어할 수 있는 방법을 제공해 줍니다. 이 플래그들은  FLAG_ACTIVITY 라는 접두어를 갖고 있는데, 종류가 다양해 헷갈리는 수도 있는데, 개인적으로 제가 가장 요긴하게 사용하고 있는 FLAG_ACTIVITY 네 가지를 소개해 봅니다. 

 먼저 FLAG_ACTIVITY_SINGLE_TOP 입니다. 우선 간단하게 그림으로 표현해 보았습니다. A 와 B  두 가지 Activity 가 있는 데, A 라는 Activity 는 B 를 B 라는 Activity 는 다시 자기 자신인 B 를 호출 하는 경우라고 가정해 보겠습니다. 


 호출하는 Activity B 가 이미 Task 의 가장 앞에 위치하는 경우, 또 하나의 B 를 생성하는 대신, 기존에 존재하는 B Activity 가 재활용됩니다. 이 때 B 가 재활용된다는 것을 개발자가 알아채고 새롭게 전달되는 Intent 를 사용할 수 있도록 B Activity 의 onPause() / onNewIntent() / onResume() 가 순차적으로 호출됩니다. 별 생각없이 동일한 Activity 를 여러번 생성하는 것은 메모리 사용량과 Activity 시작 속도 양쪽 모두에 악영향을 끼칠 수 있습니다. (특히 이미지가 덕지덕지 붙어 있는 Activity 라면). 이런 경우 FLAG_ACTIVITY_SINGLE_TOP 를 적절하게 활용하면 제법 큰 효과를 볼 수 있습니다.


 두 번째는, FLAG_ACTIVITY_NO_HISTORY 플래그입니다. 우선 간단하게 그림으로 표현해 보았습니다. A 와 B  두 가지 Activity 가 있는 데, A 라는 Activity 는 B 를 B 라는 Activity 는 A 를 호출한 후 에 (A->B->A) 사용자가 Back 키를 누르는 경우를 가정해 보겠습니다.


 말 그대로, FLAG_ACTIVITY_NO_HISTORY 로 설정된 Intent 로 시작된 Activity B 는 Task 에 그 흔적을 남기지 않게 됩니다. B 에서 또다른 A 를 시작한 후, Back 을 누르면 일반적인 경우 이전에 실행되었던 B 가 나타나지만, NO_HISTORY 를 사용하는 경우 맨 처음에 실행 되었던 A 가 화면에 표시됩니다. 몇 가지 주의할 점이 있습니다. 우선 NO_HISTORY 를 사용하게 되면 Task 에 해당 Intent 의 정보가 기록되지 않기 때문에, A->B 인 상황 (그림에서 두 번째 단계...) 에서 홈키등을 눌러 다른 Task 로 전환된 후, 다시 본 Task 로 돌아오게 되면, A Activity 가 화면에 표시됩니다. 또한, B Activity 의 onDestroy() 가 호출되는 시점이 조금 애매합니다.일반적인 예상과는 달리, B 에서 또다른 A Activity 를 호출하는 세 번째 단계에서는 onStop 까지만 호출되고, 이 후에 새롭게 호출된 A Activity 가 사라지는 순간 (네 번째 단계) 에서야 onDestroy() 가 호출 됩니다.

 FLAG_ACTIVITY_NO_HISTORY 는 여러가지로 쓸모가 있는데, 특히 특정한 이벤트에 대한 알람등을 위해 다이얼로그 형태로 화면에 표시되는 Activity 들에 적용하기에 편리합니다. (대게의 경우 팝업은 해당 시점에 한번만 보여주면 되니까.)

 다음으로 굉장히 유용한 플래그 두 가지를 동시에 설명해보고자 합니다.FLAG_ACTIVITY_REORDER_TO_FRONT 와 FLAG_ACTIVITY_CLEAR_TOP 플래그입니다. 우선 간략하게 그림으로 살펴 보겠습니다. A Activity 에서 B Activity 를 그리고 B 에서 A 를 호출하는 상황을 가정해보았습니다. (A->B->A)


 FLAG_ACTIVITY_REORDER_TO_FRONT 는 매우 특이하게도 Task 의 순서 자체를 뒤바꿔 줍니다. 이 플래그를 사용하면, 런치하고자 하는 Activity 가 이미 Task 상에 존재하는 경우 해당 Activity 를 새롭게 생성하는 대신, 아래쪽에 위치한 Activity 의 순서를 Task 의 가장 위로 끌어올려줍니다. 따라서 A->B->A 의 순서로 Activity 호출이 일어날때, 새로운 A 가 생성되는 대신 아래쪽에 위치한 A 가 위로 올라와 최종적으로 B->A 의 형태로 Task 가 구성되게 됩니다. 어떤 Activity 에서 특정 Activity 로 점프하는 형식의 Flow 를 구성해야하는 경우 요긴하게 사용될 수도 있지만, Task 의 순서를 뒤섞는 다는 점에서 사용에 주의를 기울일 필요가 있습니다.  (별 생각없이 남발하게 되면 Back 키가를 누를 때 엉뚱한 Activity 가 표시되어 사용자들이 굉장히 혼란스러워 하는 경우가 있습니다.) 

 마지막으로 소개해 드릴 플래그는 바로 FLAG_ACTIVITY_CLEAR_TOP 입니다. 제가 개인적으로 가장 사랑스럽게 생각하는 녀석입니다. 이 플래그가 사용되는 경우  
런치하고자 하는 Activity 가 이미 Task 상에 존재하는 경우, 해당 Activity 위에 존재하는 다른 Activity 를 모두 종료시켜 줍니다. 따라서 A->B->A 로 호출이 일어나는 경우, B Activity 가 종료 되고, A Activity 만 Task 에 남게 됩니다. (A->B->C->A 인 경우에도 마찬가지로 B와 C 가 종료되고 A 만 남게 됩니다.)

  이 Flag 는 특정 어플리케이션의 대쉬보드 (혹은 홈) Activity 를 호출할 때 굉장히 유용하게 사용될 수 있습니다. 즉 하나의 어플리케이션이 하나 혹은 두 가지의 주요한 Activity 와 그 외 특정 값을 선택하는등 단순한 일을 수행하기 위한 여러 개의 Sub-Activity 로 구성되어 있다면, 주요 Activity 를 호출하는데 이 Flag 를 사용함으로서 어플리케이션의 홈버튼등을 손쉽게 구현할 수 있습니다. 또 이 Flag 는 FLAG_ACTIVITY_REORDER_TO_FRONT 와는 달린 Task 의 순서를 뒤섞지 않음으로 사용자에게도 큰 혼란을 주지 않습니다. (사용을 적극 권장합니다.)

 한 가지 주의해야할 점은 A->B->A 형태로 Activity 를 호출 하고자 할 때, 단순히 FLAG_ACTIVITY_CLEAR_TOP 만을 사용하게 되면, 기존에 생성되었던 A Activity 가 종료된 후 (onDestroy() 가 호출됨) 새롭게 A 가 생성 (onCreate()) 됩니다. 만일 기존에 사용된 A Activity 가 계속 사용되기를 원한다면, SINGLE_TOP 플래그와 함께 사용해야 합니다.





신고


Posted by injunech
2015.02.14 16:57


TestCustomDialogActivity.Java 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package arabiannight.tistory.com;
 
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
import arabiannight.tistory.com.popup.CustomDialog;
 
public class TestCustomDialogActivity extends Activity {
 
    private CustomDialog mCustomDialog;
     
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
 
    public void onClickView(View v){
        switch (v.getId()) {
        case R.id.bt_main:
            mCustomDialog = new CustomDialog(this,
                    "8월의 크리스마스!!",
                    "영화보러가자~!!!",
                    leftClickListener,
                    rightClickListener);
            mCustomDialog.show();
            break;
        }
    }
 
    private View.OnClickListener leftClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Toast.makeText(getApplicationContext(), "왼쪽버튼 Click!!",
                    Toast.LENGTH_SHORT).show();
        }
    };
 
    private View.OnClickListener rightClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Toast.makeText(getApplicationContext(), "오른쪽버튼 Click!!",
                    Toast.LENGTH_SHORT).show();
        }
    };
}



CustomDialog.Java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
package arabiannight.tistory.com.popup;
 
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.TextView;
import arabiannight.tistory.com.R;
 
public class CustomDialog extends Dialog{
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
         
        WindowManager.LayoutParams lpWindow = new WindowManager.LayoutParams();   
        lpWindow.flags = WindowManager.LayoutParams.FLAG_DIM_BEHIND;
        lpWindow.dimAmount = 0.8f;
        getWindow().setAttributes(lpWindow);
         
        setContentView(R.layout.custom_dialog);
         
        setLayout();
        setTitle(mTitle);
        setContent(mContent);
        setClickListener(mLeftClickListener , mRightClickListener);
    }
     
    public CustomDialog(Context context) {
        // Dialog 배경을 투명 처리 해준다.
        super(context , android.R.style.Theme_Translucent_NoTitleBar);
    }
     
    public CustomDialog(Context context , String title ,
            View.OnClickListener singleListener) {
        super(context , android.R.style.Theme_Translucent_NoTitleBar);
        this.mTitle = title;
        this.mLeftClickListener = singleListener;
    }
     
    public CustomDialog(Context context , String title , String content ,
            View.OnClickListener leftListener , View.OnClickListener rightListener) {
        super(context , android.R.style.Theme_Translucent_NoTitleBar);
        this.mTitle = title;
        this.mContent = content;
        this.mLeftClickListener = leftListener;
        this.mRightClickListener = rightListener;
    }
     
    private void setTitle(String title){
        mTitleView.setText(title);
    }
     
    private void setContent(String content){
        mContentView.setText(content);
    }
     
    private void setClickListener(View.OnClickListener left , View.OnClickListener right){
        if(left!=null && right!=null){
            mLeftButton.setOnClickListener(left);
            mRightButton.setOnClickListener(right);
        }else if(left!=null && right==null){
            mLeftButton.setOnClickListener(left);
        }else {
             
        }
    }
     
    private TextView mTitleView;
    private TextView mContentView;
    private Button mLeftButton;
    private Button mRightButton;
    private String mTitle;
    private String mContent;
     
    private View.OnClickListener mLeftClickListener;
    private View.OnClickListener mRightClickListener;
     
    /*
     * Layout
     */
    private void setLayout(){
        mTitleView = (TextView) findViewById(R.id.tv_title);
        mContentView = (TextView) findViewById(R.id.tv_content);
        mLeftButton = (Button) findViewById(R.id.bt_left);
        mRightButton = (Button) findViewById(R.id.bt_right);
    }
     
}



 TestCustomDialog.zip







신고


Posted by injunech
2014.09.13 19:58


안드로이드의 나인패치는 다양한 단말에 최적의 UI를 구성하기 위해 가장 필수적인 항목으로 .9.png 확장자를 가진 이미지 파일로 반복되는 영역과 패딩 영역을 이미지에 정의할 수 있다. 안드로이드 UI구성시 화면의 해상도가 다양하기 때문에 화면에 맞는 최적의 이미지를 각각 가지고 있는 것 보다 나인패치 된 이미지를 사용하는 것이 훨씬 유리하다. 나인패치를 이용하게 되면 하나의 이미지를 통해 다양한 해상도에서 최적의 UI를 구성할 수 있다.

 

나인패치 파일은 .png이미지에 1픽셀로 된 검은색((#000000) 테두리를 통해 인식이 된다. 왼쪽과 상단부분은 늘어나는 영역을 지정하게되며 겹치는 부분이 반복적으로 늘어나게된다. 오른쪽과 하단부분은 패딩부분으로 나인패치한 부분내에 컨텐츠가 들어가는 경우 정렬되는 범위이다.
1.7.2

<그림 1.7.2> 나인패치 구조

나인패치된 이미지는 아무리 늘려도 강제로 늘린 것 처럼 깨져보이는 것이 아닌 원본을 유지한 상태로 늘어나게 된다. 아래처럼 나인패치된 이미지를 늘리게 되면 늘어나는 영역의 부분이 패턴식으로 반복되어 표현되기 때문에 원본의 이미지를 유지하는 것 처럼 보인다.

 

1.7.3-1

원본 이미지

1.7.3-2강제로 늘린이미지

1.7.3-3

나인패치를 통해 늘린이미지

<그림 1.7.3> 나인패치된 이미지와 강제로 늘린이미지 비교

 

나인패치된 이미지에 텍스트나 이미지등의 콘텐츠가 들어가기 위한 배경으로 사용되는 경우 콘텐츠의 패딩영역을 지정 할 수 있다. 오른쪽과 하단부분의 중복된 영역이 패딩영역으로 이 부분에 콘텐츠가 들어가게된다.
1.7.4

<그림 1.7.4> 나인패치 패딩영역

 

나인패치를 이용하면 작은 이미지 리소스로 다양한 크기의 이미지를 깨짐없이 표현 할 수 있는 장점이 있다. 다양한 해상도를 가지는 안드로이드 단말에서 없어서는 안 될 좋은 시스템이다. 하지만 나인패치 영역을 반복적인 패턴으로 보여주기 때문에 패치역역의 첫 부분과 끝 부분이 같아야 자연스럽게 표현이 된다. 반복되는 패턴이 아닌 질감을 가지는 이미지일 경우 나인패치를 사용하기는 힘들다.

 

1.7.5-1

1.7.5-3

나인패치 이미지

1.7.5-2

1.7.5-4

나인패치된 이미지 사용

<그림 1.7.5> 질감을 가진 이미지의 나인패치

 

 

이미지 스케링에 대한 팁

 

안드로이드에서는 이미지를 자동으로 스케일링 하게 되는데, hdpi를 기준으로 나인패치를 만들었는데 xhdpi단말기에서 실행하게 되면 이미지 크기를 늘리게 된다. 이렇게 스케일링 과정 중 이미지 영역은 스케일링 되며 나인패치 영역은 스케일링이 되지 않아 설정된 나인패치 영역이 원하는 부분에 잡히지 않을 수 있다.

그림 1.7.6의 왼쪽 이미지는 스케일링 과정에 문제점이 발생된다. 상단의 늘어나는 부분의 영역과 늘어나지 않는 영역의 디자인이 명확하게 나누기 위해 나인패치 영역을 잡은 것을 볼 수 있다. 이렇게 너무 명확하게 나눠 버리는 경우 이미지가 스케일링 되면서 의도한 나인패치의 영역이 명확하게 나누기 위한 영역이 아니게 바뀌게 될 수 있다. 이와 마찬가지로 왼쪽의 늘어나는 부분을 1픽셀로 잡혀 있는데 스케일링 과정에 나인패치의 영역이 없어져 버릴 수도 있다. 그림 1.7.6의 오른쪽 이미지는 이런 스케일링의 문제점을 해결 하기 위해 상단의 늘어나는 부분은 디자인이 바뀌는 영역을 조금 피해 여유분을 주었으며, 왼쪽의 늘어나는 부분의 영역을 좀 더 크게 잡아 주었다.

 

1.7.6-1

스케일링으로 인해 문제가 있는 나인패치

1.7.6-2

스케일링에 대한 처리가 된 나인패치

 

<그림 1.7.6> 나인패치 DPI 스케일링 팁

 

  • 늘어나는 영역은 최소 2~4픽셀로 한다.
  • 늘어나는 영역 외 충분 한 영역을 준다.

 

 

나인패치 예제

 

나인패치는 버튼, 입력필드, 배경등으로 다양하게 활용 할 수 있다. 버튼의 경우 다양한 크기의 가진 버튼을 하나의 나인패치로 대응이 가능하여 어떠한 기기에서도 UI를 구성할 수 있기 때문에 나인 패치는 필수이다. 또한 리스트의 아이템의 배경으로도 많이 사용되며 다양하게 응용가능하다. 좀 더 다양항 예제를 통해 어떻게 사용하며 응용할지 알아보자.

예제1. 입력필드

입력필드에서 이미지의 가로만 늘어 나고 세로부분의 이미지는 고정되어 있어야 하는 경우 다음과 같이 나인패치가 가능하다. 그림 1.7.7은 세로로 이미지는 늘어 나지 않아야 하기 때문에 이미지의 빈 영역에 나인패치를 그린 것을 볼 수 있다. 두줄의 경우에도 영역만 늘어났지 이미지가 늘어 나지 않은 것을 확인 할 수 있다. 패딩영역을 주어 텍스트가 모두 꽉 차지 않고 좌우 위아래 패딩이 적용되어 있는 것도 주의 깊게 살펴 보자.

 

1.7.7-1

나인패치 이미지

1.7.7-2

사용된 모습

<그림 1.7.7> 나인패치 입력필드 예제

예제2. 버튼

늘어나는 부분을 자세히 보면 하나가 아닌 여러개로 나눌 수 있다. 이렇게 나누게 되면 이미지가 늘어나게 되면 비율에 맞게 늘어 난다. 그림 1.7.8에서 보면 하단  검은색 줄이 좌우와 같은 비율로 늘어난 것을 볼 수 있다.

 

1.7.8-1

나인패치 이미지

1.7.8-2

사용된 모습

 

 

<그림 1.7.8> 나인패치 버튼 예제

 

 

나인패치의 숨기는 영역(Optical Bounds)

 

안드로이드 4.3(젤리빈) 부터 늘어나는영역, 패딩영역 이외 숨기고 싶은 영역을 지정할 수 있는 기능이 생겼다. 이 부분은 기존의 패딩영역의 위치인 왼쪽/하단 부분에 정의하여 검은색(#000000)이 아닌 빨강색(#FF0000)으로 정의한다.
1.7.9

<그림 1.7.9> 나인패치 숨기는 영역

이렇게 빨강색의 숨기는 영역을 정의하게 되면 이미지가 그려질때 보이지 않게 된다. 그림 1.7.10에서 보는 것과 같이 숨기는 영역을 적용 함으로 버튼의 상/하단과 위/아래 부분의 불필요한 영역이 없어졌다. 숨기는 영역은 정의한다고 바로 사용되는 것이 아니라 버튼을 감싸고 있는 레이아웃의 layoutMode의 opticalBounds값을 통해 사용가능하다.  안드로이드 4.3부터 사용가능하며 이전 버전에서는 동작하지 않는다.

 

1.7.10-1

숨기는 영역 비 적용

1.7.10-2

숨기는 영역 적용

<그림 1.7.10> 나인패치 숨기는 영역 적용

 

나인패치는 개발자 영역이지만 UI디자인시 나인패치를 감안해서 디자인을 하기 위해 디자이너도 반드시 알아둘 필요가 있다. 디자인 편집툴을 이용해서 나인패치영역을 선택하는 것보다 안드로이드에서 기존적으로 제공하는 툴을 이용하거나 Simple Nine-patch Generator 웹사이트(http://android-ui-utils.googlecode.com/hg/asset-studio/dist/nine-patches.html) 를 이용하면 쉽게 만들 수 있다.

신고


Posted by injunech
2014.09.03 02:33


[ Android / EditText ] Keyboard 이벤트, 타입 변경



참고 

http://caliou.tistory.com/33

http://ccdev.tistory.com/31

:http://www.androidpub.com/1104990

 

 

1. 변경 부분

<EditText
     android:id="@+id/et_search"
     android:layout_width="match_parent"
     android:layout_height="40dp"
     android:layout_margin="10dp"
     android:textSize="15sp"
     android:textStyle="bold"
     android:inputType="none" />

 

표시된 부분을 수정하면 키보드 설정이 변경됩니다.

아니면 다음과 같이 해주셔도 됩니다!

타입 변경 :  imeOptions

EditText 항목 속성 중에 있습니다.
android:imeOptions="actionSearch" 이렇게 정의해주시면 검색 모드로 키보드가 뜨게됩니다.
이 외에도 여러가지 action값이 있습니다. (작성 : Question 영)
 

키보드 종류에 따른 수정은 자세하게 나와있는 블로그가 있어 스크랩했습니다.

 

속성은 세가지, Class, Variation, Flag 세가지가 있고, 각 속성은 중복되어 사용가능 합니다. 중복하여 사용하려면, |로 연결하여 사용합니다.


Class는 숫자, 문자, 비밀번호 등 입력문자의 종류를 지정합니다.

Variation은 Class의 세부적속성이 들어가죠.

Flag는 이보다 더 세부적인 속성으로, 대문자 자동변환 여러줄 입력 등의 동작을 수행한다고 합니다. 


코드에서 inputType의 속성을 변경할때에는 setInputType이나, setRawInputType메서드를 호출합니다. 


대표적인 몇가지만 정리해 보자면, 다음과 같습니다요,

 

 

inputType

설명

none

편집할 수 없는 문자열

Text

단순 문자열

textImeMultiLine

여러줄 입력 가능한 문자열

textPostalAddress

우편번호

textEmailAddress

이메일 주소

textPassword

비밀번호

textVisiblePassword

비밀번호 이지만 숫자는 보임.

number

숫자

numberSigned

숫자와 부호

numberDecimal

숫자와 부호와 소수점

phone

전화번호

datetime

날짜와 시간

 

2. 연결 및 버튼 이벤트 부분

 

아래의 코드는 위에 설정해놓은 Xml layout 코드를 연결하고 Done 버튼을 눌렀을때 검색이 실행 되도록 

제가 작성한 Java 부분 코드입니다.

검색 버튼을 눌렀을 때 처리될 이벤트 리스너는 editText.setOnEditorActionListener 메서드를 활용 하면 됩니다.

 

이전에 설명한 부분을 참고하여 Custom 하게 코드를 변경 할 경우 키보드 활용은 다양해 질 수 있습니다.

 

 

 

< Java Code >

 

 

public class SearchActivity extends Activity implements OnEditorActionListener{

 EditText et_search;
 
 /** Called when the activity is first created. */
 @Override
 public void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     setContentView(R.layout.activity);
     
     et_search = (EditText)findViewById(R.id.et_search);
     et_search.setOnEditorActionListener(this);
    
 }
}

@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
 // TODO Auto-generated method stub

 switch (actionId) {
 case EditorInfo.IME_ACTION_SEARCH:
  
  Toast.makeText(getApplicationContext(), "검색", Toast.LENGTH_LONG).show();
  
  v.setText("");
  InputMethodManager imm = (InputMethodManager)getSystemService(getApplicationContext().INPUT_METHOD_SERVICE);
  imm.toggleSoftInputFromWindow(v.getApplicationWindowToken(),InputMethodManager.SHOW_FORCED,0);
  
  break;
 default:
  return false;
 }
  
 return false;
}

 


신고


Posted by injunech
2014.03.08 14:52


치수

XML에서 씨는 치수에 대한 설명입니다. 치수는 측정의 단위라고 할 수 있겠지요. 예를 들면 10px, 2in, 5sp 등등. 아래의 측정 단위가 안드로이드에서 제공됩니다.

dp(==dip)
Density-Independent Pixels(밀도 독립 픽셀). 스크린의 물리적 밀도에 기반을 한 압축적인 단위입니다. 이 단위는 160 dpi(dots per inch) screen에 상대적입니다.
=>즉, 160dpi 스크린에서의 1px이 1dp라고 생각하시면 됩니다. 이름에서 밀도에 독립적이라고 밝힌 것과 같이, 스크린의 dpi가 다른 기계에서도 1dp의 실제 크기는 똑같다고 볼 수 있습니다.

sp
Scale-independent Pixels(배육 독립 픽셀). dp와 비슷합니다만, 사용자의 font size에 비례하게 됩니다. 이것은 font size의 크기로 쓰기를 추천합니다.
=>저는 다른 사이즈들은 대개 dp로 쓰고, 폰트 사이즈만 sp로 씁니다. 사용자가 지정해놓은 font size에 따라서 글자 크기가 변하나 봅니다.

pt
Points-스크린 사이즈의 1/72를 1pt라고 합니다.
=>스크린 사이즈에 비례해서 작업을 할 때 유용하다고 할 수 있습니다.

px
픽셀.

mm
밀리미터

in
인치

XML 작업할 때 항상 단위가 헷갈리더라구요.

특히나 지금 작업하고 있는 앱이 길이 측정 관련 앱이라서 정리가 필요하다고 생각했습니다.

좋은 정보 되시고, 굿 프로그래밍 되시길 바라요!



Dimension

A dimension value defined in XML. A dimension is specified with a number followed by a unit of measure. For example: 10px, 2in, 5sp. The following units of measure are supported by Android:

dp
Density-independent Pixels - An abstract unit that is based on the physical density of the screen. These units are relative to a 160 dpi (dots per inch) screen, on which 1dp is roughly equal to 1px. When running on a higher density screen, the number of pixels used to draw 1dp is scaled up by a factor appropriate for the screen's dpi. Likewise, when on a lower density screen, the number of pixels used for 1dp is scaled down. The ratio of dp-to-pixel will change with the screen density, but not necessarily in direct proportion. Using dp units (instead of px units) is a simple solution to making the view dimensions in your layout resize properly for different screen densities. In other words, it provides consistency for the real-world sizes of your UI elements across different devices.
sp
Scale-independent Pixels - This is like the dp unit, but it is also scaled by the user's font size preference. It is recommend you use this unit when specifying font sizes, so they will be adjusted for both the screen density and the user's preference.
pt
Points - 1/72 of an inch based on the physical size of the screen.
px
Pixels - Corresponds to actual pixels on the screen. This unit of measure is not recommended because the actual representation can vary across devices; each devices may have a different number of pixels per inch and may have more or fewer total pixels available on the screen.
mm
Millimeters - Based on the physical size of the screen.
in
Inches - Based on the physical size of the screen.


신고


Posted by injunech
2014.02.28 06:45


안드로이드 서비스를 부팅시 시작시키기 (Start Service at Boot Time)


안드로이드 폰은 부팅이 끝나면 액션이 'android.intent.action.BOOT_COMPLETED'인 인텐트를 브로드캐스트 한다. 그러므로 이 인텐트 브로트캐스트를 받을 수 있는 BroadcastReceiver가 필요하다. 

public class GPSLoggerServiceManager extends BroadcastReceiver {
  @Override
  public void onReceive(Context ctx, Intent intent) {
   if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) {
     ComponentName cName = new ComponentName(ctx.getPackageName(), GPSLogger);
     ComponentName svcName = ctx.startService(new Intent().setComponent(cName);
     if (svc == null) {
       Log.e(TAG, "Could not start service " + cName.toString());
     }
   } else {
     Log.e(TAG, "Received unexpected intent " + intent.toString());
   }
  }
}


여기서 가장 핵심은 onReceive() 메소드이다. 원하는 인텐트가 브로드캐스트 되면 onReceive() 메소드가 호출된다. 

그리고 리시버는 manifest 파일에 선언되어 있어야 한다.

<receiver android:name=".LocationLoggerServiceManager"
   android:enabled="true"
   android:exported="false"
   android:label="LocationLoggerServiceManager" >
  <intent-filter>
   <action android:name="android.intent.action.BOOT_COMPLETED" />
  </intent-filter>
</receiver>


또한 이 클래스는 보안 설정에 선언할 필요가 있는 특정 이벤트 브로드캐스트를 들어야 하기 때문에 manifest 파일에 RECEIVE_BOOT_COMPLETED 퍼미션이 있어야 한다.

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />


위와 같이 추가해주면 부팅이 끝나고 서비스가 자동으로 실행되게 된다. 

-------
* 리플을 보고 좀 더 이해하기 쉽게 전체적인 코드의 프레임웍을 첨부한다.

/src/.../BootSvc.java

package app.arsviator;
...
public class BootSvc extends Service {
  @Override
  public IBinder onBind(Intent intent) {
    return null;
  }
    
  @Override
  public void onCreate() {
    super.onCreate();
        
    Log.i("BOOTSVC", "Service started at the BOOT_COMPLETED.");
  }
}



/src/.../BRcvr.java

package app.arsviator;
...
public class BRcvr extends BroadcastReceiver {
  @Override
  public void onReceive(Context context, Intent intent) {    
    if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) {
      Log.i("BOOTSVC", "Intent received");    

      ComponentName cn = new ComponentName(context.getPackageName(), BootSvc.class.getName());
      ComponentName svcName = context.startService(new Intent().setComponent(cn));
      if (svcName == null) 
        Log.e("BOOTSVC", "Could not start service " + cn.toString());
    }
  }
}



AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="app.nautes"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
      <service android:name="BootSvc"></service>
      <receiver android:name=".BRcvr"
         android:enabled="true"
         android:exported="false"
         android:label="Broadcast Receiver" >
        <intent-filter>
          <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
      </receiver>
    </application>
</manifest> 


이 프로그램을 에뮬레이터에 설치한 다음 에뮬레이터를 종료했다가 AVD Manager에서 다시 시작시키고 부팅이 끝난 다음 logcat을 보면 다음과 같다.

09-07 09:31:30.631: INFO/SurfaceFlinger(52): Boot is finished (22889 ms)
09-07 09:31:30.661: INFO/ARMAssembler(52): generated scanline__00000177:03515104_00000A01_00000000 [ 55 ipp] (79 ins) at [0x481508:0x481644] in 5894000 ns
09-07 09:31:30.750: INFO/ActivityManager(52): Start proc com.android.email for broadcast com.android.email/com.android.exchange.BootReceiver: pid=165 uid=10008 gids={3003, 1015}
09-07 09:31:30.860: DEBUG/HomeLoaders(105):   ----> items cloned, ready to refresh UI
09-07 09:31:31.230: DEBUG/ddm-heap(165): Got feature list request
09-07 09:31:32.790: DEBUG/dalvikvm(52): GC freed 14273 objects / 744904 bytes in 444ms
09-07 09:31:33.130: INFO/ActivityThread(165): Publishing provider com.android.email.provider: com.android.email.provider.EmailProvider
09-07 09:31:33.191: INFO/ActivityThread(165): Publishing provider com.android.email.attachmentprovider: com.android.email.provider.AttachmentProvider
09-07 09:31:33.300: DEBUG/Exchange(165): BootReceiver onReceive
09-07 09:31:33.360: DEBUG/EAS SyncManager(165): !!! EAS SyncManager, onCreate
09-07 09:31:33.430: INFO/ActivityManager(52): Start proc com.android.mms for broadcast com.android.mms/.transaction.MmsSystemEventReceiver: pid=176 uid=10013 gids={3003, 1015}
09-07 09:31:33.730: DEBUG/ddm-heap(176): Got feature list request
09-07 09:31:33.810: DEBUG/EAS SyncManager(165): !!! EAS SyncManager, onStartCommand
09-07 09:31:33.870: DEBUG/EAS SyncManager(165): !!! EAS SyncManager, stopping self
09-07 09:31:33.930: DEBUG/Eas Debug(165): Logging: 
09-07 09:31:34.031: DEBUG/EAS SyncManager(165): !!! EAS SyncManager, onDestroy
09-07 09:31:34.410: DEBUG/MediaScannerService(149): start scanning volume internal
09-07 09:31:35.750: INFO/ActivityManager(52): Start proc app.nautes for broadcast app.nautes/.BRcvr: pid=195 uid=10078 gids={1015}
09-07 09:31:36.280: DEBUG/ddm-heap(195): Got feature list request
09-07 09:31:36.290: DEBUG/dalvikvm(29): GC freed 280 objects / 10704 bytes in 526ms
09-07 09:31:36.590: DEBUG/dalvikvm(29): GC freed 50 objects / 2224 bytes in 224ms
09-07 09:31:36.650: INFO/BOOTSVC(195): Intent received
09-07 09:31:36.740: INFO/BOOTSVC(195): Service started at the BOOT_COMPLETED.
09-07 09:31:36.770: DEBUG/dalvikvm(29): GC freed 2 objects / 48 bytes in 174ms
09-07 09:31:37.931: DEBUG/dalvikvm(105): GC freed 4158 objects / 281904 bytes in 199ms
09-07 09:31:38.360: DEBUG/MediaScanner(149): opendir /system/media/ failed, errno: 2
09-07 09:31:38.360: DEBUG/MediaScanner(149):  prescan time: 1474ms
09-07 09:31:38.360: DEBUG/MediaScanner(149):     scan time: 55ms
09-07 09:31:38.360: DEBUG/MediaScanner(149): postscan time: 1ms
09-07 09:31:38.360: DEBUG/MediaScanner(149):    total time: 1530ms
09-07 09:31:38.390: DEBUG/MediaScannerService(149): done scanning volume internal
09-07 09:31:39.180: DEBUG/dalvikvm(105): GC freed 3308 objects / 168792 bytes in 169ms


로그를 보면 부팅이 끝난 다음 서비스가 시작된걸 확인할 수 있다.

신고


Posted by injunech
2014.02.27 15:11


XML parse    

 

 

1. XmlPullParser 예제1.zip

 

 

신고

'Programming > Android' 카테고리의 다른 글

안드로이드 치수 크기 사이즈 size  (0) 2014.03.08
안드로이드 서비스를 부팅시 시작시키기 (Start Service at Boot Time)  (0) 2014.02.28
XML parser  (0) 2014.02.27
ViewFlipper  (0) 2014.02.27
AIDL  (0) 2014.02.25
언어별 values 값 설정  (0) 2014.02.24


Posted by injunech
2014.02.27 11:52


ViewFlipper

 

8-19. ViewFlipper 예제 _3.zip

 

신고

'Programming > Android' 카테고리의 다른 글

안드로이드 서비스를 부팅시 시작시키기 (Start Service at Boot Time)  (0) 2014.02.28
XML parser  (0) 2014.02.27
ViewFlipper  (0) 2014.02.27
AIDL  (0) 2014.02.25
언어별 values 값 설정  (0) 2014.02.24
Seekbar Example  (0) 2014.02.21


Posted by injunech
2014.02.25 15:28


AIDL

 

 

AIDL_Remote Service 예제.zip

 

신고

'Programming > Android' 카테고리의 다른 글

XML parser  (0) 2014.02.27
ViewFlipper  (0) 2014.02.27
AIDL  (0) 2014.02.25
언어별 values 값 설정  (0) 2014.02.24
Seekbar Example  (0) 2014.02.21
[Android(안드로이드) 앱 개발 기초] Fragment 기초  (0) 2014.02.19


Posted by injunech
2014.02.24 20:37


언어 (국가)

폴더 이름

(언어)

폴더 이름

(언어 + 국가)

체코어 (체코)

values-cs

values-cs-rCZ

독일어 (독일)

values-de

values-de-rDE

독일어 (오스트리아)

values-de-rAT

독일어 (스위스)

values-de-rCH

독일어 (리히텐슈타인)

valued-de-rLI

영어 (미국)

values-en

values-en-rUS

영어 (영국)

values-en-rGB

영어 (캐나다)

values-en-rCA

영어 (호주)

values-en-rAU

영어 (뉴질랜드)

values-en-rNZ

영어 (싱가포르)

values-en-rSG

스페인어 (스페인)

values-es

values-es-rES

프랑스어 (프랑스)

values-fr

values-fr-rFR

프랑스어 (벨기에)

values-fr-rBE

프랑스어 (캐나다)

values-fr-rCA

프랑스어 (스위스)

values-fr-rCH

이태리어 (이탈리아)

values-it

values-fr-rIT

이태리어 (스위스)

values-fr-rCH

일본어 (일본)

values-ja

values-ja-rJP

한국어 (대한민국)

values-ko

values-ko-rKR

네덜란드어 (네덜란드)

values-nl

values-nl-rNL

네덜란드어 (벨기에)

values-nl-nBE

폴란드어 (폴란드)

values-pl

values-pl-rPL

러시아어 (러시아)

values-ru

values-ru-rRU

중국어 (중국)

values-zh

values-zh-rCN

중국어 (대만)

values-zh-rTW





Case

Language and country codes are NOT case sensitive.

 

ISO 639: Two-letter Language Codes

Sorted by Language

 

Sorted by Language Code

AbkhazianAB AAAfar
AfarAA ABAbkhazian
AfrikaansAF AFAfrikaans
AlbanianSQ AMAmharic
AmharicAM ARArabic
ArabicAR ASAssamese
ArmenianHY AYAymara
AssameseAS AZAzerbaijani
AymaraAY BABashkir
AzerbaijaniAZ BEByelorussian
BashkirBA BGBulgarian
BasqueEU BHBihari
Bengali, BanglaBN BIBislama
BhutaniDZ BNBengali, Bangla
BihariBH BOTibetan
BislamaBI BRBreton
BretonBR CACatalan
BulgarianBG COCorsican
BurmeseMY CSCzech
ByelorussianBE CYWelsh
CambodianKM DADanish
CatalanCA DEGerman
ChineseZH DZBhutani
CorsicanCO ELGreek
CroatianHR ENEnglish, American
CzechCS EOEsperanto
DanishDA ESSpanish
DutchNL ETEstonian
English, AmericanEN EUBasque
EsperantoEO FAPersian
EstonianET FIFinnish
FaeroeseFO FJFiji
FijiFJ FOFaeroese
FinnishFI FRFrench
FrenchFR FYFrisian
FrisianFY GAIrish
Gaelic (Scots Gaelic)GD GDGaelic ("Scots Gaelic")
GalicianGL GLGalician
GeorgianKA GNGuarani
GermanDE GUGujarati
GreekEL HAHausa
GreenlandicKL HIHindi
GuaraniGN HRCroatian
GujaratiGU HUHungarian
HausaHA HYArmenian
HebrewIW IAInterlingua
HindiHI IEInterlingue
HungarianHU IKInupiak
IcelandicIS INIndonesian
IndonesianIN ISIcelandic
InterlinguaIA ITItalian
InterlingueIE IWHebrew
InupiakIK JAJapanese
IrishGA JIYiddish
ItalianIT JWJavanese
JapaneseJA KAGeorgian
JavaneseJW KKKazakh
KannadaKN KLGreenlandic
KashmiriKS KMCambodian
KazakhKK KNKannada
KinyarwandaRW KOKorean
KirghizKY KSKashmiri
KirundiRN KUKurdish
KoreanKO KYKirghiz
KurdishKU LALatin
LaothianLO LNLingala
LatinLA LOLaothian
Latvian, LettishLV LTLithuanian
LingalaLN LVLatvian, Lettish
LithuanianLT MGMalagasy
MacedonianMK MIMaori
MalagasyMG MKMacedonian
MalayMS MLMalayalam
MalayalamML MNMongolian
MalteseMT MOMoldavian
MaoriMI MRMarathi
MarathiMR MSMalay
MoldavianMO MTMaltese
MongolianMN MYBurmese
NauruNA NANauru
NepaliNE NENepali
NorwegianNO NLDutch
OccitanOC NONorwegian
OriyaOR OCOccitan
Oromo, AfanOM OMOromo, Afan
Pashto, PushtoPS OROriya
PersianFA PAPunjabi
PolishPL PLPolish
PortuguesePT PSPashto, Pushto
PunjabiPA PTPortuguese
QuechuaQU QUQuechua
Rhaeto-RomanceRM RMRhaeto-Romance
RomanianRO RNKirundi
RussianRU RORomanian
SamoanSM RURussian
SangroSG RWKinyarwanda
SanskritSA SASanskrit
SerbianSR SDSindhi
Serbo-CroatianSH SGSangro
SesothoST SHSerbo-Croatian
SetswanaTN SISinghalese
ShonaSN SKSlovak
SindhiSD SLSlovenian
SinghaleseSI SMSamoan
SiswatiSS SNShona
SlovakSK SOSomali
SlovenianSL SQAlbanian
SomaliSO SRSerbian
SpanishES SSSiswati
SudaneseSU STSesotho
SwahiliSW SUSudanese
SwedishSV SVSwedish
TagalogTL SWSwahili
TajikTG TATamil
TamilTA TETegulu
TatarTT TGTajik
TeguluTE THThai
ThaiTH TITigrinya
TibetanBO TKTurkmen
TigrinyaTI TLTagalog
TongaTO TNSetswana
TsongaTS TOTonga
TurkishTR TRTurkish
TurkmenTK TSTsonga
TwiTW TTTatar
UkrainianUK TWTwi
UrduUR UKUkrainian
UzbekUZ URUrdu
VietnameseVI UZUzbek
VolapukVO VIVietnamese
WelshCY VOVolapuk
WolofWO WOWolof
XhosaXH XHXhosa
YiddishJI YOYoruba
YorubaYO ZHChinese
ZuluZU ZUZulu

 



신고

'Programming > Android' 카테고리의 다른 글

ViewFlipper  (0) 2014.02.27
AIDL  (0) 2014.02.25
언어별 values 값 설정  (0) 2014.02.24
Seekbar Example  (0) 2014.02.21
[Android(안드로이드) 앱 개발 기초] Fragment 기초  (0) 2014.02.19
안드로이드 기본 API 활용 노하우  (0) 2014.01.23


Posted by injunech

티스토리 툴바