WOONO's Blog






Android Studio 에서 Gradle: error: unmappable character for encoding MS949 해결방법




1. 에러 화면

 



<그림 1>


<그림 1> 같이 에러가 나면서 컴파일이 되지 않는다.




2. 해결방법(1)

 




<그림 2-1>


Android Studio 가 설치 된 폴더에 bin 폴더에 보면 <그림 2-1> 같이 두 파일이 존재한다.


예) D:\Dev\Android\android-studio\bin


studio.exe.vmoptions (x86 32bit 용) 

studio.exe.vmoptions (64bit 용) 




<그림 2-2>



자신의 OS에 맞는 vmoptions 파일을 선택하고 <그림 2-2> 같이 마지막 줄에 아래 라인을 추가한다.


-Dfile.encoding=UTF-8



장점 : 프로젝트를 생성할때마다 자동으로 적용된다.





3. 해결방법(2)  




<그림 3-1>



Active Tool Window 에서 Project 의 build.gradle 파일을 <그림 3-1> 열어서 편집한다.


<그림 3-2>


<그림 3-2> 같이 아래 라인을 추가 한다.


allprojects {
    tasks.withType(Compile) {
        options.encoding = 'UTF-8'
    }
}



단점 : 프로젝트마다 build.gradle 파일에 추가를 해주어야 한다.




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

Android SystemInfo  (0) 2012.06.02
Android 제조사별 소스  (0) 2012.06.01
ListView Tips & Tricks #3: Create fancy ListViews  (1) 2012.04.25
Android - Dialog  (1) 2012.04.23
Android 에서 화면 회전하는 방법  (0) 2012.04.23
Posted by woono

Android SystemInfo

2012. 6. 2. 07:47 : Dev/Android

Android SystemInfo

아래는 shell 명령어 가져온글 입니다
시스템 기본정보: 하드웨어, 커널 등
cat /proc/version : 커널 버전
cat /proc/cpuinfo : 프로세서 정보, CPU타입, 모델 제조사 등
cat /porc/meminfo : 메모리 정보, 실제 메모리 및 가상 메모리
cat /proc/devices : 현재 커널에 설정되어 있는 장치 목록
mount : 마운트된 모든 장치 정보
df : 하드디스크 사용량
cat /porc/filesystems : 커널에 설정되어 있는 파일시스템 목록
cat /proc/swaps : 스왑 파티션의 크기와 사용량
cat /proc/interrupts : 장치가 사용중인 인터럽트(IRQ)목록 표시
cat /proc/ioports : 현재 사용중인 input/output 포트
cat /proc/partitions : 파티션 정보
cat /proc/uptime : 시스템이 얼마나 살아있었는지
cat /proc/stat : 시스템 상태에 관한 다양한 정보, CPU 사용 통계, 부팅이후 page fault 발생 횟수 등
cat /proc/zoneinfo : ZONEINFO
dmesg : 시스템 부팅시 나왔던 메시지
ps : 실행중인 프로세스 정보
ps -p - t : 프로세스와 쓰레드 목록
set or printenv : 환경설정값 출력


시스템 리소스 사용 현황
vmstat : 시스템 리소스 상황 모니터, CPU, I/O, Memory 등
cat /proc/diskstats : 디스크 utilization과 throughput. 즉 디스크 I/O현황
top : 시스템 프로세스 상황 모니터링/ 프로세스별 CPU사용량, 메모리와 스왑 사용량 등
procrank : 프로세스별 메모리
dumpsys meminfo [PID] : 해당 프로세스 메모리 상세 정보
cat /proc/[PID]/stat : 해당 프로세스에 대한 정보, 시작시간, 상태, CPU 사용량 등
cat /proc/[PID]/maps : 해당 프로세스의 메모리 맵 정보
cat /proc/vmstat : 버추얼 메모리 통계?
librank : 라이브러리별 메모리 사용량?


네트워크 관련
cat /proc/net/netlink : 네트워크 정보
netcfg : 네트워크 인터페이스와 IP주소 목록
netstat : 네트워크 연결상태 확인
nc : 네트워크용 cat 명령어(netcat)
ifconfig : 네트워크 인터페이스 설정 정보. 장치명을 파라미터로 받음. ip 주소. 서브넷마스크 등
tcpdump : 실시간 패킷 모니터링
iftop : 네트워크를 위한 top
route : 해당 호스트까지 연결하는 중간 경로 정보인 라우팅 테이블 표시
ping : 원격 호스트와의 연결 테스트
cat /proc/net/route : Route


안드로이드 제공
logcat : 로그캣 보기
pm : package manager의 약자. 패키지/permission/instrumentation/feature 목록, 패키지 설치/제거 등
am : activity manager의 약자, 액티비티 시작, Intent 브로드캐스팅, Instrumentation 시작, profiling 시작 / 중지 등
service : 안드로이드 서비스 목록 표시, 서비스에 명령 전달
monkey : 애플리케이션에 랜덤 이벤트 발생시킴. 사용자 이벤트, 시스템 이벤트의 무작위 발행
cat /data/anr/traces.txt : VM TRACES (쓰레드 덤프)
cat /proc/binder/proc/[PID] : 바인더 프로세스 상태
cat /proc/binder/xxx : 바인더 관련 정보(xxx은 transaction, transaction_log, failed_transaction_log, stats 등)
cat /data/system/packages.xml : 설치된 패키지 세팅 정보
setprop : system property 셋팅
getprop : 셋팅된 system property 목록 출력


