Android - UI

오픈소스 비즈니스 컨설팅
둘러보기로 가기 검색하러 가기

스마트폰 OS인 Android에서 UI 관련 사항을 정리 한다.

Android UI

용어 정의

density
  • 밀도 (density)
  • 물리적인 길이 안에 포함된 픽셀(px)의 수
  • dpi : density per inch
  • QVGA : 120 dpi, HTC Tatii
  • HVGA : 160 dpi, 안드로원, HTC G1
  • WVGA : 240 dpi, 넥서스원, 갤럭시A, 갤럭시S, 베가, 시리우스, 이자르
  • FWVGA : 240 dpi, 모토로이, 드로이드
  • Google Android에서의 dpi
  • ldpi : Low density, 120 dpi
  • mdpi : Midium density, 160 dpi
  • hdpi : High density, 240 dpi (이미지 작성시 기준)
dip
  • Density-independent pixel
  • 160 pixels을 기본 밀도(160 dip)로 하여 작성된 밀도에 독립적인 가상의 단위
  • pixels = dips * (density / 160)
  • dips = pixels * 160 / density
  • density로는 Android의 dpi를 사용할 것
Resolution
  • 해상도, 화면의 전체 픽셀 수
  • 예) 240 * 320

화면 크기

  • 화면 크기 및 화면 방향 구하기
Display display = null;
DisplayMetrics displayMetrics = null;
int dipWidth = 0;
int dipHeight = 0;
int orientation = 0;
       
displayMetrics = new DisplayMetrics();
display = getWindowManager().getDefaultDisplay();
display.getMetrics(displayMetrics);
       
//--- displayMetrics.density : density / 160, 0.75 (ldpi), 1.0 (mdpi), 1.5 (hdpi)
dipWidth  = (int)(displayMetrics.widthPixels  / displayMetrics.density);
dipHeight = (int)(displayMetrics.heightPixels / displayMetrics.density);
//--- 0. 세로, 1. 가로
orientation = display.getOrientation();
  • Activity에서 화면 크기 구하는 방법
    	StringBuffer buf = null;
    	WindowManager wm = null;
    	Display display = null;
    	DisplayMetrics metrics = null;
    	
    	wm = getWindowManager();
    	display = wm.getDefaultDisplay();
    	metrics = new DisplayMetrics();
    	display.getMetrics(metrics);
    	
    	buf = new StringBuffer();
    	buf.append("Window display id: " + display.getDisplayId() + "\n");
    	buf.append("Window orientation: " + display.getOrientation() + "\n");
    	buf.append("Window width: " + display.getWidth() + "\n");
    	buf.append("Window height: " + display.getHeight() + "\n");
    	buf.append("Window pixel format: " + display.getPixelFormat() + "\n");
    	buf.append("Window refresh rate: " + display.getRefreshRate() + "\n");
    	buf.append("Window width pixels: " + metrics.widthPixels + "\n");
    	buf.append("Window height pixels: " + metrics.heightPixels + "\n");
    	testMsg.setText(buf.toString());
  • 갤럭시S의 화면 크기
  • 세로 화면 크기
Window display id: 0
Window orientation: 0
Window width: 320
Window height: 533
Window pixel format: 5
Window refresh rate: 68.0
Window width pixels: 320
Window height pixels: 533
  • 가로 화면 크기
Window display id: 0
Window orientation: 1
Window width: 533
Window height: 320
Window pixel format: 5
Window refresh rate: 68.0
Window width pixels: 533
Window height pixels: 320

Resource

  • /res/layout/
  • layout-small, layout-large
  • /res/drawable/
  • drawable-ldpi, drawable-mdpi, drawable-hdpi, drawable-nodpi
  • Dimensions
  • /res/values/dimensions.xml
<resources>
    <dimen name="size">10dip</dimen>
</resources>

int size = getResources().getDimensionPixelSize(R.dimen.length);

화면 회전

  • Resource에서 화면(layout) 정의
  • 세로 화면 : /res/layout-port/~.xml
  • 가로 화면 : /res/layout-land/~.xml
  • 회전 상태 확인
  • Android 2.1
WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();

//--- orientation : 0. 세로, 1. 가로
int orientation = display.getOrientation();
  • Android 2.2
WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();

