'모바일웹 > Tip&Tech' 카테고리의 다른 글
모바일웹 관련 rlqhs CSS (0) | 2013.05.23 |
---|---|
모바일웹 관련 팁앤테크 (0) | 2013.05.23 |
[펌]모바일 웹 환경 설정 하기 (0) | 2012.09.18 |
[서블릿기초] 5. 초간단 MVC 만들어보기 JSP기초정리 / JSP (0) | 2010.12.15 |
모바일웹 관련 rlqhs CSS (0) | 2013.05.23 |
---|---|
모바일웹 관련 팁앤테크 (0) | 2013.05.23 |
[펌]모바일 웹 환경 설정 하기 (0) | 2012.09.18 |
[서블릿기초] 5. 초간단 MVC 만들어보기 JSP기초정리 / JSP (0) | 2010.12.15 |
Android screen size is different for different phone models. There are some screen resolutions already defined in Android. They are:
Now let’s see how to get the screen size, @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); int ht; int wt; DisplayMetrics displaymetrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(displaymetrics); ht = displaymetrics.heightPixels; wt = displaymetrics.widthPixels; }
Here, ht will return the height & wt will return the width.
|
Android XML 과 JSON 등의 개발팁 및 예제 (0) | 2011.03.29 |
---|---|
[개발 Tip] TextView내 글자가 흘러가는 효과(marquee) 주기 | 프로그래밍 팁 (1) | 2011.03.28 |
TextView에 링크 넣어보기 (0) | 2011.03.25 |
Android task,stack,flag 자세한 설명 (0) | 2011.03.24 |
ActvityGroup에서 Spinner 사용시 오류 발행할 때 해결방안 (0) | 2011.03.24 |
TextView noteView = (TextView) findViewById(R.id.noteview);더 자세한 내용은 http://developer.android.com/resources/articles/wikinotes-linkify.html 를 참고한다.
noteView.setText(someContent);
Linkify.addLinks(noteView, Linkify.ALL);
Pattern wikiWordMatcher = Pattern.compile("\\b[A-Z]+[a-z0-9]+[A-Z][A-Za-z0-9]+\\b");
String wikiViewURL = "content://com.google.android.wikinotes.db.wikinotes/wikinotes/";
Linkify.addLinks(noteView, wikiWordMatcher, wikiViewURL);
[출처] TextView 에 브라우저를 호출하는 URL 넣기|작성자 호주 다니엘
[개발 Tip] TextView내 글자가 흘러가는 효과(marquee) 주기 | 프로그래밍 팁 (1) | 2011.03.28 |
---|---|
Get android screen size (0) | 2011.03.25 |
Android task,stack,flag 자세한 설명 (0) | 2011.03.24 |
ActvityGroup에서 Spinner 사용시 오류 발행할 때 해결방안 (0) | 2011.03.24 |
android,spinner에서 선택된 값 가져오기 (1) | 2011.03.24 |
태스크란? (Task, Activity Stack)
어피니티란? (Android Affinity)
플래그란? (Android Flag)
출처: |
|
||||
안드로이드 태스크란? (Android Task, Activity Stack)
- Task는 어플리케이션에서 실행되는 액티비티를 보관하고 관리하며 Stack형태의 연속된 Activity로 이루어진다
- 선입후출(First In Last Out)형태로 나중에 적재된 액티비티일 수록 가장 먼저 사용된다 만약 1페이지>2페이지>3페이지 순으로 액티비티를 이동했을때 실행순서대로 Task에 push해 놓았다가 back버튼을 누르면 3페이지>2페이지>1페이지순으로 Task에서 pop시켜 되돌아 간다고 생각하면 된다
- 서로 다른 어플리케이션간의 이동에도 Task를 이용해 사용자 경험(UX)를 유지시켜 준다
- 최초적재 액티비티는 Root Activity 라고 하며 어플리케이션 런처로부터 시작된다
- 마지막으로 적재되는 액티비티는 Top Activity 라고 하며 현재 화면에 활성화 되어있는 액티비티를 말한다
- Task내에는 서로 다른 어플리케이션의 액티비티들이 포함될 수 있어 어플리케이션에 경계없이 하나의 어플리케이션인것 처럼 보이게 해준다
- Task의 Stack내에 존재하는 액티비티들은 모두 묶여서 background와 foreground로 함께 이동한다 홈버튼 클릭(task interrupt => background 이동), 홈버튼 롱클릭(recent task => foreground 이동)
- Flag를 사용하여 Task내 액티비티의 흐름을 제어할 수 있다
어피니티란? (Android Affinity)
- 어플리케이션 내의 액티비티들은 하나의 어피니티를(affinity:친화력) 가지고 있다
- AndroidManifest 에서 <activity> 요소의 taskAffinity 속성을 사용해 개별 affinity가 지정 가능하다
- FLAG_ACTIVITY_NEW_TASK 플래그를 가진 인텐트 객체로 부터 호출된 allowTaskReparenting 속성을 True로 가지고 있는 액티비티에 한해 affinity가 동작한다
- 위 조건이 만족한 상황에서 시작된 액티비티는 자신과 동일한 어피니티를 갖는 태스크가 있을경우 해당 태스크로 이동한다
- 즉, [b]어피니티를 가진 A액티비티가 호출되어 해당 태스크에 속해있을때 [b]어피니티를 가진 태스크가 호출되면 A액티비티는 [b]어피니티를 가진 태스크로 이동한다
- 어피니티에 의해 태스크가 이동된 후에 back버튼으로 반환시 원래 해당하던 태스크로 돌아간다
- 하나의 어플리케이션내에서 하나 이상의 기능을 갖는 어플리케이션이 존재할경우 각 액티비티별로 다른 어피니티를 지정해 관리할 수 있다
플래그란? (Android Flag)
- AndroidManifest 에서 플래그를 사용할때에는 <activity> 요소의 launchMode 속성을 사용하며 launchMode에서 사용가능한 속성은 다음과 같이 4가지만 가능하다
standard: 스택중 어느곳에나 위치 가능하며 여러개의 인스턴스가 생성가능하다
singleTop: 스택중 어느곳에나 위치 가능하며 여러개의 인스턴스가 생성가능하고 호출한 activity와 현재 최상위 activity가(top activity) 동일한 경우 최상위 activity가 재사용 된다(기존 최상위 activity는 pop)
singleTask: 루트 액티비티로만 존재하며 하나의 인스턴스만 생성가능하다(타 task에서 동일 activity 사용불가) 다른 액티비티 실행시 동일 Task내에서 실행이 가능하다
singleInstance: 루트 액티비티로만 존재하며 하나의 인스턴스만 생성가능하고 태스크내에 해당 액티비티 하나만 속할 수 있어 다른 액티비티를 실행시키면 새로운 Task가 생성되어 (FLAG_ACTIVITY_NEW_TASK와 동일) 그 Task내에 포함된다
- 소스코드에서 플래그를 사용하고 싶을때에는 Intent에 addFlags() 또는 setFlags() 메소드를 사용한다
FLAG_ACTIVITY_NEW_TASK: 동일 affinity의 task가 있으면 그곳에 실행되고 아니면 새로운 task를 실행
FLAG_ACTIVITY_SINGLE_TOP: 상단 singleTop과 같으며, 실행시 재사용 액티비티의 실행은 onPause(), onNewIntent(), onResume() 순으로 호출된다 ☞ [B]를 single top설정: [A][B] 상태에서 [B] 호출시 => [A][재사용된B] ☞ [B]를 single top설정: [B][A] 상태에서 [B] 호출시 => [B][A][B]
FLAG_ACTIVITY_NO_HISTORY: 해당 액티비티는 재활성화시(back키를 눌러 다시 활성화될때) pop 된다 ☞ [B]를 no history설정: [A][B][A] 상태에서 back키 사용시 [A]가 pop 되고 [B] 역시 no history에 의해 pop => [A]
FLAG_ACTIVITY_REORDER_TO_FRONT: activity 호출시 이미 같은 activity가 task내에 있으면 같은 activity는 pop 시키고 해당 activity가 push 된다 ☞ [A]를 reorder to front설정: [A][B] 상태에서 [A] 호출시 같은 activity인 [A]가 pop되고 => [B][A]
FLAG_ACTIVITY_CLEAR_TOP: 해당 task에 있는 모든 activity를 pop 시키고 해당 activity가 root activity로 task에 push된다 ☞ [A]를 clear top설정: [A][B] 상태에서 [A] 호출시 모두 pop되고 => [A] 단, 해당 플래그는 액티비티를 모두 onDestroy() 시킨 후 새롭게 onCreate() 시키기 때문에 [A]를 유지하려면 FLAG_ACTIVITY_SINGLE_TOP 플래그와 함께 사용하면 된다
http://developer.android.com/reference/android/content/Intent.html#FLAG_ACTIVITY_BROUGHT_TO_FRONT
Clear Task
- Task를 오랫동안 사용하지 않고 방치해 두면 시스템은 Root Activity를 제외한 모든 액티비티를 Clear 시킨다 - 이러한 동작은 Activity의 속성을 수정하여 제어할 수 있다
alwaysRetainTaskState: Task의 Root Activity에 true로 설정되어 있다면 상단에 언급되었던 동작은 발생하지 않으며 Task는 오랜 시간 이후에도 Stack에 있는 모든 Activity를 유지한다
clearTaskOnLaunch: 이 속성이 true로 설정되어 있으면 alwaysRetainTaskState 와 정반대로 사용자가 Task를 떠났다가 다시 돌아올 때마다 항상 Stack은 Root Activity로 정리된다
finishOnTaskLaunch: 이 속성은 clearTaskOnLaunch와 유사하지만 전체 Task가 아닌 단일 Activity에서 동작한다 그리고 그것은 Root Activity를 포함한 어떤 Activity가 사라지는 원인이 될 수도 있다 true로 설정되어 있을 때, Activity는 현재 Session 동안 Task의 일부만 유지한다 만일 사용자가 해당 Task를 벗어났다가 다시 돌아오면 더이상 존재하지 않는다 |
Get android screen size (0) | 2011.03.25 |
---|---|
TextView에 링크 넣어보기 (0) | 2011.03.25 |
ActvityGroup에서 Spinner 사용시 오류 발행할 때 해결방안 (0) | 2011.03.24 |
android,spinner에서 선택된 값 가져오기 (1) | 2011.03.24 |
Custom Tab을 꾸며보자 (3) | 2011.03.23 |
have an activity group containing 3 activities. When a button is pressed, I enter into this activity group and show the 1st activity. From the 1st activity I can goto 2nd activity and from 2nd activity I can goto 3rd activity. I have a spinner in this 3rd activity layout. Problem is I am not able to click on that spinner. Error gets displayed showing:
How can I solve this issue? Can anyone plz help... Hi, Please find the code for spinner attached:
Inside requestinfo.xml,
|
|||
|
2
| Hi, The error was with the setContentView. I had given
Instead of that we should give,
And the spinner code is:
|
TextView에 링크 넣어보기 (0) | 2011.03.25 |
---|---|
Android task,stack,flag 자세한 설명 (0) | 2011.03.24 |
android,spinner에서 선택된 값 가져오기 (1) | 2011.03.24 |
Custom Tab을 꾸며보자 (3) | 2011.03.23 |
스피너 외관확장관련 링크모음 (0) | 2011.03.23 |
Android에서 Spinner를 사용하는 경우 Spinner에서 선택된 아이템을 가져오는 방법을 제시한다.
가장 간단한 String Array type을 기준으로 설명한다.
우선 Spinner에 Event Listener를 달자. (Event Listener를 다는 방법은 각자 원하는 방식으로~)
spinner.setOnItemSelectedListener(mOnItemSelectedListener); |
그리고 Event Listener를 정의한다.
/** * @brief OnItemSelectedListener - OnItemSeleted event listener */ private OnItemSelectedListener mOnItemSelectedListener = new OnItemSelectedListener() {
@Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { WLog.m(TAG, "onItemSelected() entered!!");
String selItem= (String)spinner.getSelectedItem(); Log.i(TAG, "Spinner selected item = "+selItem); }
@Override public void onNothingSelected(AdapterView<?> parent) { WLog.m(TAG, "onNothingSelected() entered!!"); } }; |
Activity가 활성화되고 Spinner가 onCreate(), onResume()에서 호출 되는 시점에서 onItemSelected() method를 호출하고 이 후는 User의 action으로 인해 Spinner에서 event가 발생했을 때 호출된다.
주의할 점은 Spinner의 ArrayItem type에 따라 getSelectedItem() method의 반환값이 다르다는 것이다. 즉 Object를 반환한다는 말이다. 이 말은 Item type에 따라 적절한 casting과 가공 과정이 필요할 수도 있다는 말이 된다.
예를 들면 Cusor의 반환이라면 다음과 같은 가공 처리 과정이 필요하다.
Cursor cursor = spinner.getSelectedItem(); cursor.movePosition(pos); String selItem = cursor.getString(cursor.getColumnIndex([Filed Name])); |
이상으로 Spinner에서 Item을 선택했을 때 해야 할 처리과정에 대한 설명을 마친다
Android task,stack,flag 자세한 설명 (0) | 2011.03.24 |
---|---|
ActvityGroup에서 Spinner 사용시 오류 발행할 때 해결방안 (0) | 2011.03.24 |
Custom Tab을 꾸며보자 (3) | 2011.03.23 |
스피너 외관확장관련 링크모음 (0) | 2011.03.23 |
requestWindowFeature(Window.FEATURE_CUSTOM_TITLE) (0) | 2011.03.22 |
Tabs can be a difficult component when you first start building Android applications. To do something as simple as change the height of the tabs you need to build a view and pass it to setIndicator in the TabSpec. It might sound confusing but hopefully this code sample helps. It uses custom tab backgrounds, tab height, and programmatic tab creation.
Image Files: MyActivity.java import android.app.Activity; //Custom Tabs int tabHeight = 40;
@Override super.onCreate(savedInstanceState); TabHost tabs = new TabHost(this); TabWidget tabWidget = new TabWidget(this); FrameLayout tabContent = new FrameLayout(this); TextView content = new TextView(this); TabSpec tspec1 = tabs.newTabSpec("Tab1"); TabSpec tspec2 = tabs.newTabSpec("Tab2"); TabSpec tspec3 = tabs.newTabSpec("Tab3"); } private TextView makeTabIndicator(String text){ TextView tabView = new TextView(this); } class PreExistingViewFactory implements TabContentFactory{ private final View preExisting; public View createTabContent(String tag) { } } res/drawable/tab_indicator.xml
<!-- Focused states -->
<!-- Pressed --> |
ActvityGroup에서 Spinner 사용시 오류 발행할 때 해결방안 (0) | 2011.03.24 |
---|---|
android,spinner에서 선택된 값 가져오기 (1) | 2011.03.24 |
스피너 외관확장관련 링크모음 (0) | 2011.03.23 |
requestWindowFeature(Window.FEATURE_CUSTOM_TITLE) (0) | 2011.03.22 |
img size 변경 관련 (0) | 2011.03.22 |
스피너의 외관 및 확장을 원하는 분에게 권장하고 싶은 사이트의 모음입니다.
1. http://www.gersic.com/blog.php?id=57
2. http://androidapps.org.ua/i_sect14_d1e12819.html
3. http://www.codeweblog.com/popupwindow-use-and-extend/
4. http://www.codeweblog.com/custom-spinner-five-steps-away/
5. http://www.codeweblog.com/department-of-famous-gate-android-8/
6. http://www.codeweblog.com/android-study-notes-one-of-the-commonly-used-controls/
7. http://www.androidpeople.com/android-spinner-default-value/
8. http://stackoverflow.com/questions/2703848/android-multiple-spinners
9. http://forums.pragprog.com/forums/67/topics/3200
10. http://www.anddev.org/viewtopic.php?p=23788
android,spinner에서 선택된 값 가져오기 (1) | 2011.03.24 |
---|---|
Custom Tab을 꾸며보자 (3) | 2011.03.23 |
requestWindowFeature(Window.FEATURE_CUSTOM_TITLE) (0) | 2011.03.22 |
img size 변경 관련 (0) | 2011.03.22 |
안드로이드 팁 모음 (0) | 2011.03.22 |
Custom Tab을 꾸며보자 (3) | 2011.03.23 |
---|---|
스피너 외관확장관련 링크모음 (0) | 2011.03.23 |
img size 변경 관련 (0) | 2011.03.22 |
안드로이드 팁 모음 (0) | 2011.03.22 |
안드로이드 외부 이미지 사용하기(ListView,WebView) (0) | 2011.03.22 |
<html>
<head>
<script type="text/javascript">
function resize(image)
{
var differenceHeight = document.body.clientHeight - image.clientHeight;
var differenceWidth = document.body.clientWidth - image.clientWidth;
if (differenceHeight < 0) differenceHeight = differenceHeight * -1;
if (differenceWidth < 0) differenceWidth = differenceWidth * -1;
if (differenceHeight > differenceWidth)
{
image.style['height'] = document.body.clientHeight + 'px';
}
else
{
image.style['width'] = document.body.clientWidth + 'px';
}
// Optional: remove margins or compensate for offset.
image.style['margin'] = 0;
document.body.style['margin'] = 0;
}
</script>
</head>
<body>
<img src="http://extremecnc.co.kr/board_data/z_product/1297766177_98262_8.jpg" onload="resize(this);" />
</body>
</html>
스피너 외관확장관련 링크모음 (0) | 2011.03.23 |
---|---|
requestWindowFeature(Window.FEATURE_CUSTOM_TITLE) (0) | 2011.03.22 |
안드로이드 팁 모음 (0) | 2011.03.22 |
안드로이드 외부 이미지 사용하기(ListView,WebView) (0) | 2011.03.22 |
Bitmap Image Resize Tip (0) | 2011.03.22 |
안드로이드_개발_팁
소스코드
SD 카드에 저장되어 있는 이미지의 Thumbnails를 표시하기requestWindowFeature(Window.FEATURE_CUSTOM_TITLE) (0) | 2011.03.22 |
---|---|
img size 변경 관련 (0) | 2011.03.22 |
안드로이드 외부 이미지 사용하기(ListView,WebView) (0) | 2011.03.22 |
Bitmap Image Resize Tip (0) | 2011.03.22 |
TabHost 에 등록되어있는 버튼의 클릭이벤트 받는법 (0) | 2011.03.21 |
drawable에 있는 이미지가 아닌 외부 이미지를 사용하는 방법을 소개합니다.
1. WebView 를 이용하는 방법
*.xml 에 아래와 같이 WebView영역을 정의합니다.
<WebView android:id="@+id/ID_IMG"
android:layout_width="80dip"
android:layout_height="60dip"
android:layout_gravity="center_vertical|center_horizontal"
android:scrollbars="none"
android:clickable="false"
android:focusable="false"></WebView>
*.java 에 아래와 같이 소스를 적용하면 끝.
// 주의: 안드로이드 버그로 ListView 안에 클릭 가능한 객체(ex. Button, WebView 등)가 존재하면
// ListView 를 클릭했을때 호출되는 OnListItemClick 이 호출되지 않습니다.
// 그래서 WebView 의 focusable을 false 로 만들어 줘야 합니다.
// 더 주의해야 할 사항은 xml에서 설정해도 적용되지 않으므로 반드시 코드상에 한번더 명시해줘야 합니다.
WebView wv = (WebView) v.findViewById(R.id.ID_IMG);
wv.setFocusable(false);
if (wv != null) wv.loadUrl( "https://t1.daumcdn.net/cfile/tistory/1946B11A4C5606ED3C" );
2. BitMap 을 이용한 방법
*.xml 에 아래와 같이 ImageView영역을 정의합니다.
<ImageView android:id="@+id/ID_IMG" android:src="@drawable/icon"
android:adjustViewBounds="true" android:layout_width="wrap_content"
android:layout_height="60dip" android:layout_margin="5px"
android:visibility="gone"/>
*.java 에 아래와 같이 소스를 적용하면 끝.
ImageView iv = (ImageView) v.findViewById(R.id.ID_IMG);
Bitmap bm = LoadImage( "https://t1.daumcdn.net/cfile/tistory/1946B11A4C5606ED3C" ) ;
Bitmap resize = Bitmap.createScaledBitmap(bm, 30, 40,true);
iv.setImageBitmap( resize ) ;
3. Drawable 을 이용한 방법
*.xml 에 아래와 같이 ImageView영역을 정의합니다.
<ImageView android:id="@+id/ID_IMG" android:src="@drawable/icon"
android:adjustViewBounds="true" android:layout_width="wrap_content"
android:layout_height="60dip" android:layout_margin="5px"
android:visibility="gone"/>
*.java 에 아래와 같이 소스를 적용하면 끝.
ImageView iv = (ImageView) v.findViewById(R.id.ID_IMG);
Drawable drawable = LoadImageFromWebOperations( "https://t1.daumcdn.net/cfile/tistory/1946B11A4C5606ED3C" );
iv.setImageDrawable(drawable);
4. URL 을 이용한 방법
*.xml 에 아래와 같이 ImageView영역을 정의합니다.
<ImageView android:id="@+id/ID_IMG" android:src="@drawable/icon"
android:adjustViewBounds="true" android:layout_width="wrap_content"
android:layout_height="60dip" android:layout_margin="5px"
android:visibility="gone"/>
*.java 에 아래와 같이 소스를 적용하면 끝.
ImageView iv = (ImageView) v.findViewById(R.id.ID_IMG);
try {
URL url = new URL("https://t1.daumcdn.net/cfile/tistory/1946B11A4C5606ED3C");
URLConnection conn =
url.openConnection();
conn.connect();
BufferedInputStream bis = new BufferedInputStream(conn.getInputStream());
Bitmap bm = BitmapFactory.decodeStream(bis); bis.close();
iv.setImageBitmap(bm);
} catch (IOException e) {
Logger.e("Androes", " " + e);
}
이렇게 다양한 방법이 있긴 하지만 아래와 같이 이미지 목록을 노출하고자 할 경우엔 1번 방법을 선호합니다.
이유인즉, 2번 ~ 4번 방법은 각 이미지를 받아서 한번더 가공하여 보여지기 때문에 부하가 너무 오래 걸립니다.
아직은 초보 개발자인 제가 쓰레드로 구현하기엔 많이 미흡하지만 지금 열심히 스터디중이기에
곧 좋은 결실 보지 않을까 싶네요!!^^
아무튼 저와 비슷한 궁금증 이나 자바/안드로이드 초보로써 이중고를 겪고 있는 저와 같은 처지에 계신분들을 위해
하나하나 해결해 나갈적마다 흔적을 남겨 놓습니다. 엄한데 시간 뺏지 않길 바라는 마음으로 말입니다
img size 변경 관련 (0) | 2011.03.22 |
---|---|
안드로이드 팁 모음 (0) | 2011.03.22 |
Bitmap Image Resize Tip (0) | 2011.03.22 |
TabHost 에 등록되어있는 버튼의 클릭이벤트 받는법 (0) | 2011.03.21 |
TabActivity / ActivityGroup / Navigation (첨부파일포함) (0) | 2011.03.21 |
[Intro]
Android에서 사용하는 이미지는 Bitmap이라는 클래스에서 다~ 알아서 해줍니다.
그리고 이런 Bitmap Object를 쉽게 만들 수 있도록 도와주는
BitmapFactory 클래스 라는 것도 있습니다.
BitmapFactory는 여러가지 소스로 부터 Bitmap Object를 만들어 주는 일을 하는데,
전부 static이며 decodeXXX 라는 이름을 가진 메소드들로 이루어져 있습니다.
XXX에는 어떤 것으로 부터 decode를 하여
Bitmap Object를 만들어 낼지에 대한 말들이 들어 가겠죠.
[Decoding Methods]
BitmapFactory.decodeByteArray() 메소드는 Camera.PictureCallback 으로 부터 받은
Jpeg 사진 데이터를 가지고 Bitmap으로 만들어 줄 때 많이 사용 합니다.
Camera.PictureCallback에서 들어오는 데이터가 byte[] 형식이기 때문에
저 메소드를 사용 해야 하는 것이죠.
BitmapFactory.decodeFile() 메소드는 파일을 그대로 읽어 옵니다.
내부적으로는 파일 경로를 가지고 FileInputStream을 만들어서 decodeStream을 합니다.
그냥 파일 경로만 쓰면 다 해주는게 편리 한 것이죠.
BitmapFactory.decodeResource() 메소드는 Resource로 부터 Bitmap을 만들어 내며
BitmapFactory.decodeStream() 메소드는 InputStream으로 부터 Bitmap을 만들어 냅니다.
뭐 그냥 이름만 봐도 알 수 있는 것들이지요.
[OutOfMemoryError??]
보통 이미지 파일을 읽어서 Resizing을 해야 할 때가 있는데,
그럴때는 BitmapFactory로 읽어서 Bitmap.createScaledBitmap() 메소드를 사용하여 줄이면
간단하게 처리 할 수 있습니다.
그런데 BitmapFactory를 사용할 때 주의해야 할 점이 있습니다.
아래의 예를 한번 보시죠.
Bitmap src = BitmapFactory.decodeFile("/sdcard/image.jpg");
Bitmap resized = Bitmap.createScaledBitmap(src, dstWidth, dstHeight, true);
이미지 파일로부터 Bitmap을 만든 다음에
다시 dstWidth, dstHeight 만큼 줄여서 resized 라는 Bitmap을 만들어 냈습니다.
보통이라면 저렇게 하는게 맞습니다.
읽어서, 줄인다.
그런데 만약 이미지 파일의 크기가 아주 크다면 어떻게 될까요?
지금 Dev Phone에서 카메라로 촬영하면
기본적으로 2048 x 1536 크기의 Jpeg 이미지가 촬영된 데이터로 넘어옵니다.
이것을 decode 하려면 3MB 정도의 메모리가 필요 할 텐데,
과연 어떤 모바일 디바이스에서 얼마나 처리 할 수 있을까요?
실제로 촬영된 Jpeg 이미지를 여러번 decoding 하다보면
아래와 같은 황당한 메세지를 발견 할 수 있습니다.
java.lang.OutOfMemoryError: bitmap size exceeds VM budget
네... OutOfMemory 입니다.
더 이상 무슨 말이 필요 하겠습니까...
메모리가 딸려서 처리를 제대로 못합니다.
이것이 실제로 decoding 후 메모리 해제가 제대로 되지 않아서 그런 것인지,
하더라도 어디서 Leak이 발생 하는지에 대한 정확한 원인은 알 수 없습니다.
이것은 엔지니어들이 해결해야 할 문제 겠죠...
하지만 메모리 에러를 피할 수 있는 방법이 있습니다.
[BitmapFactory.Options.inSampleSize]
BitmapFactory.decodeXXX 시리즈는 똑같은 메소드가 두 개씩 오버로딩 되어 있습니다.
같은 이름이지만 Signature가 다른 메소드의 차이점은
BitmapFactory.Options를 파라메터로 받느냐 안받느냐의 차이죠.
BitmapFactory.Options를 사용하게 되면 decode 할 때 여러가지 옵션을 줄 수 있습니다.
여러가지 많지만 저희가 지금 사용할 것은 inSampleSize 옵션 입니다.
inSampleSize 옵션은,
애초에 decode를 할 때 얼마만큼 줄여서 decoding을 할 지 정하는 옵션 입니다.
inSampleSize 옵션은 1보다 작은 값일때는 무조건 1로 세팅이 되며,
1보다 큰 값, N일때는 1/N 만큼 이미지를 줄여서 decoding 하게 됩니다.
즉 inSampleSize가 4라면 1/4 만큼 이미지를 줄여서 decoding 해서 Bitmap으로 만들게 되는 것이죠.
2의 지수만큼 비례할 때 가장 빠르다고 합니다.
2, 4, 8, 16... 정도 되겠죠?
그래서 만약 내가 줄이고자 하는 이미지가 1/4보다는 작고 1/8보다는 클 때,
inSampleSize 옵션에 4를 주어서 decoding 한 다음에,
Bitmap.createScaledBitmap() 메소드를 사용하여 한번 더 줄이면 됩니다.
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 4;
Bitmap src = BitmapFactory.decodeFile("/sdcard/image.jpg", options);
Bitmap resized = Bitmap.createScaledBitmap(src, dstWidth, dstHeight, true);
당연한 이야기 이겠지만,
내가 원하고자 하는 사이즈가 딱 1/4 크기라면
Bitmap.createScaledBitmap() 메소드를 쓸 필요가 없지요.
inSampleSize 옵션을 잘 활용하면 메모리 부족 현상을 대략적으로 해소 할 수 있습니다.
참고로 제가 저 옵션을 사용한 뒤로는 메모리 에러를 본적이 한~번도 없답니다.
[Appendix]
inSampleSize 옵션을 사용하면
SkScaledBitmapSampler Object (Library Level) 를 생성 하게 되는데,
Object를 만들때 정해진 SampleSize 만큼 축소하여 width와 height를 정한 뒤에 만들게 됩니다.
그러니까 애초에 축소된 사이즈로 이미지를 decoding 하는 것이죠.
[Outro]
Android의 기본 어플리케이션 소스를 분석 하다보면
상당히 테크니컬한 기법들을 많이 얻을 수 있습니다.
어떻게 이런 방법으로 만들었나 싶을 정도로 매우 정교하고 복잡하게 만들어져 있지요.
참 대단한 것 같습니다.
아 그리고 왜 dstWidth와 dstHeight 변수 선언이 없냐고 따지시는 분들 설마 없겠죠
안드로이드 팁 모음 (0) | 2011.03.22 |
---|---|
안드로이드 외부 이미지 사용하기(ListView,WebView) (0) | 2011.03.22 |
TabHost 에 등록되어있는 버튼의 클릭이벤트 받는법 (0) | 2011.03.21 |
TabActivity / ActivityGroup / Navigation (첨부파일포함) (0) | 2011.03.21 |
TabActivity 내에서 ActivityGroup을 사용할 경우의 Navigation 처리 (0) | 2011.03.21 |
안드로이드 외부 이미지 사용하기(ListView,WebView) (0) | 2011.03.22 |
---|---|
Bitmap Image Resize Tip (0) | 2011.03.22 |
TabActivity / ActivityGroup / Navigation (첨부파일포함) (0) | 2011.03.21 |
TabActivity 내에서 ActivityGroup을 사용할 경우의 Navigation 처리 (0) | 2011.03.21 |
Android 하단탭 아이폰처럼 꾸미기 (TabHost 이용) (0) | 2011.03.17 |
Bitmap Image Resize Tip (0) | 2011.03.22 |
---|---|
TabHost 에 등록되어있는 버튼의 클릭이벤트 받는법 (0) | 2011.03.21 |
TabActivity 내에서 ActivityGroup을 사용할 경우의 Navigation 처리 (0) | 2011.03.21 |
Android 하단탭 아이폰처럼 꾸미기 (TabHost 이용) (0) | 2011.03.17 |
Android Tab 관련 하단에 붙이는 거랑 인텐트 넘기는 것 팁(ActivityGroup,intent) (0) | 2011.03.17 |
오늘의 강좌는 미리 공지한대로 TabActivity 내에서 ActivityGroup을 사용할 경우의 Navigation 처리에 대한 내용입니다.
먼저 TabActivity가 동작하는 간단한 원리를 정리해 보면 다음과 같습니다.
1.
getTabHost();
1.
Intent intent =
new
Intent().setClass(
this
,
2.
com.mk.counsel.group.ViewCounselGroup.
class
);
3.
spec = tabHost.newTabSpec(
"tab01"
).setIndicator(
4.
new
TabView(
this
, R.drawable.tab1_selector,
"tab01"
)
5.
).setContent(intent);
1.
tabHost.addTab(spec);
위의 과정에서 TabSpec에 적용되는 Intent가 하나의 Activity 만을 처리하는 형태와 여러 Activity가 하나의 Tab 내에서 관리되는 경우(그림 참조)로 구성될 수 있는데 후자의 경우에 문제가 발생할 수 있습니다.
단순히 Activity를 변경하기 위해서 startActivity() 함수를 사용할 경우 TabActivity가 새로운 Activity로 변경되어 버려서 기존의 Tab 화면을 유지할 수 없다는 문제가 생기는데 이런 문제를 해결해 주기 위해서 등장한 것이 ActivityGroup 입니다.
ActivityGroup은 철저하게 Activity수행에 대한 관리와 화면처리(View)를 분리하여 관리하기 위한 용도
로 생각하시면 됩니다. Activity 수행에 대한 관리는 전적으로 LocalActivityManager에 위임하고 각종 Event 처리에 대해서는 Activity 자체에 맡기고 생성된 최종 화면(View)만 본인이 소유하고 있도록 구성되어 있습니다.(그림참조)
문제는 전형적인 ActivityGroup은 모든 Activity의 관리 권한을 LocalActivityManager에 위임한 상태이고 View만을 제공 받으므로 자체적으로 Navigation 처리를 할 수 없다는 것입니다.바로 여기서 Navigation을 관리할 대상이 정해집니다. 바로 ActivityGroup이 유일하게 소유할 수 있는 View가 바로 그것입니다. 이 View들을 ActivityGroup이 관리함으로 Navigation이 가능
해 진다는 것입니다.
01.
public
class
NavigationGroupActivity
extends
ActivityGroup {
02.
ArrayList<view> history;
// View들을 관리하기 위한 List
03.
NavigationGroupActivity group;
// Activity들이 접근하기 위한 Group
04.
05.
@Override
06.
protected
void
onCreate(Bundle savedInstanceState) {
07.
// TODO Auto-generated method stub
08.
super
.onCreate(savedInstanceState);
09.
history =
new
ArrayList<view>();
10.
group =
this
;
11.
}
12.
13.
public
void
changeView(View v) {
// 동일한 Level의 Activity를 다른 Activity로 변경하는 경우
14.
history.remove(history.size()-
1
);
15.
history.add(v);
16.
setContentView(v);
17.
}
18.
19.
public
void
replaceView(View v) {
// 새로운 Level의 Activity를 추가하는 경우
20.
Log.d(
"MK"
,
"REPLACE VIEW..."
);
21.
history.add(v);
22.
setContentView(v);
23.
}
24.
25.
public
void
back() {
// Back Key가 눌려졌을 경우에 대한 처리
26.
if
(history.size() >
1
) {
27.
history.remove(history.size()-
1
);
28.
setContentView(history.get(history.size()-
1
));
29.
}
else
{
30.
finish();
// 최상위 Level의 경우 TabActvity를 종료해야 한다.
31.
}
32.
}
33.
34.
@Override
35.
public
void
onBackPressed() {
// Back Key에 대한 Event Handler
36.
group.back();
37.
return
;
38.
}
39.
}</view></view>
위에서 언급한 내용대로 ActivityGroup이 관리할 수 있는 유일한 자원이 View 이므로 View를 저장할 List를 하나 생성합니다. 기존에는Activity가 변경될 때마다 LocalActivityManager가 넘겨주는 View를 ActivityGroup이 받아서 화면 처리만 하던 것을 조금 능동적으로 View를 직접 관리하는 것으로 바뀌었습니다. 즉 Back Key에 대한 Event가 발생하면 이를 처리할 Handler에서 ActivityGroup에게 View List에서 화면 전환 처리를 해 주라고 직접 요청하는 것입니다.
그러면 Back Key 처리는 알겠는데 새로운 Activity를 추가할 경우는 어디서 누가 호출을 해 주는지가 궁금할 것입니다. 다음의 코드를 보시기 바랍니다.
01.
public
class
NavigationActivity
extends
Activity {
02.
public
void
goNextHistory(String id,Intent intent) {
//앞으로 가기 처리
03.
NavigationGroupActivity parent = ((NavigationGroupActivity)getParent());
04.
View view = parent.group.getLocalActivityManager()
05.
.startActivity(id,intent)
06.
.getDecorView();
07.
parent.group.replaceView(view);
08.
}
09.
10.
@Override
11.
public
void
onBackPressed() {
//뒤로가기 처리
12.
NavigationGroupActivity parent = ((NavigationGroupActivity)getParent());
13.
parent.back();
14.
}
15.
}
위의 코드를 보시면 해당 Activity를 소유하고 있는 ActivityGroup을 getParent() 함수로 구한 다음에 실제 Activity의 실행을LocalActivityManager에 맡기고 있습니다.
LocalActivityManager에서 실행된(startActivity() 함수 호출) Activity의 View를 getDecoderView() 함수를 통해 얻은 다음 이 View를ActivityGroup의 view에 적용하는 모습을 볼 수 있습니다. 반대로 Back Key가 발생하면 Parent의 back 함수를 호출하여ActivityGroup내의View를 조정하여 Navigation처리를 하도록 요청합니다.
자 그럼 이제 두 클래스를 상속받은 실제 ActivityGroup 과 Activity가 어떻게 적용되는지를 살펴 보겠습니다.
아래의 코드를 보시기 바랍니다.
01.
public
class
ViewCounselGroup
extends
NavigationGroupActivity {
02.
@Override
03.
protected
void
onCreate(Bundle savedInstanceState) {
04.
// TODO Auto-generated method stub
05.
super
.onCreate(savedInstanceState);
06.
Intent intent =
new
Intent(
this
,ViewCounselMainActivity.
class
);
07.
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |Intent.FLAG_ACTIVITY_SINGLE_TOP);
08.
View view = getLocalActivityManager().startActivity(
"CounselMainActivity"
,intent)
09.
.getDecorView();
10.
replaceView(view);
11.
}
12.
13.
@Override
14.
public
void
onBackPressed() {
// Back Key에 대한 처리 요청
15.
super
.onBackPressed();
16.
}
17.
}
ViewCounselGroup이라는 ActivityGroup에서는 LocalActivityManager를 통해 초기에 실행할 Activity인 ViewCounselMainActivity라는 클래스를 Intent로 실행합니다. 이때 Intent에 적절한 Flag를 설정해 주지 않으면 LocalActivityManager가 관리하는 Stack에 Activity가 View의 저장 구조와 다른 형태로 쌓이게 되므로 Navigation이 동기화 되지 못합니다.따라서 반드시 위의 Intent Flag를 설정해 주셔야 Activity와View의 순서가 동기화 됩니다. 또한 Back Key에 대한 처리는 모든 Activity에서 처리가 되는 것이 아니라 ActivityGroup에서 실행한 맨처음 Activity에서만 Event를 받을 수 있다는 점을 꼭~~~ 기억 하셔야 합니다.
참고로 Intent에 대한 Flag 설명은 다음 주소를 참고하시기 바랍니다.
Intent가 설정되면 LocalActivityManager를 통해 Activity를 실행하고 이때 생성된 View를 ActivityGroup에 적용해 주어야 하는데 그냥 적용하면 안되고 replace()라는 함수를 통해 View를 관리하는 List에 등록한 후 화면 적용을 해 주셔야 합니다.
01.
public
class
ViewCounselMainActivity
extends
NavigationActivity
02.
implements
OnItemClickListener{
03.
04.
……중략……
05.
@Override
06.
protected
void
onCreate(Bundle savedInstanceState) {
07.
// TODO Auto-generated method stub
08.
super
.onCreate(savedInstanceState);
09.
setContentView(R.layout.view_counsel_list);
10.
adapter =
new
CounselAdapter(
this
,items);
11.
ListView view = (ListView)findViewById(R.id.counsel_list);
12.
view.setAdapter(adapter);
13.
view.setOnItemClickListener(
this
);
14.
}
15.
16.
@Override
17.
public
void
onItemClick(AdapterView<!--?--> adapter, View view,
int
position,
long
id) {
18.
Intent intent =
new
Intent(ViewCounselMainActivity.
this
,
19.
com.mk.counsel.ViewCounselDetailActivity.
class
);
20.
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |Intent.FLAG_ACTIVITY_SINGLE_TOP);
21.
intent.putExtra(
"id"
, items.get(position).id);
22.
goNextHistory(
"ViewCounselMainActivity"
,intent);
23.
}
24.
}
동작에 대한 Event 처리 등은 실행된 Activity 내에서 관리가 된다고 말씀 드렸듯이 GroupActivity에서 처음 실행된 ViewCounselMainActivity내에서 특정 아이템이 선택된 경우에 ItemClick 핸들러를 처리하고 다음 Level의 Activity로 이동을 하려고 한다면goNextHistory()를 통해 이동하고자 하는 Intent를 넘겨주면 GroupActivity 내부에서 LocalActivityManager를 통해 Intent를 수행하고 View를 GroupACtivity의 ViewList에 추가하고 화면을 전환하는 작업을 해 줍니다.
TabSpec에 Intent를 설정할 때 GroupActivity를 먼저 등록하고 GroupActivity 내에서 처음 호출할 Activity를 LocalActivityManager를 통해 실행하고 View를 얻는 과정이 핵심입니다. 이걸로 TabActivity와 ActivityGroup간의 관계 정리와 ActivityGroup에서 LocalActivityManager를 통해 Activity와 View를 관리하는 메커니즘을 살펴 보았습니다. 먼저 그림을 한번 보시고 전체 흐름을 이해하신 후에 해당 소스를 보시면 훨씬 이해가 쉬우실 것으로 생각됩니다.
다음 글에는 TabActivity 위에 TitleBar를 각 탭별로 Custom하게 만들어서 TitleBar의 메뉴와 TabActivity의 각 Tab이 상호 연동되어 구동되는 예제를 가지고 설명을 드리겠습니다. 완벽하게 돌아가는 예제를 만들어 전체 소스를 올리고 싶지만 예제를 따로 만들만한 개인적인 시간이 조금 부족한 관계로 핵심 코드만을 보여 드렸습니다. 다음 번 강좌를 기대해 주세요. ^^
LocalActivityManager에 보면 현재 Activity를 종료하는... (finish와 유사동작) 방법이 있는것으로 알고 있습니다. 현재 Activity를 종료하고 현재 Activity를 얻어서 윈도우의 DecorView를 얻어서 현재 ContentView를 갱신하는 방식으로 하면 뒤로가기가 따로 뷰를 관리 안해도 되지 않나요? (실테스트는 완벽하게 하지 않아서... 혹시 이게 안되서 그리하신건가요?) 그리고 Flag를 쓸때 문제점이 해결될수 있습니다. 현재는 자유롭게 쓸수 없죠...
현재 Activity를 LocalActivityManager를 통해서 종료 시키고 이전 Activity를 활성화 할 경우 화면상으로는 이전 Activity가 나타나지만 기존에 처리되던 상태나 화면을 그대로 다시 복원하는데 문제가 발생합니다. Intent Flag를 통해서 기존 Activity가 재사용 되도록 처리를 하더라도 화면에 대한 복원을 해 주지는 않기 때문에 인스턴스 상태를 저장하거나 복원하기 위한 처리를 따로 해 주어야 하는데 그 방법이 복잡하기 때문에 View 관리를 통해서 이동하는 것이 훨씬 간단하다고 생각되었습니다. 그리고 DecodeView를 하게 되면 근본적으로 LocalActivityManager가 Activity를 재시작하고 View를 새로 얻는 것이므로 상태 유지 자체가 안됩니다.
결국 저런 구조의 소스들은 재사용 측면에서 통째로 들고 다녀야 하는 나쁜점이 있습니다. 클래스이름에 대한 리펙토링 문제도 있구요.. (물론 이클립스의 리펙토링이 좋긴해서 다 되긴합니다.) Broadcast를 이용하는게 의존성이 낮아지기 때문에 구성이 더 깔끔해 보일거라 생각합니다.
사용해 보았지만 의존성이라는 측면은 공감을 하지만 아무래도 Message전송을 통한 Receiver를 통해 Activity의 View를 변경하는 방식보다 직접 View를 관리하는 것이 성능면에서 조금 나은 면을 보였습니다. 그리고 LocalActivityManager에서도 Stack에 Activity를 들고 다니면서 관리하고 있기 때문에 Activity View를 추가로 들고 다니는 것이 같은 원리에서 보면 큰 문제는 아니지 않을까 생각됩니다. 마지막으로 ActivityGroup을 상속받는대신 NavigationGroupActivity를 상속받고 Activity 대신 NavigationActivity 클래스를 상속 받는거 뿐이기 때문에 재사용성 측면에서도 문제가 될 부분이 없어 보이는데요...ㅠㅠ
TabHost 에 등록되어있는 버튼의 클릭이벤트 받는법 (0) | 2011.03.21 |
---|---|
TabActivity / ActivityGroup / Navigation (첨부파일포함) (0) | 2011.03.21 |
Android 하단탭 아이폰처럼 꾸미기 (TabHost 이용) (0) | 2011.03.17 |
Android Tab 관련 하단에 붙이는 거랑 인텐트 넘기는 것 팁(ActivityGroup,intent) (0) | 2011.03.17 |
Changing the Android EditText UI Widget (0) | 2011.03.15 |
TabActivity / ActivityGroup / Navigation (첨부파일포함) (0) | 2011.03.21 |
---|---|
TabActivity 내에서 ActivityGroup을 사용할 경우의 Navigation 처리 (0) | 2011.03.21 |
Android Tab 관련 하단에 붙이는 거랑 인텐트 넘기는 것 팁(ActivityGroup,intent) (0) | 2011.03.17 |
Changing the Android EditText UI Widget (0) | 2011.03.15 |
android 로그인 처리 예제 (0) | 2011.03.15 |
이번에 Tab을 사용해보면서 안것이지만.. 안드로이드에서 tab을 사용하는 방법은 정말 많다.
Activity를 상속받고 (Tabhost - TabWidget - FrameLayout).xml을 사용하는 방법도 있고 TabActivity를 상속받아 getTabHost()를 사용하여 TabHost를 가져와서 tab을 추가하는 방법도 있다.
내가 만드는건 하나의 Tab 안에서 사용자의 동작에 따라 해줘야 할게 많을 것 같아서 Tab을 Activity로 구성하는 방법으로 해봤다.
main.xml
xml은 위와 같이 TabHost안에 LinearLayout을 두고 그 안에 TabWidget과 하부 화면을 담당할 FrameLayout을 넣었다.
ImageEditorMainActivity.java
Tab 추가 전에 tabHost.setup()을 해야 한다. 만약 activity 호출을 위한 intent를 content로 설정하기 위해서는 tabHost.setup() 대신 tabHost.setup(getLocalActivityManager())을 해야 한다.
그런데 Actvity를 extends 한 경우에는 getLocalActivityManager()가 없다. 왜냐하면 TabActivity extends ActivityGroup extends Activity 이고, getLocalActivityManager()는 ActivityGroup class에 있는 메소드이 이기 때문이다.
따라서 위와 같이 extends ActivityGroup을 해주고 setup을 진행해 줘야 한다.
사실 위 스크린샷과 같이 화면 구성을 할거면 extends TabActivity 를 하여 간단하게 구현할 수 있다. 내가 이리 삽질을 한것은 tab은 하단으로, 화면은 Activity로 구성하고 싶어서다.
main.xml
|
TabActivity 내에서 ActivityGroup을 사용할 경우의 Navigation 처리 (0) | 2011.03.21 |
---|---|
Android 하단탭 아이폰처럼 꾸미기 (TabHost 이용) (0) | 2011.03.17 |
Changing the Android EditText UI Widget (0) | 2011.03.15 |
android 로그인 처리 예제 (0) | 2011.03.15 |
안드로이드 사용자 MAC 주소 및 전화번호 가져오기 (0) | 2011.03.14 |
출처 : http://mainia.tistory.com/554
개발환경 : JDK 1.5, eclipse-galileo, window XP, android Google API 2.1 |
이것은 편법인데 TabHost 안에 TabWidget 컨트롤의 위치를 아래로 내려버리는
것이다. 밑에 붙어있을수 있도록 할려면 TabWidget 옵션중 paddingTop 값을
화면 크기만큼 줘서 아래로 내린다.
그리고 탭당 들어가는 각각의 화면들은 FrameLayout 에다가 LinearLayout
화면들을 하나씩 추가해 배치시킨다.
하지만 탭아래 라인이 있어 그렇게 깔끔하게 보이지 않으며 화면 크기가
바뀔 때 마다 그 크기를 알아와서 paddingTop 값을 조정해야 되는
불편함이 있을 것 같다.
Xml 의 내용은 다음과 같다.
01 |
<!--?xml version="1.0" encoding="utf-8"?--> |
02 |
< linearlayout android:layout_height = "fill_parent" android:layout_width = "fill_parent" xmlns:android = "http://schemas.android.com/apk/res/android" android:orientation = "vertical" > |
03 |
04 |
< tabhost android:layout_height = "fill_parent" android:layout_width = "fill_parent" android:id = "@+id/edit_item_tab_host" > |
05 |
06 |
< tabwidget android:layout_height = "wrap_content" android:layout_width = "fill_parent" android:id = "@android:id/tabs" android:paddingtop = "370px" > |
07 |
08 |
< framelayout android:layout_height = "fill_parent" android:layout_width = "fill_parent" android:id = "@android:id/tabcontent" android:paddingtop = "65px" > |
09 |
< linearlayout android:layout_height = "fill_parent" android:layout_width = "fill_parent" android:orientation = "vertical" android:id = "@+id/edit_item_date_tab" android:padding = "5px" > |
10 |
< textview android:layout_height = "wrap_content" android:layout_width = "wrap_content" android:text = "date" android:textstyle = "bold" > |
11 |
</ textview ></ linearlayout > |
12 |
< linearlayout android:layout_height = "fill_parent" android:layout_width = "fill_parent" android:orientation = "vertical" android:id = "@+id/edit_item_geocontext_tab" android:padding = "5px" > |
13 |
< textview android:layout_height = "wrap_content" android:layout_width = "wrap_content" android:text = "lieu" android:textstyle = "bold" > |
14 |
</ textview ></ linearlayout > |
15 |
< linearlayout android:layout_height = "fill_parent" android:layout_width = "fill_parent" android:orientation = "vertical" android:id = "@+id/edit_item_text_tab" android:padding = "5px" > |
16 |
</ linearlayout > |
17 |
</ framelayout > |
18 |
</ tabwidget ></ tabhost > |
19 |
</ linearlayout > |
01 |
import android.app.Activity; |
02 |
import android.os.Bundle; |
03 |
import android.widget.TabHost; |
04 |
import android.widget.TabHost.TabSpec; |
05 |
06 |
import com.sample.R; |
07 |
08 |
public class TabBottom extends Activity{ |
09 |
10 |
public void onCreate(Bundle savedInstanceState) { |
11 |
super .onCreate(savedInstanceState); |
12 |
setContentView(R.layout.tab_bottom); |
13 |
14 |
TabHost tab_host = (TabHost) findViewById(R.id.edit_item_tab_host); |
15 |
tab_host.setup(); |
16 |
17 |
TabSpec ts1 = tab_host.newTabSpec( "TAB_DATE" ); |
18 |
ts1.setIndicator( "tab1" ); |
19 |
ts1.setContent(R.id.edit_item_date_tab); |
20 |
tab_host.addTab(ts1); |
21 |
22 |
TabSpec ts2 = tab_host.newTabSpec( "TAB_GEO" ); |
23 |
ts2.setIndicator( "tab2" ); |
24 |
ts2.setContent(R.id.edit_item_geocontext_tab); |
25 |
tab_host.addTab(ts2); |
26 |
27 |
TabSpec ts3 = tab_host.newTabSpec( "TAB_TEXT" ); |
28 |
ts3.setIndicator( "tab3" ); |
29 |
ts3.setContent(R.id.edit_item_text_tab); |
30 |
tab_host.addTab(ts3); |
31 |
32 |
tab_host.setCurrentTab( 0 ); |
33 |
34 |
} |
35 |
} |
This article should be useful to people who want to customize the default UI EditText as well as TextView on the Android platform. Mostly, I mean the Orange skin that appears to be hard to change. No matter how many color properties I attempted, I failed. Then, after inspecting the Android source code, picking apart how they wrote the TextView control (which EditText extends), I realized it was just a skin ofNinePatch drawables set in the background of the underlying View class. I’ll take you through the steps.
First lets look at the art that Android uses, and how they reference it. This provides a better understanding of what we need to do on our own.
Look in the <android_sdk>\platforms\android-x.x\data\res\drawable
directory. In this directory, you will notice this file, edit_text.xml:
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_window_focused="false" android:state_enabled="true" android:drawable="@drawable/textfield_default" /> <item android:state_window_focused="false" android:state_enabled="false" android:drawable="@drawable/textfield_disabled" /> <item android:state_pressed="true" android:drawable="@drawable/textfield_pressed" /> <item android:state_enabled="true" android:state_focused="true" android:drawable="@drawable/textfield_selected" /> <item android:state_enabled="true" android:drawable="@drawable/textfield_default" /> <item android:state_focused="true" android:drawable="@drawable/textfield_disabled_selected" /> <item android:drawable="@drawable/textfield_disabled" /> </selector>
This is the ColorStateList that is default for the EditText background. This file points to various background resources in each state. So, from inspection, it appears that we need to create NinePatch art for the following drawable files:
textfield_default.9.png, textfield_disabled.9.png, textfield_pressed.9.png, textfield_selected.9.png, textfield_disabled_selected.9.png, etc…
So, this is where and how Android’s default EditText gets the Orange look!
So change the look to your requirements (using gimp, photoshop, or Android’s recommended Draw9Patch tool), in my case I just did a red version of these files. Place these new png’s in your res/drawable directory. Now they can be referenced by your very own ColorStateList.
Name them .9.png
Using the example provided by the default Android edit_text.xml above, create your own version of it, pointing to your own NinePatch files. This file should live in your res/drawable directory also. Now you have a valid ColorStateList visible to styles and widgets.
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_window_focused="false" android:state_enabled="true" android:drawable="@drawable/textfield_default" /> <item android:state_window_focused="false" android:state_enabled="false" android:drawable="@drawable/textfield_disabled_red" /> <item android:state_pressed="true" android:drawable="@drawable/textfield_pressed_red" /> <item android:state_enabled="true" android:state_focused="true" android:drawable="@drawable/textfield_selected_red" /> <item android:state_enabled="true" android:drawable="@drawable/textfield_default" /> <item android:state_focused="true" android:drawable="@drawable/textfield_disabled_selected_red" /> <item android:drawable="@drawable/textfield_disabled_red" /> </selector>
Save it as red_edit_text.xml and place in your res/drawable directory.
In my case, decided to use a theme and style approach to override all EditText boxes in my Application.
From my AndroidManifest.xml application element, set the theme
android:theme="@style/mytheme"
From my theme.xml
<resources> <style name="mytheme" parent="@android:style/Theme" > <item name="android:editTextStyle">@style/red_edittext</item> </style> </resources>
From my styles.xml
<resources>
<style name="red_edittext" parent="@android:style/Widget.EditText">
<item name="android:focusable">true</item>
<item name="android:focusableInTouchMode">true</item>
<item name="android:clickable">true</item>
<item name="android:background">@drawable/red_edit_text</item>
<item name="android:textColor">@color/state_list</item>
<item name="android:gravity">center_vertical</item>
<item name="android:textColorHint">@color/default_text_color</item>
<item name="android:textColorHighlight">@color/transparent_red</item>
</style>
<style name="droiddate_btn" parent="@android:style/Widget.Button">
<item name="android:background">@drawable/btn_default_red</item>
</style>
</resources>
So now all EditText boxes should have my new red color instead of the default Orange. Although this might not be your end goal, just to change an EditText box from orange to red, it allows you to see how Android NinePatch, ColorStateList , Styles, and Themes can all work together to override and skin any control in Android. It could obviously be much more dramatic than my example below. Good luck, here is the result:
Android 하단탭 아이폰처럼 꾸미기 (TabHost 이용) (0) | 2011.03.17 |
---|---|
Android Tab 관련 하단에 붙이는 거랑 인텐트 넘기는 것 팁(ActivityGroup,intent) (0) | 2011.03.17 |
android 로그인 처리 예제 (0) | 2011.03.15 |
안드로이드 사용자 MAC 주소 및 전화번호 가져오기 (0) | 2011.03.14 |
안드로이드(Android) 의 ImageView 레이아웃 옵션과 사용예제들 (0) | 2011.03.14 |
try {
httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
// Post, check and show the result (not really
spectacular, but works):
client.execute(httpost, new BasicResponseHandler() {
@Override
public String handleResponse(HttpResponse response) {
HttpEntity entity = response.getEntity();
HttpParams params = response.getParams();
Log.i("LOGIN", "e: " + entity + " p: " + params);
return "";
}
});
} catch (Exception e) {
Log.e(getClass().getName(), "Error logging in: " +
e.getMessage(),
e);
}
}
[출처] 안드로이드 로그인 처리|작성자 프레드
Android Tab 관련 하단에 붙이는 거랑 인텐트 넘기는 것 팁(ActivityGroup,intent) (0) | 2011.03.17 |
---|---|
Changing the Android EditText UI Widget (0) | 2011.03.15 |
안드로이드 사용자 MAC 주소 및 전화번호 가져오기 (0) | 2011.03.14 |
안드로이드(Android) 의 ImageView 레이아웃 옵션과 사용예제들 (0) | 2011.03.14 |
[Day19] Android Iphone Tab UI 2 소스 (0) | 2011.03.11 |
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name = "android.permission.INTERNET"/>
<uses-permission android:name = "android.permission.READ_PHONE_STATE"/>
Mac 정보 및 전화번호 가져오기
public String getLocalPhoneNumber(){ //전화번호 TelephonyManager manager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE); return manager.getLine1Number(); } public String getLocalIpAddress() {//맥 어드레스 try { for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) { NetworkInterface intf = en.nextElement(); for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) { InetAddress inetAddress = enumIpAddr.nextElement(); if (!inetAddress.isLoopbackAddress()) { return inetAddress.getHostAddress().toString(); } } } } catch (SocketException ex) { ex.printStackTrace(); } return null; }
Changing the Android EditText UI Widget (0) | 2011.03.15 |
---|---|
android 로그인 처리 예제 (0) | 2011.03.15 |
안드로이드(Android) 의 ImageView 레이아웃 옵션과 사용예제들 (0) | 2011.03.14 |
[Day19] Android Iphone Tab UI 2 소스 (0) | 2011.03.11 |
[팁] Activity에서 XML을 이용해 Tab을 사용시 쉬운 팁 (0) | 2011.03.11 |
다음은 이미지를 표시해주는 레이아웃 ImageView 의 옵션중 android:ScaleType 에 대한
xml 에서는 표에서 나온 android:scaleType=”matrix” 로 표현하며 소스에서는
ImageView::setScaleType(ImageView.ScaleType.MATRIX) 로 구현된다.
이제 각각의 값들이 적용되는 예를 살펴보도록 하자.
그림에서 빨간색은 ImageView 의 틀을 보여주기 위해 ImageView 의 Background 값으로
준것이다. 그리고 Padding 값을 3으로 주었기 때문에 이미지가 조금 안쪽으로 당겨져 표현된다.
(1) MATRIX : ImageView 의 틀을 기준으로 해서 왼쪽 상단을 꼭지점으로 정렬된다.
이미지를 틀에 맞게 재조정하지 않는다. 틀보다 작거나 커도 그대로 표현된다.
XML : android:scaleType=”matrix”
Source : setScaleType(ImageView.ScaleType.MATRIX);
ImageView : width=287, height=316
Image : width=150, height=250
위의 경우는 이미지가 틀보다 작으므로 정상적으로 보이지만 ImageView 의 틀보다 키우게
되면 줄이지 않기 때문에 잘라져서 보이게 된다.
ImageView : width=287, height=316
Image : width=400, height=400
(2) FIT_XY : 이미지가 ImageView 틀 보다 작거나 크든지 간에 이미지를 틀에 맞추는 것이다.
비율과 상관없이 틀에 맞추기 때문에 좌우 크기가 맞지 않은 그림일 경우에는 찌그러져
보일것이다.
(3) FIX_START : 이미지크기를 틀에 맞게 비율을 줄이되 이미지 시작지점을 ImageView 왼쪽
상단에 맞추어 그림을 표현한다.
XML : android:scaleType=”fitStart”
Source : setScaleType(ImageView.ScaleType.FIT_START);
ImageView : width=287, height=316
Image : width=450, height=350
(4) FIX_CENTER : 이미지크기를 틀에 맞게 비율을 줄이되 ImageView 중앙에 맞추어 표현한다.
XML : android:scaleType=”fitCenter”
Source : setScaleType(ImageView.ScaleType.FIT_CENTER);
ImageView : width=287, height=316
Image : width=450, height=350
(5) FIX_END : 이미지크기를 틀에 맞게 비율을 줄이되 ImageView 의 오른쪽 아래에 맞추어
이미지를 표현한다.
XML : android:scaleType=”fitEnd”
Source : setScaleType(ImageView.ScaleType.FIT_END);
ImageView : width=287, height=316
(6) CENTER : 이미지크기 그대로 표현하되 이미지를 틀에 맞게 줄이지는 않는다. 그리고
ImageView 틀의 중앙에 위치시킨다.
XML : android:scaleType=”center”
Source : setScaleType(ImageView.ScaleType.CENTER);
ImageView : width=287, height=316
(7) CENTER_CROP : 6번에서의 그림은 높이가 ImageView 의 틀과 맞지 않다. 이것처럼
한쪽이 틀과 맞지 않다면 틀에 맞게 이미지를 늘이면서 다른 한쪽도 같이 비율에 맞게
증가 시킨다. 그러면 6번 그림은 높이가 증가한 비율만큼 넓이가 증가하여 표현되게 된다.
그리고 그림의 위치는 틀의 중앙에서 표현된다.
XML : android:scaleType=”centerCrop”
Source : setScaleType(ImageView.ScaleType.CENTER_CROP);
ImageView : width=287, height=316
Image : width=450, height=200
(8) CENTER_INSIDE : 7번에서의 내용과 반대로 ImageView 의 틀에 벗어나는 쪽을 맞추어
비율을 줄여 표현한다. 만약 넓이가 틀에서 벗어난다면 넓이를 틀에 맞추고 그 비율만큼
높이를 줄이게 될것이다. CENTER_CROP, CENTER_INSIDE 는 ImageView 의 틀에 맞게
이미지를 조정하는 것이 공통적인 특징이다.
XML : android:scaleType=”centerInside”
Source : setScaleType(ImageView.ScaleType.CENTER_INSIDE);
ImageView : width=287, height=316
전체소스와 XML 설정값 |
구현한 소스
01 |
import android.app.Activity; |
02 |
import android.graphics.Bitmap; |
03 |
import android.graphics.BitmapFactory; |
04 |
import android.os.Bundle; |
05 |
import android.view.View; |
06 |
import android.view.View.OnClickListener; |
07 |
import android.widget.ImageView; |
08 |
09 |
public class ViewDetail extends Activity { |
10 |
/** Called when the activity is first created. */ |
11 |
@Override |
12 |
public void onCreate(Bundle savedInstanceState) { |
13 |
super.onCreate(savedInstanceState); |
14 |
setContentView(R.layout.view_detail); |
15 |
ImageView iv = (ImageView)findViewById(R.id.imageView); |
16 |
17 |
Bitmap image = BitmapFactory.decodeResource(getResources(), R.drawable.test02); |
18 |
Bitmap resized = Bitmap.createScaledBitmap(image, 450, 200, true ); |
19 |
iv.setImageBitmap(resized); |
20 |
iv.setScaleType(ImageView.ScaleType.CENTER_INSIDE); // 레이아웃 크기에 이미지를 맞춘다 |
21 |
iv.setPadding(3, 3, 3, 3); |
22 |
iv.setOnClickListener( new OnClickListener(){ |
23 |
public void onClick(View arg0) { |
24 |
finish(); |
25 |
} |
26 |
}); |
27 |
} |
28 |
} |
view_detail.xml 설정 내용
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <ImageView android:id="@+id/imageView" android:layout_width="287px" android:layout_height="316px" android:maxWidth="287px" android:maxHeight="316px" android:background="#FF9900"/> <LinearLayout android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="50px" android:gravity="center" > <Button android:text="New Game" android:id="@+id/btnNew" android:layout_width="fill_parent" android:layout_height="fill_parent"/> </LinearLayout> </LinearLayout> |
android 로그인 처리 예제 (0) | 2011.03.15 |
---|---|
안드로이드 사용자 MAC 주소 및 전화번호 가져오기 (0) | 2011.03.14 |
[Day19] Android Iphone Tab UI 2 소스 (0) | 2011.03.11 |
[팁] Activity에서 XML을 이용해 Tab을 사용시 쉬운 팁 (0) | 2011.03.11 |
[안드로이드팁]텍스트뷰에서 글자에 선긋기 팁 (0) | 2011.03.11 |
TITLE : Android Fake Iphone UI 2 Source
Date : 2010/08/12
Description :
This is Source that make Iphone style UI by android Tab controller.
Download Link : TabTest
Reference Site :
http://sourceway.eu/wp/2010/06/android-tutorial-1-custom-tabs/
저번 시간에 포스트는 하단 이미지4개를 배치해서 Iphone 스타일로 만드는 것이였다면,
이번 시간에는 TabView를 사용해서 정석적인 방법에서 접근했다. (논란의 여지도 있어서)
Tabview을 상속받는 CustomTabView를 만들어야 하나 고민하다가
TabHost의 setIndicator로 뷰를 지정할 수있다는 사실을 알게되니(헉!) 생각보다 쉽게 해결됬다;
(Thanks to sourceway.eu~)
1. LinearLayout을 상속받는 setIndicator에 지정될 뷰를 정의한다. 각 탭의 Indecator 디자인을 의미한다.
XML로 정의해서 Inflator로 생성하면 좀더 정교한 디자인이 될 수 있겠지만, 원작자의 의견을 존중(?)했다.
private class MyView extends LinearLayout {
public MyView(Context c, int drawable, String label) {
super(c);
ImageView iv = new ImageView(c);
iv.setImageResource(drawable);
TextView tv = new TextView(c);
tv.setText(label);
tv.setGravity(0×01); /* Center */
setOrientation(LinearLayout.VERTICAL);
addView(iv);
addView(tv);
}
2. TabHost에 붙일 때 들어갈 아이콘 과 스트링 문자열을 정의한다.
정말 생각보다 간단하게 구현됫다;
spec = tabHost.newTabSpec(“player”).setIndicator(
new MyView(this, R.drawable.home, “Home”)).setContent(intent);
tabHost.addTab(spec);
3. 여기까지는 원작자의 소스를 바탕으로 설명한 것인데, 실제로 탭 이동간에 허전한 느낌이 있다.
탭 이동간 에니메이션을 처리해 줄 순서.
res-anim폴더에 anim.push_left_in.xml 에니메이션 파일을 등록한 후
translateLeftAnim = AnimationUtils.loadAnimation(this,
R.anim.push_left_in) ;
으로 장전하여 언제든지 쏠 준비를 한다.
4. TabHost을 클릭했을 때 Animation을 시작하는 리스너를 등록한다.
tabHost.setOnTabChangedListener(new OnTabChangeListener() {
// 텝이 변경될 때 에니메이션이 바뀐다.
@Override
public void onTabChanged(String tabId) {
// TODO Auto-generated method stub
// 현재 Activity에 토스트 팝업
Toast.makeText(getCurrentActivity(),
ActivityName[tabHost.getCurrentTab()] + ” Activity”,
Toast.LENGTH_SHORT).show();
// 에니메이션 출발 !
tabHost.getCurrentView().startAnimation(translateLeftAnim);
}
});
<P.S> 구현된 UI를 보니 예전에 만든 UI보다 멎지게 작동하는 것 같아서 흐믓하다.
(이의를 제기해 주신분들께 ㄳ)
하단 뷰에 이미지를 Selector를 사용해서 눌리는 효과를 주거나 에니메이션 효과를 주면 더 좋을것 같다
안드로이드 사용자 MAC 주소 및 전화번호 가져오기 (0) | 2011.03.14 |
---|---|
안드로이드(Android) 의 ImageView 레이아웃 옵션과 사용예제들 (0) | 2011.03.14 |
[팁] Activity에서 XML을 이용해 Tab을 사용시 쉬운 팁 (0) | 2011.03.11 |
[안드로이드팁]텍스트뷰에서 글자에 선긋기 팁 (0) | 2011.03.11 |
XmlPullParser 사용법 펌 (2) | 2011.03.08 |
안드로이드(Android) 의 ImageView 레이아웃 옵션과 사용예제들 (0) | 2011.03.14 |
---|---|
[Day19] Android Iphone Tab UI 2 소스 (0) | 2011.03.11 |
[안드로이드팁]텍스트뷰에서 글자에 선긋기 팁 (0) | 2011.03.11 |
XmlPullParser 사용법 펌 (2) | 2011.03.08 |
[펌]좌우로 드래그 하는 안드로이스드 (1) | 2011.03.07 |
[Day19] Android Iphone Tab UI 2 소스 (0) | 2011.03.11 |
---|---|
[팁] Activity에서 XML을 이용해 Tab을 사용시 쉬운 팁 (0) | 2011.03.11 |
XmlPullParser 사용법 펌 (2) | 2011.03.08 |
[펌]좌우로 드래그 하는 안드로이스드 (1) | 2011.03.07 |
[펌]TextSwitcher 관련 (0) | 2011.01.25 |
XML을분석하는것은 org.xmlpull.v1패키지의 XmlPullParser클래스를 사용합니다.
XmlPullParser의 인스턴스를 얻는 방법은?
android.util패키지의 XML클래스의 static메소드에 있는 newPullParser()를 호출합니다.
final XmlPullParser xmlPullParser = Xml.newPullParser();
또는 og.xmlpull.v1패키지의 XmlPullParserFactory클래스의 static메소드에 있는 XmlPullParserfactory.newInstance()를 호출해 XmlPullParserFactory의 인스턴스를 취득한 후
같은 인스턴스의 newPullParser()를 호출합니다.
final XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); final XmlPullParser xmlPullParser = factory.newPullParser(); |
XmlPullParser인스턴스의 분석하고싶은 XML을 셋트(셋팅)하는 방법은?
XmlPullParser클래스의 setInput(Reader in)、
또는 setInput(InputStream inputStream, String inputEncoding)을 호출한다.
예를들면, 이 클래스의 동작을 이해하기 위해서, 아래와 같이 코딩해 보는 것도 좋습니다.
(헬프와 같은 예입니다)
xmlPullParser.setInput(new StringReader("<foo>Hello World!</foo>"));
XmlPullParser인스턴스에 분석을 진행하는 방법은?
XmlPullParser클래스의 next()를 호출하면 반환값에 EventType와 호출되는 아래의 정수값을 얻을 수 있습니다.
또, XmlPullParser클래스의 getDepth()를 호출하면, 현재분석하고있는 계층을 얻는 것도 가능하며,
getName()을 호출하면 앨리먼트네임도 얻을 수 있습니다.
예를 들면, 아래와 같은 XML을 분석한다면
<lv1>
a
<lv2 title="test">
b
</lv2>
c
</lv1>
아래와 같은 결과가 나옵니다.
depth | eventType | name | |
0 | START_DOCUMENT | null | |
1 | START_TAG | lv1 | // <lv1> |
1 | TEXT | null | // a |
2 | START_TAG | lv2 | // <lv2> |
2 | TEXT | null | // b |
2 | END_TAG | lv2 | // </lv2> |
1 | TEXT | null | // c |
1 | END_TAG | lv1 | // </lv1> |
0 | END_DOCUMENT | null | // |
정리하면,
마지막으로 ..
중요한값은 얻었으나, TEXT의 값을 얻기 위해서는 getText(), 속성을 얻는 방법은 getAttributeValue()를 호출하면 얻을 수 있습니다.
[출처] [Android] XML PullParser|작성자 쪼꼬
[팁] Activity에서 XML을 이용해 Tab을 사용시 쉬운 팁 (0) | 2011.03.11 |
---|---|
[안드로이드팁]텍스트뷰에서 글자에 선긋기 팁 (0) | 2011.03.11 |
[펌]좌우로 드래그 하는 안드로이스드 (1) | 2011.03.07 |
[펌]TextSwitcher 관련 (0) | 2011.01.25 |
안드로이드에서 단위테스트를 위한 Junit 사용하기 (2) (0) | 2011.01.24 |
조건은 메뉴처럼 화면 하단에 존재해야 하고 좌우로 슬라이딩 되어야 한다. 두개의 image view로 이뤄진 하단 layout은 중간에 어중간하게 슬라이딩 되어서는 안된다.
MainActivity.java
main.xml
MenuSlideView.java
|
[안드로이드팁]텍스트뷰에서 글자에 선긋기 팁 (0) | 2011.03.11 |
---|---|
XmlPullParser 사용법 펌 (2) | 2011.03.08 |
[펌]TextSwitcher 관련 (0) | 2011.01.25 |
안드로이드에서 단위테스트를 위한 Junit 사용하기 (2) (0) | 2011.01.24 |
[펌]안드로이드에서 단위테스트를 위한 Junit 사용하기 (1) (0) | 2011.01.24 |
[마켓/무료]아이스마터 출시[스마트폰 사고 돈도 얻는 어플] (0) | 2011.09.02 |
---|---|
초간단 구글 맵 찾기 앱 구현 (0) | 2011.03.30 |
직접만든 ExpandableListView 의 아주 간단한 예제 (17) | 2011.01.13 |
UDP 에코 서비랑 클라이언트 (0) | 2011.01.02 |
[왕초보팁]서비스연결후 현재 보여지고 있는 엑티비티에 값 넘겨줄때 (5) | 2010.12.08 |
XmlPullParser 사용법 펌 (2) | 2011.03.08 |
---|---|
[펌]좌우로 드래그 하는 안드로이스드 (1) | 2011.03.07 |
안드로이드에서 단위테스트를 위한 Junit 사용하기 (2) (0) | 2011.01.24 |
[펌]안드로이드에서 단위테스트를 위한 Junit 사용하기 (1) (0) | 2011.01.24 |
안드로이드 키보드 보이기/안보이기 (0) | 2011.01.13 |