종합 리포트
dumpsys [service] : app/service 상태정보 덤프, 서비스별로 추가 파라미터 받을 수 있음
dumpstate : device 상태정보 덤프. 상태정보를 추출하는 여러 명령어들의 조합으로 구성
dumpcrash : 애플리케이션이 crach될 때의 상태정보 덤프
bugreport : logcat + dumpsys + dumpstat

Posted by woono

안드로이드를 직접 빌드하기 위해 가장 먼저 필요한것은 소스코드입니다. 몇년전 피처폰 시절만하더라도 제조사들은 모두 꽁꽁 숨겨두고 자신들만의 소스코드에 각자들만의 휴대폰을 만들어왔습니다. 하지만 구글이 안드로이드를 공개하면서 상황은 180도 달라졌습니다. 구글은 안드로이스 소스를 100% 공개 했고, 안드로이드를 구동시키는 리눅스 커널 역시 완전공개를 원칙으로 하고 있습니다. 안드로이드를 채택한 제조사들 또한 이런 원칙을 받아 들일수 밖에 없게 되었습니다. 누구나 자유롭게 공짜로 안드로이드 소스를 다운로드 하고, 빌드하고, 자신만의 휴대폰을 만들 수 있게 된거죠.

안드로이드 소스는 크게 두부분으로 나눌 수있습니다. 바로 안드로이드와 리눅스 커널입니다. 커널은 안드로이드라는 자동차의 엔진이라고 할 수 있습니다. 구글은 이 두가지 소스를 따로 다운 받을수 있도록 관리하고 있습니다. 한번에 다운로드 받을 수 있지만 커널 소스만 다운로드 받기를 원하거나 안드로이드 소스만 원하는 사람들을 위해 그냥 따로 관리 한다고 하네요.

안드로이드 개발의 가장 먼저 그럼 이런 안드로이스 소스코드를 다운 받는 방법을 소개해 드리겠습니다. 아래 다운로드에 대한 설명은 우분투에서 안드로이드 빌드 환경에 대한 셋팅이 모드 끝났다는 가정하에 정리해봤습니다.

구글 안드로이드 소스 다운 받기

링크: http://source.android.com/source/downloading.html


(1) bin 폴더를 만들고 Path를 등록(어디서나 bin 폴더 내용을 실행할수 있게한다는 의미)
$ PATH=~/bin:$PATH

(2) repo 스크립트를 다운로드하고, 실행권한 설정
$ curl https://dl-ssl.google.com/dl/googlesource/git-repo/repo > ~/bin/repo
$ chmod a+x ~/bin/repo

(3) 소스를 다운로드하기 위한 폴더 생성
$ mkdir WORKING_DIRECTORY
$ cd WORKING_DIRECTORY

(4)최신 버전의 repo를 다운로드

$ repo init -u https://android.googlesource.com/platform/manifest
또는, 안드로이드4.0 아이스크림을 다운로드 받고 싶을때,
$ repo init -u https://android.googlesource.com/platform/manifest -b android-4.0.1_r1


(5) 소스 다운로드 하기

$ repo sync


여기까지 실행 후 30분~2시간 정도 다운로드가 자동으로 진행됩니다. 구글 서버 속도에 따라 속도가 많이 다르기 떄문에 매우 빠를 수도 있고 엄청 느릴수도 있습니다. 소스 다운로드가 끝나면 이제 폴더로 들어가 다운 받은 소스를 확인해 봅세요.

안드로이드 커널 소스 다운로드

(1) 다운받을 폴더 생성
$ mkdir kernel
$ cd kernel

(2) 커널 다운로드

git clone https://android.googlesource.com/kernel/common.git

git clone https://android.googlesource.com/kernel/goldfish.git

git clone https://android.googlesource.com/kernel/msm.git

git clone https://android.googlesource.com/kernel/omap.git

git clone https://android.googlesource.com/kernel/samsung.git

git clone https://android.googlesource.com/kernel/tegra.git



칩셋 제조사별 안드로이드 & 커널 소스 다운로드

칩셋 제조사에서 공개하는 안드로이드 소스란, 퀄컴이나 TI에서 자신들의 각 칩의 레퍼런스 보드에 맞게 포팅된 안드로이드 소스코드를 말합니다. 예를 들어 퀄컴의 경우 스냅드레곤칩에 맞게 커널과 안드로이드를 포팅해 공개하고 있고, TI 역시 omap칩으로 만든 레퍼런스 보드용 안드로이드를 포팅에 공개하게 됩니다. 모든 휴대폰 개발의 기본이 되는 안드로이드 코드라고 할수 있죠.

(1) 퀄컴 칩 소스 다운로드
퀄컴에서는 codeaurora.org라를 비영리커뮤니티 사이트를 이용해 각 칩셋별 코드를 공개하고 있습니다. 각 칩셋별 소스코드 다운로드 방법은 아래 주소에서 확인 할 수 있습니다.
링크: https://www.codeaurora.org/xwiki/bin/QAEP/
웹 Git: https://www.codeaurora.org/gitweb/quic/la/

예) msm8660 칩셋의 ics 코드를 다운로드 하고 싶을때

$ repo init -u git://codeaurora.org/platform/manifest.git -b ics -m M8260AAABQNLZA30112.xml --repo-url=git://codeaurora.org/tools/repo.git$ repo sync

$ repo sync



(2) TI OMAP 칩 소스 다운로드
TI 역시 Omap칩 레퍼런스 보드인 Panda보드용 안드로이드 소스를 공개하고 있습니다. 최근 출시된 갤럭시 넥서스가 마로 omap4460칩으로 만들어 졌기 떄문에 안드로이드 4.0 소스코드도 같이 공개 하고 있습니다.
링크: http://omappedia.org/wiki/Main_Page
웹 Git: http://omapzoom.org