//--- Surface.ROTATION_0   : 세로
//--- Surface.ROTATION_90  : 가로
//--- Surface.ROTATION_180 : 세로
//--- Surface.ROTATION_270 : 가로
int rotation = display.getRotation();
  • 화면 회전 금지 방법 1
  • AndroidManifest.xml에서 모든 Activity에 다음을 추가 한다.
android:screenOrientation="portrait"       //--- 세로 화면 고정
android:screenOrientation="landscape"      //--- 가로 화면 고정
  • 화면 회전 금지 방법 2
//--- public void onCreate(Bundle savedInstanceState) 함수에서
//--- setContentView(~); 다음에 아래 라인을 추가 한다.
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);    //--- 세로 화면 고정
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);   //--- 가로 화면 고정
  • 화면이 회전해도 Activity가 다시 로딩되지 않도록 하는 방법
  • Activity가 다시 로딩되지 않으므로 화면의 크기는 변하지 않는다. 따라서 수작업으로 화면을 조정해 주어야 한다.
  • AndroidManifest.xml에서 모든 Activity에 다음을 추가 한다.
android:configChanges="keyboardHidden|orientation"
  • 모든 Activity에 다음을 추가 한다.
@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    switch(newConfig.orientation) {
        case Configuration.ORIENTATION_PORTRAIT:   //--- 수작업으로 세로 화면 생성
            //--- onCreate(~)에서 처리한 것을 똑같이 처리 한다.
            //--- 단, 기존에 데이터가 있는 것을 그것을 그대로 활용 한다.
            //--- 아래 break 이전의 코드는 사례이므로, 대신의 자신의 적절한 코드를 삽입 한다.
            setContentView(R.layout.infromation);
            restoreStatus();
            setupViews();
            break;
        case Configuration.ORIENTATION_LANDSCAPE:  //--- 수작업으로 가로 화면 생성
            setContentView(R.layout.infromation);
            restoreStatus();
            setupViews();
            break;
    }
}
  • 화면 회전시 정보를 저장한 후 복구하는 방법
  • public void onCreate(Bundle savedInstanceState)에 복구와 관련된 코딩을 한다.
Object obj = getLastNonConfigurationInstance()
if (obj != null) {
    HashMap<String, Object> map = (HashMap<String, Object>) obj;
    //--- 저장된 복구 데이터로 화면 또는 Thread를 복구 한다.
}
  • public void onDestroy()에 화면 종료와 관련된 코딩을 한다.
public void onDestroy() {
   if (isFinishing()) {
   	 //--- 화면이 종료될 때, Thread 처리 등을 한다.
 	 //---   worker.interrupt();
        //---   worker = null;
    } else {
      	 //--- 화면이 회전할 때
    }
    super.onDestroy();
}
  • public Object onRetainNonConfigurationInstance()에 화면 회전시 데이터를 저장하는 코딩을 한다.
public Object onRetainNonConfigurationInstance() {
    HashMap<String, Object> map = null;

    map = new HashMap<String, Object>();
    //--- 화면 또는 Thread에서 복구할 데이터를 저장 한다.
    return map;
}

View

Droid Draw

  • DroidDraw Beta : 화면을 그리면 XML (layout) 파일을 생성해 준다.

DroidDraw 001.png

주요 기능 상세 설명
File -> Open
  • Android Layout 파일을 연다.
Project -> Load ...
  • Android Layout에서 사용하는 String, Color, Arrary, Drawables 저장 폴더를 연다.
Generate
  • 드래그앤드랍 등을 사용하여 작성한 화면에 해당하는 Android Layout을 Output 영역에 생성한다.
Load
  • Output 영역에 입력된 XML 파일을 사용하여 화면을 생성 한다.

Android의 화면 구성 요소

View
  • 기본 사용자 인터페이스 클래스
public class android.view.View
implements android.graphics.drawable.Drawable.Callback,
KeyEvent.Callback, AccessibilityEventSource
ViewGroup
  • 여러 개의 자식 뷰를 담을 수 있는 뷰 클래스의 확장
public abstract class android.view.ViewGroup extends View
implements ViewParent, ViewManager
Control & Widget
  • Control : 상대적으로 간단한 기능을 구현하는 뷰의 확장
  • Widget : 복잡한 컨트롤과 좀더 복잡한 뷰의 확장
android.widget.~
Layout
  • 화면 위에 있는 자식 컨트롤의 위치를 제어하기 위해 설계된 ViewGroup 클래스의 확장
public class android.widget.FrameLayout extends ViewGroup
public class android.widget.LinearLayout extends ViewGroup
public class android.widget.RelativeLayout extends ViewGroup
public class android.widget.TableLayout extends LinearLayout
public static class LayoutParams extends android.view.ViewGroup.MarginLayoutParams
Menu
  • public interface android.view.Menu
  • MenuItem, SubMenu
  • Activity의 메뉴 관련
  • 아이콘 메뉴, 확장 메뉴, 하위 메뉴
  • OptionMenu : onCreateOptionMenu : onPrepareOptionsMenu, onOtionsItemSelected
  • ContextMenu : onCreateContextMenu, onContextItemSelected
  • PanelMenu : onCreatePanelMenu, onPreparePanel
  • TextView, TextEdit, Spinner
  • Button, ToggleButton, CheckBox (RadioButton, RadioGroup)
  • DatePicker, TimePicker
  • ProgressBar, SeekBar, RatingBar
  • Chronometer, AnalogClock, DigitalClock
  • 옵션 메뉴
  • OptionMenu, Menu, SubMenu
  • 문맥 메뉴
  • ContextMenu, onCreateContextMenu(), registerForContextMenu(), onContextItemSelected()
  • 제스처
  • GestureDetector, onGestureListener, onTouchEvent
  • 화면 방향
  • OrientationEventListener, SensorManager
  • Style, Theme
  • /tools/hierarchyviewer
  • Layout
  • FrameLayout. 중첩, Linearlayout. 선형, RelativeLayout. 상대, TableLayout. 표
  • ViewGroup
  • ImageSwitcher, ScherollView, TabHost, ListView
  • AdapterView
  • ListView, GridView, GalleryView
  • ArrayAdapter, CursorAdapter
  • ListActivity
  • TabActivity, TabHost
  • 기타
  • Switcher, Dialog, Schroll~, SlidingDrawer
  • AppWidget
  • GPS, 멀티미디어
  • 상태표시줄, 진동, 지시등, 소리내기, 알림
  • ((ViewStub) findViewById(R.id.stub_import)).setVisibility(View.VISIBLE);
  • merge

Focus

  • Focus
  • nextFocusDown, nextFocusLeft, nextFocusRight, nextFocusUp
  • View getCurrentFocus()
  • void onWindowFocusChanged(boolean hasFocus)
  • boolean hasWindowFocus()
  • xml 파일에서 view에 포커스를 가져가는 태그
<requestFocus/>

Event

  • Key
  • onKeyDown(int keyCode, KeyEvent event)
  • onKeyLongPress(int keyCode, KeyEvent event)
  • onKeyUp(int keyCode, KeyEvent event)
  • onKeyMultiple(int keyCode, int repeatCount, KeyEvent event)
  • onBackPressed()
  • onTouchEvent(MotionEvent event)
  • onTrackballEvent(MotionEvent event)
  • onWindowAttributesChanged(android.view.WindowManager.LayoutParams params)
  • onContentChanged()
  • onMenuOpened(int featureId, Menu menu)
  • onMenuItemSelected(int featureId, MenuItem item)
  • onConfigurationChanged(Configuration newConfig)
  • onLowMemory()

android.widget

AbsListView
AbsoluteLayout
AbsSeekBar
AbsSpinner
Adapter
AdapterView
AlphabetIndexer
AnalogClock
ArrayAdapter
AutoCompleteTextView
BaseAdapter
BaseExpandableListAdapter
Button
Checkable
CheckBox
CheckedTextView
Chronometer
CompoundButton
CursorAdapter
CursorTreeAdapter
DatePicker
DialerFilter
DigitalClock
EditText
ExpandableListAdapter
ExpandableListView
Filter
Filterable
FilterQueryProvider
FrameLayout
Gallery
GridView
HeaderViewListAdapter
HorizontalScrollView
ImageButton
ImageSwitcher
ImageView
LinearLayout
ListAdapter
ListView
MediaController
MultiAutoCompleteTextView
PopupWindow
ProgressBar
QuickContactBadge
RadioButton
RadioGroup
RatingBar
RelativeLayout
RemoteViews
ResourceCursorAdapter
ResourceCursorTreeAdapter
Scroller
ScrollView
SectionIndexer
SeekBar
SimpleAdapter
SimpleCursorAdapter
SimpleCursorTreeAdapter
SimpleExpandableListAdapter
SlidingDrawer
Spinner
SpinnerAdapter
TabHost
TableLayout
TableRow
TabWidget
TextSwitcher
TextView
TimePicker
Toast
ToggleButton
TwoLineListItem
VideoView
ViewAnimator
ViewFlipper
ViewSwitcher
WrapperListAdapter
ZoomButton
ZoomButtonsController
ZoomControls