안드로이드 소스 받기

$ repo init -u git://git.omapzoom.org/platform/omapmanifest.git
$ repo sync


커널 소스 받기

$ git clone git://git.omapzoom.org/kernel/omap.git



휴대폰 제조사별 오픈소스 웹 링크

각 제조사별로 휴대폰을 출시하게 되면 GNU 라이센스에 따라 커널 전체 코드와 안드로이드일부 코드를 공개하게 되어 있습니다. 이 소스들을 다운로드 받아 안드로이드 원본 소스랑 합치면 이제 휴대폰을 위한 가장 기본적인 커스텀 롬이 탄생하게 됩니다. 대부분의 소스코드는 압축파일 형태로 웹에서 직접 다운로드 받을 수 있습니다.

(1) 삼성 전자 오픈소스
opensource.samsung.com

(2) LG 전자 오픈소스
http://www.lg.com/global/support/opensource/opensource.jsp

(3) HTC 오픈소스
http://htcdev.com/devcenter/downloads


(5) 모토로라
http://sourceforge.net/motorola/
각 오픈소스 사이트에서 원하는 모델의 파일을 다운로드 받아 폴더에 압축을 풀면 됩니다. 오픈소스 라이센스에는 공개되는 코드는 빌드 가능해야하고, 빌드하는 방법 또한 공개하도록 하고 있기 떄문에 각 오픈소스 압축을 풀게 되면 간단한 빌드 방법을 확인할 수 있습니다


Posted by woono

Note: I apologize to all diligent readers of this blog but I need to give a small reminder to those who have not read the two first articles of the ‘ListView Tips & Tricks’ series. I strongly suggest to all of them to look at the previous tips and tricks I have illustrated. Reading those posts is not mandatory but highly recommended as they may be mentioned here. Do not hesitate to learn more about emptiness handling and sectioning

Note: I do not know how many articles will be written in this series of tips and tricks about the ListView widget. In the second opus, I gathered all sample codes into a single repository on GitHub. This project will be augmented with each code I will be developing in this series. For instance, all of the code you will find in this page is already available in the ListViewTipsAndTricks project. You can clone/fork it at the following GitHub page:

http://github.com/cyrilmottier/ListViewTipsAndTricks

In the previous article, we have learned how to section data inside a ListView. I have also given you a few tips that might have helped you to improve performance in your application. Providing a very smooth and responsive UI is essential to users as mobile applications are a way for them to improve their productivity. Performance and responsiveness are great but I’m sure all of you know users are very demanding. They also want their applications to be user-friendly, easy-to-use and … beautiful. In this article we will focus on creating fancy and eye-candy ListViews

Along this post we will display a list of cheeses. I know this is far from being a great set of data (especially for a guy that never eat cheese like me ^^). The reason for this is I preferred focusing on the actual code of the ListView rather the data-fetching code. I’m sure, you can all imagine cheeses as relevant and have enough imagination to consider cheeses like something more ‘accurate’: tweets, Google+ messages, etc.

Our goal in this post is to learn few tips to create well-designed ListView-based applications. ListViews are widely used on the Android platform and must be designed keeping in mind its actual purpose. For instance, the Contact app is regularly used but the time taken by a user to find a contact must be as quick as possible. To fulfill these requirements, the Android team developed a very easy-to-read ListView: clean, containing as few texts as possible, large texts, plain background color, white texts on black background, etc. Even if this is great for the ‘Contact’ app, this is not a perfect and generic solution. Conversely, the ‘Messages’ app contains a ListView designed to be used as often but in a slower way, rarely flinged, differentiating each participant of a conversation, etc. The solution to this problem has been to create a ListView with various background colors, a small but readable font, using grey color for less important information, etc. In other word, a smooth ListView is not enough: you have to design it constantly thinking about the way your customers will use it.

The starting point

Let’s start by creating a ListActivity displaying our list of cheeses. The first step is to create a layout containing our ListView. The code below shows you the layout we will be using afterwards in this article. You can also find a graphic representation of this layout in the screenshot below.

View Code XML
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical">
 
    <ListView
        android:id="@android:id/list"
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />
 
    <LinearLayout
        style="@android:style/ButtonBar"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
 
        <Button
            android:layout_width="0dp"
            android:layout_height="fill_parent"
            android:layout_weight="1"
            android:layout_gravity="center_vertical"
            android:text="@string/draw_selector_on_top"
            android:onClick="onDrawSelectorOnTop" />
 
        <Button
            android:layout_width="0dp"
            android:layout_height="fill_parent"
            android:layout_weight="1"
            android:layout_gravity="center_vertical"
            android:text="@string/use_selector_as_background"
            android:onClick="onUseSelectorAsBackground" />
 
    </LinearLayout>
 
</LinearLayout>

As you may have noticed, the layout contains a ‘bottom bar’ with two Buttons. We could have created a very basic layout … or even not creating one at all and letting the ListActivity create a full-sized ListView but we will actually use those Buttons in the rest of this post to switch between different ’styling’ methods.

The code of our basic ListActivity is given below:

View Code JAVA
package com.cyrilmottier.android.listviewtipsandtricks;
 
import android.app.ListActivity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
 
import com.cyrilmottier.android.listviewtipsandtricks.data.Cheeses;
 
public class FancyListActivity extends ListActivity {
 
    private FancyAdapter mFancyAdapter;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.fancy_list);
 
        mFancyAdapter = new FancyAdapter(Cheeses.CHEESES);
        setListAdapter(mFancyAdapter);
    }
 
 
    private class FancyAdapter extends BaseAdapter {
 
        private String[] mData;
 
        public FancyAdapter(String[] data) {
            mData = data;
        }
 
        @Override
        public int getCount() {
            return mData.length;
        }
 
        @Override
        public String getItem(int position) {
            return mData[position];
        }
 
        @Override
        public long getItemId(int position) {
            return position;
        }
 
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
 
            TextView result;
 
            if (convertView == null) {
                result = (TextView) getLayoutInflater().inflate(R.layout.text_item, parent, false);
            } else {
                result = (TextView) convertView;
            }
 
            final String cheese = getItem(position);
            result.setText(cheese);
 
            return result;
        }
 
    }
 
}

If we look at the overall appearance of this UI, we have a very basic ListView with a black background. When the user taps an item, the background of this itemview turns orange while the text turns black. Where do those colors come from? In the source code of our application, there is no reference to colors nor Drawables. The actual reason is all styles come from the Application/Activity theme. As we have set no theme to our application, the default theme (@android:style/Theme) is used.

List selector

Let’s start customizing our ListView! The first thing we can change from the default theme is the color of the pressed itemview. In order to do that, we will use the android:listSelector XML attribute which is equivalent to the ListView.setSelector(int) method. The list selector is a Drawable drawn by the ListView as the background of the pressed/focused itemview. The ListView manages all types of Drawables but the preferred Drawable is usually the StateListDrawable. This Drawable changes its appearance based on its current state (focused, pressed, selected, etc.). The capture below shows the list selector we want to develop in the focused and pressed states:

Note: As some of you may know, I am a huge fan of Android Drawables. I think they are one of the most amazing features of the Android UI toolkit. They are so powerful I have given a talk named “Mastering Drawables” during the Droidcon (London - 2010) as well as the Android Developer Labs (Paris - 2010). If you want to know more about Drawables, you can have a look at the slides (in French only … it seems I have lost the English version of those slides) on Slideshare and the sample codes I made on GitHub

Edit (2011-09-24): I finally succeed to find the English version of the slides. You can download them here

In this example, we will create a brand new list selector that displays a nice gradient beneath the pressed/focused itemview. The first thing we need to do is to create two GradientDrawables: the first one for the pressed state and the second one for the focused state. The GradientDrawables below are respectively called list_selector_pressed.xml and list_selector_focused.xml and can be found in the res/drawable folder:

View Code XML
<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
 
    <gradient
        android:startColor="#fb9d23"
        android:endColor="#ffc579"
        android:angle="90" />
 
</shape>

 

View Code XML
<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
 
    <gradient
        android:startColor="#f5c98c"
        android:endColor="#f7ddb8"
        android:angle="90" />
 
</shape>

We can now create our own list selector that references the two previous Drawables (this is where the magic happens ^^). This file is located in the res/drawable folder and its name is list_selector.xml:

View Code XML
<?xml version="1.0" encoding="utf-8"?>
<selector
    xmlns:android="http://schemas.android.com/apk/res/android">
 
    <item
        android:state_pressed="true"
        android:drawable="@drawable/list_selector_pressed" />
 
    <item
        android:state_focused="true"
        android:drawable="@drawable/list_selector_focused" />
 
    <item
        android:drawable="@android:color/transparent" />
 
</selector>

The only thing we need to do now is to apply this brand new list selector to our ListView. You can do it by adding android:listSelector="@drawable/list_selector" to the ListView tag in your layout.

Note: Using a color as part of your list selector may entirely fill your ListView. This problem comes from the fact a ColorDrawable does not respect its bounds: it entirely fills the clip rect of the Canvas in which it is drawn into. I have always considered this as a bug but nothing has been fixed until … Android 3.0 (Honeycomb)! As a result, using a ColorDrawable in your list selector is strongly discouraged. Fortunately, this article is entitled ‘ListView tips & tricks’ and here is an easily way to get round this bug: instead of setting a ColorDrawable, use a Drawable that respect its bounds such as a GradientDrawable or a NinePatchDrawable. The code below shows a GradientDrawable that can be used in replacement of a regular ColorDrawable.

View Code XML
<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
 
    <solid
        android:color="#fb9d23" />
 
</shape>

Miscellaneous styling

ListViews provides a lot of “styling” features. In this paragraph we will focus on various methods that may be used to style your ListView. Please note those most of those tips are given “as it” and are not part of the sample code.

Cache color hint

By default, an Android View has a transparent background. Although it seems natural … transparency involves a lot of calculation when rendering your application on screen. In order to avoid blending and make the rendering faster while scrolling/flinging, the ListView widget uses a ’scrolling cache’ mechanism. This mechanism consists on taking an opaque screenshot of all visible child Views (in other words, it draws the content of each itemview in a Bitmap) and directly draws those screenshots when necessary. The color used to make those screenshots opaque is the one given by the cache color hint. If your ListView turns opaque (black for instance) when scrolling that because you need to set the cache color hint to the actual color of your ListView background. Setting this property @android:color/transparent will fix the problem but will also disable the optimization …

If you want to know more about the cache color hint optimization I strongly recommend you to have a look at a really great article written by Romain Guy. You can read it on the Android Developer Blog

Divider

Contrary to the ScrollView widget, ListView has a built-in support for dividers. By default, a divider is a 1-pixel tall line that is used to separate two itemviews. You can style/modify this property with the android:divider XML attribute. Setting a new divider can be done with a color or a Drawable. When drawing the content, the ListView will automatically look at the height of the divider to part the itemviews. In other words, it means you can use a very complex Drawable as divider and your ListView will automatically measure it and draw it when necessary.