TextView

  • View의 visibility 속성
  • visible: 보이는상태
  • invisible: 숨겨져있지만 자리는차지
  • gone: 숨겨지며 자리도 차지x

EditText

  • android:inputType="number"
  • textUri, textEmailAddress, textPassword, number, numberSigned, phone
  • datetime, date, time
  • none, text
  • textAutoComplete
  • textMultiLine, textImeMultiLine

Button

ListView

ListView는 다수의 자료를 목록의 형태로 보여주는 View로 Android에서 상당히 유용한 View 이다. 여기서는 예제를 사용하여 ListView에 대해 간단하게 살펴보자.

  • ListView를 사용하기 위한 구성 요소와 예제
Activity
  • 예제 - MessageActivity.java : ListView를 포함하는 화면으로 사용자가 상호 교류 한다.
Layout
  • ListView를 보여주는 Layout은 android:list와 android:empty 라는 아이디를 가진 View를 포함하여야 한다.
  • android:list : 데이터가 있을 겨우에 보여주는 ListView
  • android:empty : 데이터가 없을 경우에 보여주는 View (TextView 등 여러가지 View를 사용할 수 있다.)


  • 예제 - list_activity.xml : ListView를 포함하는 layout
  • 예제 - list_row.xml : ListView에서 각 행을 보여주는 layout
Adapter

Adapter는 목록의 형태로 데이터를 보여주는 View에서 데이터를 관리하는 용도로 사용된다. 주로 ListView, GridView, GalleryView 등에서 사용되며 BaseAdapter, ArrayAdapter, CursorAdapter 등 다양한 종류의 adapter가 존재 한다.

  • 예제 - MessageAdapter.java : ListView와 연동되어 ListView에 보여지는 데이터를 관리
데이터 클래스

ListView에서 한 행에 보여지는 데이터가 많을 경우 POJO 클래스를 만들어 관리 한다.

  • 예제 - Message.java : DB와 연동하여 데이터를 저장하는 POJO 클래스
Menu
  • 예제 - message_context.xml : ListView를 오래 누르고 있을 때 나타나는 Context Menu 정의


아래에서는 위 각각의 구성요소에 대해서 중요한 사항을 위주로 설명 한다. 단, SQLite3를 사용하여 DB에 접속하는 로직은 이 범위를 벗어나므로 생략 한다. 개인적으로 테스트용으로 만든 안드로이드 앱을 가지고 설명을 하니 이름은 향후 필요한대로 변경하여 사용하기 바란다.

  • Activity : MessageActivity.java
  • 구현의 편의상 ListActivity를 상속 받아 MessageActivity를 구현 한다.
public class MessageActivity extends ListActivity implements OnClickListener {
    private SmartAndroidApplication app = null;
    private ListView list = null;
    private MessageAdapter adapter = null;
 
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.list_activity);
        
        //--- android:list 아이디를 가진 ListView를 가져오기 위해 android.R.id.list를 사용 한다.
        list = (ListView) findViewById(android.R.id.list);
       
        //--- ListView에 Context Menu를 사용할 수 있도록 설정 한다.
        //--- Context Menu : View를 오랫동안 누르고 있을 때 표시되는 Menu
        registerForContextMenu(getListView());
        list.setItemsCanFocus(true);
       
        //--- Database를 관리하기 위해 SmartAndroidApplication 클래스를 만들어 사용 한다.
        //--- 여기서 DB(SQLite3)를 관리하는 부분은 생략 한다.
        app = (SmartAndroidApplication)getApplication();
       
        //--- getCurrentMessages() 함수는 DB를 읽어 ArrayList<Message>를 반환 한다.
        adapter = new MessageAdapter(this, app.getCurrentMessages());
       
        //--- ListView와 Adapter를 서로 연결 한다.
        //--- Adapter에 있는 데이터가 ListView에 표시 된다.
        setListAdapter(adapter);
    }

    //--- Message 등록 버튼과 입력 항목은 이번 예제에서는 생략 하였다.
    public void onClick(View v) {
    	 Message msg = null;
 
        if (v.getId() == R.id.insert_button) {
            //--- 등록 버튼을 선택되었을 경우, ListViw에서 행 등록
            msg = new Message();
            msg.setMsg("등록할 메시지");
            msg.setId(app.insertMessage(msg));  //--- DB에 메시지 등록
            adapter.add(msg);
   	 }
    }

    //--- ListView가 눌러졌을 때 실행되는 함수 이다.
    protected void onListItemClick(ListView l, View v, int position, long id) {
        super.onListItemClick(l, v, position, id);
        //--- 생략
    }
    
    //--- Context Menu를 표시 한다.
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
        switch (v.getId()) {
        case android.R.id.list:
            MenuInflater inflater = getMenuInflater();
            inflater.inflate(R.menu.message_context, menu);
        }
    }

    //--- Context Menu가 선택되었을 경우의 처리를 한다.
    public boolean onContextItemSelected(MenuItem item) {
   	 AdapterContextMenuInfo info = null;
   	 Message msg = null;
 
        if (item.getItemId() == R.id.message_menu01) {
            info = (AdapterContextMenuInfo)item.getMenuInfo();
            
            //--- ListViw에서 행의 내용 수정
            //--- ListView의 선택된 행의 번호 : info.position
            msg = adapter.getItem(info.position);
            msg.setMsg("수정할 내용");
            app.updateMessage(msg);   //--- DB에서 메시지 수정
            adapter.remove(msg);
            adapter.insert(msg, info.position);
        } else if (item.getItemId() == R.id.message_menu02) {
            info = (AdapterContextMenuInfo)item.getMenuInfo();
           
            //--- ListViw에서 행 삭제
            msg = adapter.getItem(info.position);
            app.deleteMessage(msg.getId());   //--- DB에서 메시지 삭제
            adapter.remove(msg);
        }
        return true;
    }
}
  • Layout : /res/layout/list_activity.xml
  • ListView를 구성하는 화면으로 android:list와 android:empty를 가진다.
  • android:list : 데이터가 있을 겨우에 보여주는 ListView
  • android:empty : 데이터가 없을 경우에 보여주는 View
<?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"
    >
	<EditText
		android:id="@+id/message" 
		android:layout_width="fill_parent" 
		android:layout_height="wrap_content"
		android:minLines="2"
		style="@android:style/Widget.EditText"
		>
		<requestFocus/>
	</EditText>
	<Button
		android:id="@+id/insert_button" 
		android:text="@string/insert_button" 
		android:layout_width="fill_parent" 
		android:layout_height="wrap_content" 
		style="@android:style/Widget.Button"
		/>
	<ListView 
		android:id="@+id/android:list" 
		android:layout_width="fill_parent" 
		android:layout_height="wrap_content"
		android:layout_weight="1.0"
		android:layout_gravity="center" 
		style="@android:style/Widget.ListView" 
		/>
	<TextView 
		android:id="@+id/android:empty" 
		android:text="@string/empty" 
		android:layout_width="fill_parent" 
		android:layout_height="fill_parent"
		android:gravity="center_vertical|center_horizontal"
		style="@android:style/Widget.TextView"
		/>
</LinearLayout>
  • Layout : /res/layout/list_row.xml
  • ListView에서 각 행을 표시하는 layout으로 여기서는 편의상 meseage_id와 message_msg만 사용해 보자.

<?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"
    >
    <TextView
        android:id="@+id/message_id" 
        android:layout_width="50px" 
        android:layout_height="wrap_content"
        android:gravity="left|center_vertical"
        style="@android:style/Widget.TextView"
        />
    <TextView
        android:id="@+id/message_msg" 
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content"
        android:gravity="right|center_vertical"
        style="@android:style/Widget.TextView"
        />