This looks amazingly powerful and easy, isn’t it? It actually is … but there is little a problem. Some Drawables (for instance the ColorDrawable) has no intrinsic height (which means a call to Drawable.getIntrinsicHeight() returns -1). In order to by-pass this problem, ListView provides a android:dividerHeight XML attribute that asks for a dimension.

Note: The previously detailed problem concerning the un-respected bounds does not apply to dividers. This is odd, isn’t it? Indeed, ListView has an internal mechanism clipping the Drawable to the correct rectangle on screen when the divider is a ColorDrawable. As a result you can safely use colors when styling your dividers.

Fading edges

By default, a ListView fades away at the top and bottom edges once the content is larger than the actual size of the ListView. This property is called fading edge and can be easily removed or modified using android:fadingEdge and/or android:fadingEdgeLength. You can look at the sample code of this post in which I have prefered removing this Android feature by adding a android:fadingEdge="none" in the XML attributes of our ListView.

ColorStateList

Sooner, we have discovered a way to create a custom list selector. If you look closely to the image, you will notice the text has a different color between the normal and pressed states. Changing the text color may be mandatory in some cases where the background color of a pressed itemview is very close to the color of the text. In order to change the color of the text depending on the current state of the itemview, you can use a ColorStateList. I will not describe how to use it here but you can take a look at the framework documentation. This class and its use is described very clearly in the Android developer guide

Overscroll Drawables

Since Android 2.3, ListViews gives a visual feedback when the user tries to scroll the content of the ListView over its bounds. This feedback looks like a ‘halo’ at the bottom/top of the ListView. You can set your own Drawable using one of the setOverscroll[Footer/Header](Drawable) method.

Customizing itemviews background

Changing the background color of a ListView can be rather complex. The next part gives you a few tips and tricks you can use to create eye-candy and unique ListViews. Our goal is to change the background of our UI to a light color. We will also try to emphasize some cheeses by setting the background of their itemview to a more noticeable color. The screenshots below shows our final ListView depending on the method used:

ListView background

The simplest approach of changing the UI background color is to change the background color of the ListView. In order to do that, we simply have to use the android:background XML attribute or one of the setBackground[Color|Resource|Drawable] method.

The main problem with this approach is the background is applied globally. In other words, it means you don’t a control over each itemview as the background applied to the entire ListView. This works particularly great with a plain color but this method will not allow you style two itemviews differently.

Itemviews background

In the previous method, we have chosen to change the background of the entire ListView. If we want to have a control over each itemview appearance it makes sense to change the background of each of our itemviews independently. The code below shows you how to apply a background depending on whether the underlying data is special or not:

View Code JAVA
@Override
public View getView(int position, View convertView, ViewGroup parent) {
 
    TextView result;
 
    if (convertView == null) {
        result = (TextView) getLayoutInflater().inflate(R.layout.text_item, parent, false);
        result.setTextColor(Color.BLACK);
    } else {
        result = (TextView) convertView;
    }
 
    final String cheese = getItem(position);
 
    result.setText(cheese);
    result.setBackgroundResource(isSpecial(cheese) ? R.drawable.list_item_background_special : R.drawable.list_item_background_normal);
 
    return result;
}

If you compile and run this example, everything will work perfectly fine … until you try to press an itemview. Indeed, using the previous technique, the customized list selector we created never shows up. It may look like a bug at first but this is actually completely normal. Let’s look at how things are drawn the following diagram (you can click on the image to access to a larger version):

As you can see, Android first draws the ListView background as well as the dividers. Then, the system draws the list selector. Finally, ListView renders all itemviews on top of that. Thanks to this diagram, it is clear the list selector will never be visible with opaque background set to itemviews. Fortunately, I have a listed a few solutions you can implement.

Drawing selector on top

The ListView or more globally the AbsListView offers a android:drawSelectorOnTop XML attribute and its Java equivalent setDrawSelectorOnTop(boolean). As mentioned in the method’s name, setting this property to true will indicate the ListView to draw the selector on top of each itemview. Even if this looks like a good option, drawing selector on top does not allow you to have opaque list selector as the content of your itemview will be completely hidden.

OnItemClickListener and OnItemSelectedListener

I have seen a lot of samples over the Internet using the OnItemClickListener and OnItemSelectedListener in order to be notified the background must be changed to transparent … This can work but I think this is a pure hack considering the features available in the Android framework. Even if this technique is probably great on some mobile platforms could you please guys stop using it on the Android platform. This is not a correct nor easy way to do it on Android. As a result, you can probably guess why there is no line of code in this article explaining the trick hack.

StateListDrawable

As we have seen previously, our biggest problem comes the fact the background is opaque and hides the list selector when the itemview is pressed. Hence, we need to find a way to make the background transparent when pressed. This looks like something we have already done and some of you may have understood where I want to get to … Hurray, you are right! The trick consists on using a StateListDrawable as the background of each itemview. This Drawable will have the exact opposite behavior of the list selector: it will be opaque by default and will become transparent when pressed, focused or selected. The code below refers to the list_selector_normal.xml (the list_selector_special.xml is very similar and is not available here. Look at the sample code for more details):

View Code XML
<?xml version="1.0" encoding="utf-8"?>
<selector
    xmlns:android="http://schemas.android.com/apk/res/android">
 
    <item
        android:state_pressed="true"
        android:drawable="@android:color/transparent" />
 
    <item
        android:state_selected="true"
        android:drawable="@android:color/transparent" />
 
    <item
        android:state_focused="true"
        android:drawable="@android:color/transparent" />
 
    <item
        android:drawable="@drawable/list_item_background_normal" />
 