</LinearLayout>
  • Adapter : MessageAdapter.java
  • 구현의 편의상 BaseAdapter가 아니라 ArrayAdapter를 상속 받아 MessageAdapter를 구현 한다.
  • getView(~) 함수에서 ListView의 각 행을 표시하는 View를 생성하여 반환 한다.
public class MessageAdapter extends ArrayAdapter<Message> {
    private Activity context = null;
    private ArrayList<Message> messages = null;

    public MessageAdapter(Activity context, ArrayList<Message> messages) {
        this.context = context;
        this.messages = messages;
    }

    //--- ListView의 각 행을 표시하는 View를 생성하여 반환 한다.
    public View getView(int position, View convertView, ViewGroup parent) {
        View layout = null;
        int realPosition = 0;

        //--- 행을 표시하는 Layout을 불러 온다.
        if (null == convertView) {
            LayoutInflater inflater = context.getLayoutInflater();
            layout = inflater.inflate(R.layout.list_row, null);
        } else {
            layout = convertView;
        }

        //--- Message의 id를 화면에 표시 한다. (position 행에 표시됨)
        TextView message_id = (TextView) layout.findViewById(R.id.message_id);
        message_id.setText(Long.toString(messages.get(position).getId()));

        //--- Message의 msg를 화면에 표시 한다. (position 행에 표시됨)
        TextView message_msg = (TextView) layout.findViewById(R.id.message_msg);
        message_msg.setText(messages.get(position).getMsg());
        return layout;
    }
}
  • 데이터 클래스 : Message.java
  • 데이터를 저장하는 클래스로 여기서는 편의상 id와 msg만 사용해 보자.
public class Message implements Serializable {
    private long id = 0l;
    private String msg = null;

    public long getId() {
        return id;
    }
    public void setId(long id) {
        this.id = id;
    }
	
    public String getMsg() {
        return msg;
    }
    public void setMsg(String msg) {
        this.msg = msg; 
    }
}
  • Menu : /res/menu/message_context.xml, 메뉴 파일
  • @string/message_menu01 : 수정
  • @string/message_menu02 : 삭제
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
   <item
       android:id="@+id/message_menu01"
       android:title="@string/message_menu01" 
       android:icon="@drawable/icon"/>
   <item
       android:id="@+id/message_menu02"
       android:title="@string/message_menu02"
       android:icon="@drawable/icon"/>
</menu>

Spinner

Spinner는 여러개의 목록에서 값을 선택하고자 할 때 사용하는 View 이다. HTML에서 보면 select 태그와 동일한 기능을 한다.

  • /res/layout/~.xml
<Spinner
    android:id="@+id/max_contacts" 
    android:layout_width="200dip" 
    android:layout_height="wrap_content"
    android:prompt="@string/smartsearch_max_contacts"    //--- 선택 목록 화면에 표시할 제목
    style="@android:style/Widget.Spinner"
    >
</Spinner>
  • /res/values/~.xml
  • 선택 목록을 배열로 관리하면 편리 하다.
  • getResources().getStringArray(R.array.smartsearch_max_contacts_array)로 문자열 배열을 가져올 수 있다.
<?xml version="1.0" encoding="utf-8" ?>
<resources>
	<string-array name="smartsearch_max_contacts_array">
 	    <item>10</item>
	    <item>20</item> 
	    <item>30</item>
	    <item>40</item>
	    <item>50</item>
	    <item>100</item>
	    <item>200</item>
	    <item>500</item> 
	    <item>1000</item>
	</string-array>
</resources>
  • Activity
  • implements android.widget.AdapterView$OnItemSelectedListener 를 구현 하여야 한다.
private int maxContacts = 100;
private int maxContactsPos = 5;
private Spinner vMaxContacts = null;
ArrayAdapter<CharSequence> maxContactsAdapter= null;

vMaxContacts = (Spinner)findViewById(R.id.max_contacts);
maxContactsAdapter = ArrayAdapter.createFromResource(this, 
    R.array.smartsearch_max_contacts_array, android.R.layout.simple_spinner_item);
maxContactsAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
vMaxContacts.setAdapter(maxContactsAdapter);
vMaxContacts.setOnItemSelectedListener(this);
vMaxContacts.setSelection(maxContactsPos);      //--- 선택값을 지정할 때마다 onItemSelected 함수가 호출됨

//--- parent. 상위 View, view. 선택된 뷰, position. Adapter에서 view의 위치, id. 선택된 항목의 row id
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
    if (parent == vMaxContacts) {
        maxContactsPos = position;
        maxContacts = Integer.parseInt(parent.getItemAtPosition(position).toString());
    }
}

public void onNothingSelected(AdapterView<?> parent) {
}

Notification, Alarm

Toast

  • android.widget.Toast

화면에 일시적인 메시지를 보여 준다. 메시지는 텍스트를 사용하여 보여 주거나 뷰를 사용하여 보여 준다. 아래 그림은 Toast 메시지가 표시되는 방식을 알려 준다.
Toast 001.png

  • 메시지를 사용하여 Toast 메시지를 보여 준다.
//--- duration : 메시지가 표시되는 시간
//---    Toast.LENGTH_SHORT, Toast.LENGTH_LONG
Toast.makeText(Context context, CharSequence text, int duration).show();
Toast.makeText(Context context, int resId, int duration).show();
  • View를 사용하여 Toast 메시지를 보여 준다.
//--- View를 사용하여 메시지를 보여줄 화면을 생성 한다.
LayoutInflater inflater = getLayoutInflater();
View toastView = inflater.inflater(R.layout.toast_view, null);
TextView message = (TextView) layout.findViewById(R.id.message);
message.setText("Toast Message");

//--- Toast를 사용하여 메시지를 보여 준다.
Toast toast = new Toast(this);
toast.setView(toastView);
toast.setDuration(Toast.LENGTH_LONG);
toast.show();

Notification

  • android.app.Notification

Notification은 사용자가 지정한 시간에 메시지를 보여 주고 사용자가 등록한 Activity를 실행 한다. Notification은 Notification Manager에 의해 관리되며 화면 최상단의 상태바에 표시된다.

Activity에서 Notification을 등록하여 보자.

//--- Notification Manager를 생성 한다.
NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

//--- Notification과 동시에 실행할 Activity를 PendingIntent를 사용하여 지정 한다.
//--- 여기서는 null을 지정하여 Activity를 실행하지 않는다.
PendingIntent notifIntent = PendingIntent.getActivity(this, 0, null, 0);

//--- public Notification(int icon, CharSequence tickerText, long when)
//---    icon : 아이콘
//---    tickerText : 표시할 메시지
//---    when : Notification을 표시할 시간
Notification notif = new Notification(R.drawable.icon, "invalid userid", System.currentTimeMillis());
//--- public void setLatestEventInfo(Context context, CharSequence contentTitle, CharSequence contentText, PendingIntent contentIntent)
//---    contentTitle : Notification의 제목
//---    contentText : Notification의 내용
//---    contentIntent : 실행할 Activity를 지정하고 있는 PendingIntent
notif.setLatestEventInfo(this, "title", "text", notifIntent);
notif.number++;   
nm.notify(notif.number, notif);   //--- Notification의 고유한 번호로 notif.number를 사용 한다.

Notification이 안드로이드에 의해서 어떻게 표시되는지 그림으로 확인해 보자.

  • 화면 최상단의 상태바에 Notification 아이콘과 tickerText가 표시 된다.

Notification 01.png

  • 약간의 시간이 지난 후 다음과 같이 표시가 변경 된다. 여기서 1은 등록된 Notification 갯수 이다.

Notification 02.png

  • 화면 최상단의 상태바를 아래로 당기면 상세한 Notification 정보를 볼 수 있다.
  • "지우기" 버튼을 누르면 등록된 Notification이 삭제 된다.

Notification 03.png

AlarmManager

  • android.app.AlarmManager
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);

Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.SECOND, 30);

Intent intent = new Intent(GenerateAlarm.this, AlarmReceiver.class);
//--- PendingIntent getActivity(Context context, int requestCode, Intent intent, int flags)
//--- PendingIntent getBroadcast(Context context, int requestCode, Intent intent, int flags)
//--- PendingIntent getService(Context context, int requestCode, Intent intent, int flags)
PendingIntent appIntent = PendingIntent.getBroadcast(GenerateAlarm.this, 0, intent, 0);