</selector>

This trick can even be pushed to its paroxysm by setting the list selector of your ListView to null or a transparent color and letting each itemview handle the all states itself. You only thing you need to do here is to create a final StateListDrawable containing the background (normal state) as well as the gradient used as visual interaction feedback (pressed/focused state). This method works pretty well and does not suffer from the previously mentioned problem regarding ColorDrawable (the color is drawn at the itemview level not at the ListView level) but it does not force you to have consistent pressed/focused states between your itemviews. Even if it is usually okay to have different Drawable for the ‘normal’ background it is generally not recommended to have different Drawable between itemviews.

Conclusion

Although we have just scratched the surface of the styling possibilities, you now have a large set of keys to design eye-candy ListViews. Do not hesitate to use those tips always keeping in mind what the important questions are: “What’s the real purpose on this ListView?”, “What are my users’ expectations?”, “Do I need to focus on productivity, readability, efficiency or something else?”, etc.

I hope you have appreciated this article. I know it is quite a long post but let’s say this will be the only one I will be posting this month of holidays ^^. Do not hesitate to leave a comment below if you have questions, if you think I have made a mistake somewhere or simply if you want to thank me for this! Have fun styling your ListViews!

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

Android SystemInfo  (0) 2012.06.02
Android 제조사별 소스  (0) 2012.06.01
Android - Dialog  (1) 2012.04.23
Android 에서 화면 회전하는 방법  (0) 2012.04.23
Android Emulator Market 2.2 (마켓버전 Image)  (0) 2012.04.22
Posted by woono

Android - Dialog

2012. 4. 23. 11:46 : Dev/Android
User Interface:

Dialogs

A dialog is usually a small window that appears in front of the current Activity. The underlying Activity loses focus and the dialog accepts all user interaction. Dialogs are normally used for notifications that should interupt the user and to perform short tasks that directly relate to the application in progress (such as a progress bar or a login prompt).

The Dialog class is the base class for creating dialogs. However, you typically should not instantiate a Dialog directly. Instead, you should use one of the following subclasses:

AlertDialog
A dialog that can manage zero, one, two, or three buttons, and/or a list of selectable items that can include checkboxes or radio buttons. The AlertDialog is capable of constructing most dialog user interfaces and is the suggested dialog type. See Creating an AlertDialog below.
ProgressDialog
A dialog that displays a progress wheel or progress bar. Because it's an extension of the AlertDialog, it also supports buttons. See Creating a ProgressDialog below.
DatePickerDialog
A dialog that allows the user to select a date. See the Hello DatePicker tutorial.
TimePickerDialog
A dialog that allows the user to select a time. See the Hello TimePicker tutorial.

If you would like to customize your own dialog, you can extend the base Dialog object or any of the subclasses listed above and define a new layout. See the section on Creating a Custom Dialog below.

Dialog Design

For design guidelines, read Android Design's Dialogs guide.

Showing a Dialog

A dialog is always created and displayed as a part of an Activity. You should normally create dialogs from within your Activity's onCreateDialog(int) callback method. When you use this callback, the Android system automatically manages the state of each dialog and hooks them to the Activity, effectively making it the "owner" of each dialog. As such, each dialog inherits certain properties from the Activity. For example, when a dialog is open, the Menu key reveals the options menu defined for the Activity and the volume keys modify the audio stream used by the Activity.

Note: If you decide to create a dialog outside of the onCreateDialog() method, it will not be attached to an Activity. You can, however, attach it to an Activity with setOwnerActivity(Activity).

When you want to show a dialog, call showDialog(int) and pass it an integer that uniquely identifies the dialog that you want to display.

When a dialog is requested for the first time, Android calls onCreateDialog(int) from your Activity, which is where you should instantiate the Dialog. This callback method is passed the same ID that you passed to showDialog(int). After you create the Dialog, return the object at the end of the method.

Before the dialog is displayed, Android also calls the optional callback method onPrepareDialog(int, Dialog). Define this method if you want to change any properties of the dialog each time it is opened. This method is called every time a dialog is opened, whereas onCreateDialog(int) is only called the very first time a dialog is opened. If you don't define onPrepareDialog(), then the dialog will remain the same as it was the previous time it was opened. This method is also passed the dialog's ID, along with the Dialog object you created in onCreateDialog().

The best way to define the onCreateDialog(int) and onPrepareDialog(int, Dialog) callback methods is with a switch statement that checks the id parameter that's passed into the method. Each case should check for a unique dialog ID and then create and define the respective Dialog. For example, imagine a game that uses two different dialogs: one to indicate that the game has paused and another to indicate that the game is over. First, define an integer ID for each dialog:

static final int DIALOG_PAUSED_ID = 0;
static final int DIALOG_GAMEOVER_ID = 1;

Then, define the onCreateDialog(int) callback with a switch case for each ID:

protected Dialog onCreateDialog(int id) {
   
Dialog dialog;
   
switch(id) {
   
case DIALOG_PAUSED_ID:
       
// do the work to define the pause Dialog
       
break;
   
case DIALOG_GAMEOVER_ID:
       
// do the work to define the game over Dialog
       
break;
   
default:
        dialog
= null;
   
}
   
return dialog;
}

Note: In this example, there's no code inside the case statements because the procedure for defining your Dialog is outside the scope of this section. See the section below about Creating an AlertDialog, offers code suitable for this example.

When it's time to show one of the dialogs, call showDialog(int) with the ID of a dialog:

showDialog(DIALOG_PAUSED_ID);

Dismissing a Dialog

When you're ready to close your dialog, you can dismiss it by calling dismiss() on the Dialog object. If necessary, you can also call dismissDialog(int) from the Activity, which effectively calls dismiss() on the Dialog for you.

If you are using onCreateDialog(int) to manage the state of your dialogs (as discussed in the previous section), then every time your dialog is dismissed, the state of the Dialog object is retained by the Activity. If you decide that you will no longer need this object or it's important that the state is cleared, then you should call removeDialog(int). This will remove any internal references to the object and if the dialog is showing, it will dismiss it.

Using dismiss listeners

If you'd like your application to perform some procedures the moment that a dialog is dismissed, then you should attach an on-dismiss listener to your Dialog.

First define the DialogInterface.OnDismissListener interface. This interface has just one method, onDismiss(DialogInterface), which will be called when the dialog is dismissed. Then simply pass your OnDismissListener implementation to setOnDismissListener().

However, note that dialogs can also be "cancelled." This is a special case that indicates the dialog was explicitly cancelled by the user. This will occur if the user presses the "back" button to close the dialog, or if the dialog explicitly calls cancel() (perhaps from a "Cancel" button in the dialog). When a dialog is cancelled, the OnDismissListener will still be notified, but if you'd like to be informed that the dialog was explicitly cancelled (and not dismissed normally), then you should register an DialogInterface.OnCancelListener with setOnCancelListener().

Creating an AlertDialog

An AlertDialog is an extension of the Dialog class. It is capable of constructing most dialog user interfaces and is the suggested dialog type. You should use it for dialogs that use any of the following features:

  • A title
  • A text message
  • One, two, or three buttons
  • A list of selectable items (with optional checkboxes or radio buttons)

To create an AlertDialog, use the AlertDialog.Builder subclass. Get a Builder with AlertDialog.Builder(Context) and then use the class's public methods to define all of the AlertDialog properties. After you're done with the Builder, retrieve the AlertDialog object with create().

The following topics show how to define various properties of the AlertDialog using the AlertDialog.Builder class. If you use any of the following sample code inside your onCreateDialog() callback method, you can return the resulting Dialog object to display the dialog.

Adding buttons

To create an AlertDialog with side-by-side buttons like the one shown in the screenshot to the right, use the set...Button() methods:

AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder
.setMessage("Are you sure you want to exit?")
       
.setCancelable(false)
       
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
           
public void onClick(DialogInterface dialog, int id) {
               
MyActivity.this.finish();
           
}
       
})
       
.setNegativeButton("No", new DialogInterface.OnClickListener() {
           
public void onClick(DialogInterface dialog, int id) {
                dialog
.cancel();
           
}
       
});
AlertDialog alert = builder.create();

First, add a message for the dialog with setMessage(CharSequence). Then, begin method-chaining and set the dialog to be not cancelable (so the user cannot close the dialog with the back button) with setCancelable(boolean). For each button, use one of the set...Button() methods, such as setPositiveButton(), that accepts the name for the button and a DialogInterface.OnClickListener that defines the action to take when the user selects the button.

Note: You can only add one of each button type to the AlertDialog. That is, you cannot have more than one "positive" button. This limits the number of possible buttons to three: positive, neutral, and negative. These names are technically irrelevant to the actual functionality of your buttons, but should help you keep track of which one does what.

Adding a list

To create an AlertDialog with a list of selectable items like the one shown to the right, use the setItems() method:

final CharSequence[] items = {"Red", "Green", "Blue"};

AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder
.setTitle("Pick a color");
builder
.setItems(items, new DialogInterface.OnClickListener() {
   
public void onClick(DialogInterface dialog, int item) {
       
Toast.makeText(getApplicationContext(), items[item], Toast.LENGTH_SHORT).show();
   
}
});
AlertDialog alert = builder.create();

First, add a title to the dialog with setTitle(CharSequence). Then, add a list of selectable items with setItems(), which accepts the array of items to display and a DialogInterface.OnClickListener that defines the action to take when the user selects an item.

Adding checkboxes and radio buttons

To create a list of multiple-choice items (checkboxes) or single-choice items (radio buttons) inside the dialog, use the setMultiChoiceItems() and setSingleChoiceItems() methods, respectively. If you create one of these selectable lists in the onCreateDialog() callback method, Android manages the state of the list for you. As long as the Activity is active, the dialog remembers the items that were previously selected, but when the user exits the Activity, the selection is lost.

Note: To save the selection when the user leaves or pauses the Activity, you must properly save and restore the setting throughout the activity lifecycle. To permanently save the selections, even when the Activity process is completely shutdown, you need to save the settings with one of the Data Storage techniques.

To create an AlertDialog with a list of single-choice items like the one shown to the right, use the same code from the previous example, but replace the setItems() method with setSingleChoiceItems():

final CharSequence[] items = {"Red", "Green", "Blue"};

AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder
.setTitle("Pick a color");
builder
.setSingleChoiceItems(items, -1, new DialogInterface.OnClickListener() {
   
public void onClick(DialogInterface dialog, int item) {
       
Toast.makeText(getApplicationContext(), items[item], Toast.LENGTH_SHORT).show();
   
}
});
AlertDialog alert = builder.create();

The second parameter in the setSingleChoiceItems() method is an integer value for the checkedItem, which indicates the zero-based list position of the default selected item. Use "-1" to indicate that no item should be selected by default.

Creating a ProgressDialog