//--- RTC : System.currentTimeMillis() 알람 시간
//--- RTC_WAKEUP : System.currentTimeMillis() 알람 시간, 기기 작동
//--- ELAPSED_REALTIME : SystemClock.elapsedRealtime() 알람 시간 (부팅 이후 시간)
//--- ELAPSED_REALTIME_WAKEUP : SystemClock.elapsedRealtime() 알람 시간, 기기 작동
//--- set(int type, long triggerAtTime, PendingIntent operation)
//--- setRepeating(int type, long triggerAtTime, long interval, PendingIntent operation)
am.set(AlarmManager.RTC_WAKEUP, calendar.getTimeMillis(), appIntent);

<receiver android:name=".AlarmReceiver" android:process=":remote" />

Dialog

  • AlertDialog의 종류
  • OK Cancel dialog with a message
  • OK Cancel dialog with a long message
  • List dialog
  • Progress dialog
  • Single choice list
  • Multi choice list
  • Text Entry dialog

Single choice list

  • public class AlertDialog extends Dialog
  • /res/values/~.xml
  • Dialog에서 보여줄 선택 목록을 정의 한다.
<?xml version="1.0" encoding="utf-8" ?>
<resources>
    <string-array name="smartqrcode_language_array">
        <item>UTF-8</item>
        <item>Shift_JIS</item>
        <item>ISO-8859-1</item>
    </string-array>
</resources>
  • Activity
private static final int DIALOG_SINGLE_CHOICE_CATEGORY = 0;

//--- Dialog를 화면에 표시 한다.
showDialog(DIALOG_SINGLE_CHOICE_CATEGORY);                       //--- Dialog 표시

//--- 화면에 표시할 Dialog를 작성 한다.
protected Dialog onCreateDialog(int id) {
    AlertDialog.Builder builder = null;
    AlertDialog alert = null;

    switch (id) {
    case DIALOG_SINGLE_CHOICE_CATEGORY:
        builder = new AlertDialog.Builder(this);
        builder.setIcon(R.drawable.smartqrcode_icon);            //--- 아이콘 지정
        builder.setTitle(R.string.smartqrcode_category);         //--- 제목 지정
        builder.setSingleChoiceItems(
            R.array.smartqrcode_category_array,                  //--- 선택 목록 지정
            0,                                                   //--- 초기 선택 값 지정 (0, 1, 2, ...)
            new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int item) { //--- item. 선택된 값의 index
                    String[] items = null;
                    String strItem = null;

                    items = getResources().getStringArray(R.array.smartqrcode_category_array);
                    strItem = items[item];                       //--- 선택된 항목
                    dialog.dismiss();                            //--- Dialog 닫기
                }
            }
        );
        alert = builder.create();
        break;
    }
    return alert;
}

ProgressDialog

진행 바퀴 또는 진행 바를 보여 주는 Dialog

  • Activity
private static final int DIALOG_SEARCHING = 0;

showDialog(DIALOG_SEARCHING);          //--- Dialog 보이기
dismissDialog(DIALOG_SEARCHING);       //--- Dialog 보이지 않기
removeDialog(DIALOG_SEARCHING);        //--- Dialog 완전 제거

protected Dialog onCreateDialog(int id)                 //--- showDialog(~)로 호출
protected void onPrepareDialog(int id, Dialog dialog)   //--- Dialog가 보여질 때마다 호출, 동적으로 Dialog 구성
  • onCreateDialog 사례
private static final int DIALOG_SEARCHING = 0;

protected Dialog onCreateDialog(int id) {
    ProgressDialog dialog = null;
	
    Log.i(TAG, "onCreateDialog()");
    switch (id) {
    case DIALOG_SEARCHING:
        dialog = ProgressDialog.show(SmartSearchActivity.this, "", "Searching ...", true);
        dialog.setCancelable(true);
        break;
    default:
        break;
    }
    return dialog;
}
  • DialogInterface.OnDismissListener()
  • Dialog가 종료될 때 onDismiss() 함수가 호출됨
  • DialogInterface.OnCancelListener()
  • Dialog가 취소될 때 OnCancel() 함수가 호출됨
  • 참고 문헌

디자인 가이드

  • 참고 문헌

참고 문헌