A ProgressDialog is an extension of the AlertDialog class that can display a progress animation in the form of a spinning wheel, for a task with progress that's undefined, or a progress bar, for a task that has a defined progression. The dialog can also provide buttons, such as one to cancel a download.

Opening a progress dialog can be as simple as calling ProgressDialog.show(). For example, the progress dialog shown to the right can be easily achieved without managing the dialog through the onCreateDialog(int) callback, as shown here:

ProgressDialog dialog = ProgressDialog.show(MyActivity.this, "", 
                       
"Loading. Please wait...", true);

The first parameter is the application Context, the second is a title for the dialog (left empty), the third is the message, and the last parameter is whether the progress is indeterminate (this is only relevant when creating a progress bar, which is discussed in the next section).

The default style of a progress dialog is the spinning wheel. If you want to create a progress bar that shows the loading progress with granularity, some more code is required, as discussed in the next section.

Showing a progress bar

To show the progression with an animated progress bar:

  1. Initialize the ProgressDialog with the class constructor, ProgressDialog(Context).
  2. Set the progress style to "STYLE_HORIZONTAL" with setProgressStyle(int) and set any other properties, such as the message.
  3. When you're ready to show the dialog, call show() or return the ProgressDialog from the onCreateDialog(int) callback.
  4. You can increment the amount of progress displayed in the bar by calling either setProgress(int) with a value for the total percentage completed so far or incrementProgressBy(int) with an incremental value to add to the total percentage completed so far.

For example, your setup might look like this:

ProgressDialog progressDialog;
progressDialog
= new ProgressDialog(mContext);
progressDialog
.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog
.setMessage("Loading...");
progressDialog
.setCancelable(false);

The setup is simple. Most of the code needed to create a progress dialog is actually involved in the process that updates it. You might find that it's necessary to create a second thread in your application for this work and then report the progress back to the Activity's UI thread with a Handler object. If you're not familiar with using additional threads with a Handler, see the example Activity below that uses a second thread to increment a progress dialog managed by the Activity.

Creating a Custom Dialog

If you want a customized design for a dialog, you can create your own layout for the dialog window with layout and widget elements. After you've defined your layout, pass the root View object or layout resource ID to setContentView(View).

For example, to create the dialog shown to the right:

  1. Create an XML layout saved as custom_dialog.xml:
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                 
    android:id="@+id/layout_root"
                 
    android:orientation="horizontal"
                 
    android:layout_width="fill_parent"
                 
    android:layout_height="fill_parent"
                 
    android:padding="10dp"
                 
    >
       
    <ImageView android:id="@+id/image"
                   
    android:layout_width="wrap_content"
                   
    android:layout_height="fill_parent"
                   
    android:layout_marginRight="10dp"
                   
    />
       
    <TextView android:id="@+id/text"
                 
    android:layout_width="wrap_content"
                 
    android:layout_height="fill_parent"
                 
    android:textColor="#FFF"
                 
    />
    </LinearLayout>

    This XML defines an ImageView and a TextView inside a LinearLayout.

  2. Set the above layout as the dialog's content view and define the content for the ImageView and TextView elements:
    Context mContext = getApplicationContext();
    Dialog dialog = new Dialog(mContext);

    dialog
    .setContentView(R.layout.custom_dialog);
    dialog
    .setTitle("Custom Dialog");

    TextView text = (TextView) dialog.findViewById(R.id.text);
    text
    .setText("Hello, this is a custom dialog!");
    ImageView image = (ImageView) dialog.findViewById(R.id.image);
    image
    .setImageResource(R.drawable.android);

    After you instantiate the Dialog, set your custom layout as the dialog's content view with setContentView(int), passing it the layout resource ID. Now that the Dialog has a defined layout, you can capture View objects from the layout with findViewById(int) and modify their content.

  3. That's it. You can now show the dialog as described in Showing A Dialog.

A dialog made with the base Dialog class must have a title. If you don't call setTitle(), then the space used for the title remains empty, but still visible. If you don't want a title at all, then you should create your custom dialog using the AlertDialog class. However, because an AlertDialog is created easiest with the AlertDialog.Builder class, you do not have access to the setContentView(int) method used above. Instead, you must use setView(View). This method accepts a View object, so you need to inflate the layout's root View object from XML.

To inflate the XML layout, retrieve the LayoutInflater with getLayoutInflater() (or getSystemService()), and then call inflate(int, ViewGroup), where the first parameter is the layout resource ID and the second is the ID of the root View. At this point, you can use the inflated layout to find View objects in the layout and define the content for the ImageView and TextView elements. Then instantiate the AlertDialog.Builder and set the inflated layout for the dialog with setView(View).

Here's an example, creating a custom layout in an AlertDialog:

AlertDialog.Builder builder;
AlertDialog alertDialog;

Context mContext = getApplicationContext();
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.custom_dialog,
                               
(ViewGroup) findViewById(R.id.layout_root));

TextView text = (TextView) layout.findViewById(R.id.text);
text
.setText("Hello, this is a custom dialog!");
ImageView image = (ImageView) layout.findViewById(R.id.image);
image
.setImageResource(R.drawable.android);

builder
= new AlertDialog.Builder(mContext);
builder
.setView(layout);
alertDialog
= builder.create();

Using an AlertDialog for your custom layout lets you take advantage of built-in AlertDialog features like managed buttons, selectable lists, a title, an icon and so on.

For more information, refer to the reference documentation for the Dialog and AlertDialog.Builder classes.


Posted by woono


Android 에서 화면 회전하는 방법






Posted by woono