2013.07.25 02:00


안드로이드에서 이미지를 사용하기 위해서, 보통 Bitmap 클래스를 사용하게 됩니다. 안드로이드 앱에서 이미지에 대한 Thumbnail이나 이미지의 부분을 자르기 위해서는 Bitmap 클래스로 원하는 사이즈나 원하는 부분을 쉽게 잘라낼 수 있습니다. 

아래의 BitmapUtil 클래스는, Bitmap 클래스를 이용해서 이미지를 줄이거나 늘리는 기능을 제공하는 유틸리티 클래스입니다. 아래의 기능정도면, 정말 특이한 요구사항(우측아래를 기준으로 100x100 이미지를 가져와라, 이런건 간단하게 아래의 cropCenter 메쏘드를 약간 변경하면 쉽게 적용)이 없다면, 아래의 유틸리티 클래스만으로도 상당히 많은 부분을 커버할 수 있을것 같습니다.. 

import android.graphics.Bitmap;

/**
 * BitmapUtil Class
 * 
 * @Author : mcsong@gmail.com
 * @Date : Mar 11, 2012 9:59:18 AM
 * @Version : 1.0.0
 */
public class BitmapUtil {    
    /**
     * Bitmap을 ratio에 맞춰서 max값 만큼 resize한다.
     *  
     * @param Bitmap 원본 
     * @param max 원하는 크기의 값
     * @return
     */
    public static Bitmap resizeBitmap(Bitmap src, int max) {
        if(src == null)
            return null;
        
        int width = src.getWidth();
        int height = src.getHeight();
        float rate = 0.0f;
        
        if (width > height) {
            rate = max / (float) width;
            height = (int) (height * rate);
            width = max;
        } else {
            rate = max / (float) height;
            width = (int) (width * rate);
            height = max;
        }

        return Bitmap.createScaledBitmap(src, width, height, true);            
    }
    
    /**
     * Bitmap을 ratio에 맞춰서 max값 만큼 resize한다.
     * 
     * @param src
     * @param max 
     * @param isKeep 작은 크기인 경우 유지할건지 체크..  
     * @return
     */
    public static Bitmap resize(Bitmap src, int max, boolean isKeep) {
        if(!isKeep)
            return resizeBitmap(src, max);
        
        int width = src.getWidth();
        int height = src.getHeight();
        float rate = 0.0f;
        
        if (width > height) {
            if (max > width) {
                rate = max / (float) width;
                height = (int) (height * rate);
                width = max;
            }
        } else {
            if (max > height) {
                rate = max / (float) height;
                width = (int) (width * rate);
                height = max;
            }
        }

        return Bitmap.createScaledBitmap(src, width, height, true);
    }
    
    /**
     * Bitmap 이미지를 정사각형으로 만든다.
     * 
     * @param src 원본 
     * @param max 사이즈
     * @return
     */
    public static Bitmap resizeSquare(Bitmap src, int max) {
        if(src == null)
            return null;
        
        return Bitmap.createScaledBitmap(src, max, max, true);
    }
    
    
    /**
     * Bitmap 이미지를 가운데를 기준으로 w, h 크기 만큼 crop한다. 
     * 
     * @param src 원본
     * @param w 넓이
     * @param h 높이
     * @return
     */
    public static Bitmap cropCenterBitmap(Bitmap src, int w, int h) {
        if(src == null)
            return null;
        
        int width = src.getWidth();
        int height = src.getHeight();
                
        if(width < w && height < h)
            return src;
        
        int x = 0;
        int y = 0;
        
        if(width > w)
            x = (width - w)/2;
        
        if(height > h)
            y = (height - h)/2;
        
        int cw = w; // crop width
        int ch = h; // crop height
        
        if(w > width)
            cw = width;
        
        if(h > height)
            ch = height;
        
        return Bitmap.createBitmap(src, x, y, cw, ch);
    }
    
}




Posted by injunech
2013.06.07 17:09


안드로이드 작업을 하다보면 메니페스트 파일에 넣어야하는 User-permission 을 잊거나 생각이

안날경우가 있따. 그래서 일단 적어 놓는다.

</application> 밑에 추가할것 ㅋ

 

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

//위치정보 확인함
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION"/>

//위치정보 확인함

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

//wifi 연결을 확인함
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>

//wifi 체인지를 확인함

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

//네트웍이 연결된것을 확인할수 있게함

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

//부팅완료를 확인할수있게함

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

// 인터넷을 사용함

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

// 외장메모리 사용

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

//녹음이 가능하게 함

 

ACCESS_CHECKIN_PROPERTIES      체크인데이터베이스의_속성테이블로_액세스
ACCESS_COARSE_LOCATION         코스_로케이션_액세스_(Cell-ID/WiFi)
ACCESS_FINE_LOCATION           파인로케이션_액세스(GPS)          
ACCESS_LOCATION_EXTRA_COMMANDS 로케이션_옵션_커맨드_액세스       
ACCESS_MOCK_LOCATION           목_로케이션_프로바이더_생성_(테스트용)
ACCESS_NETWORK_STATE           네트워크_상태_접근                
ACCESS_SURFACE_FLINGER         서피스_플링거_접근                
ACCESS_WIFI_STATE              WiFi상태_접근                     
ADD_SYSTEM_SERVICE             시스템서비스_추가                 
BATTERY_STATS                  배터리_상태                       
BLUETOOTH                      블루투스                          
BLUETOOTH_ADMIN                블루투스_어드민                   
BRICK                          디바이스_실효성_지정              
BROADCAST_PACKAGE_REMOVED      제거된_패키지에_대한_notification_브로드캐스트
BROADCAST_SMS                  SMS에_대한_브로드캐스트           
BROADCAST_STICKY               인텐트_브로드캐스트               
CALL_PHONE                     통화                              
CALL_PRIVILEGED                통화(긴급전화_포함)               
CAMERA                         카메라                            
CHANGE_COMPONENT_ENABLED_STATE 컴포넌트의_실효성_변경            
CHANGE_CONFIGURATION           컨피그_변경                       
CHANGE_NETWORK_STATE           통신상태_변경                     
CHANGE_WIFI_STATE              WiFi상태_변경                     
CLEAR_APP_CACHE                어플리케이션_캐시_클리어          
CLEAR_APP_USER_DATA            어플리케이션의_유저데이터_클리어  
CONTROL_LOCATION_UPDATES       위치정보_갱신                     
DELETE_CACHE_FILES             캐시파일_제거                     
DELETE_PACKAGES                패키지_제거                       
DEVICE_POWER                   전원상태에_대한_로우레벨_접근     
DIAGNOSTIC                     진단리소스_읽고쓰기               
DISABLE_KEYGUARD               키_가드_끄기_DUMP_덤?            
EXPAND_STATUS_BAR              상태표시줄_확장                   
FACTORY_TEST                   팩토리_테스트                     
FLASHLIGHT                     플래시라이트                      
FORCE_BACK                     포스백                            
GET_ACCOUNTS                   어카운트_획득                     
GET_PACKAGE_SIZE               패키지_획득                       
GET_TASKS                      태스크_획득                       
HARDWARE_TEST                  하드웨어테스트                    
INJECT_EVENTS                  유저이벤트_키/트랙볼              
INSTALL_PACKAGES               패키지_인스톨                     
INTERNAL_SYSTEM_WINDOW         내부_시스템윈도_활용              
INTERNET                       인터넷                            
MANAGE_APP_TOKENS              어플리케이션_토큰관리             
MASTER_CLEAR                   마스터_클리어                     
MODIFY_AUDIO_SETTINGS          오디오설정_편집                   
MODIFY_PHONE_STATE             전화상태_편집                     
MOUNT_UNMOUNT_FILESYSTEMS      파일시스템_편집                   
PERSISTENT_ACTIVITY            액티비티_지속                     
PROCESS_OUTGOING_CALLS         전화_발신처리_접근                
READ_CALENDAR                  캘린더_읽어오기                   
READ_CONTACTS                  주소록_읽어오기                   
READ_FRAME_BUFFER              프레임버퍼_읽어오기               
READ_INPUT_STATE               입력상태_읽어오기                 
READ_LOGS                      로그_읽어오기                     
READ_OWNER_DATA                owner_data읽어오기                
READ_PHONE_STATE               통화상태_읽어오기_READ_SMS_SMS읽어오기
READ_SYNC_SETTINGS             동기설정_읽어오기                 
READ_SYNC_STATS                동기상태_읽어오기                 
REBOOT                         reboot                            
RECEIVE_BOOT_COMPLETED         boot완료                          
RECEIVE_MMS                    MMS수신                           
RECEIVE_SMS                    SMS수신                           
RECEIVE_WAP_PUSH               WAP수신                           
RECORD_AUDIO                   오디오_수신                       
REORDER_TASKS                  태스크_Z오더                      
RESTART_PACKAGES               패키지_리스타트                   
SEND_SMS                       SMS송신                           
SET_ACTIVITY_WATCHER           액티비티_왓쳐지정                 
SET_ALWAYS_FINISH              액티비티_전체_종료                
SET_ANIMATION_SCALE            스케일_애니메이션_지정            
SET_DEBUG_APP                  디버그어플리케이션_지정           
SET_ORIENTATION                스크린_로테이션지정               
SET_PREFERRED_APPLICATIONS     자주_사용하는_어플리케이션_지정   
SET_PROCESS_FOREGROUND         포어그라운드_처리지정             
SET_PROCESS_LIMIT              제한처리_지정                     
SET_TIME_ZONE                  타임존_지정                       
SET_WALLPAPER                  배경화면_지정                     
SET_WALLPAPER_HINTS            배경화면_힌트_지정                
SIGNAL_PERSISTENT_PROCESSES    지속처리_시그널_지정              
STATUS_BAR                     상태표시줄_지정                   
SUBSCRIBED_FEEDS_READ          서브스트립드_피즈_읽어오기        
SUBSCRIBED_FEEDS_WRITE         서브스트립드_피즈_쓰기            
SYSTEM_ALERT_WINDOW            알림_윈도우                       
VIBRATE                        진동                              
WAKE_LOCK                      알람                              
WRITE_APN_SETTINGS             APN설정_쓰기                      
WRITE_CALENDAR                 캘린더_쓰기                       
WRITE_CONTACTS                 주소록_쓰기                       
WRITE_GSERVICES                G서비스_쓰기                      
WRITE_OWNER_DATA               owner_data쓰기                    
WRITE_SETTINGS                 설정_쓰기
WRITE_SMS                      SMS쓰기 
WRITE_SYNC_SETTINGS            동기설정_쓰기



Posted by injunech
2013.05.31 11:28


FROM drawable TO bitmap :

Drawable d = ImagesArrayList.get(0);  
Bitmap bitmap = ((BitmapDrawable)d).getBitmap();

 

FROM resource id of drawable TO bitmap:

Bitmap b1 = BitmapFactory.decodeResource(context.getResources(),R.drawable.icon_resource);

 

Reference:

http://stackoverflow.com/questions/3035692/how-to-convert-a-drawable-to-a-bitmap

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

Android Bitmap Utility(resize, crop) 클래스..  (0) 2013.07.25
android uses-permission  (0) 2013.06.07
Convert drawable to bitmap  (0) 2013.05.31
안드로이드 디렉토리 생성 및 파일 I/O  (0) 2013.05.29
Android WebView 예제  (0) 2013.05.27
Bitmap Merge  (0) 2013.05.26


Posted by injunech
2013.05.29 10:51


보안상의 이유로 응용 프로그램은 허가받은 위치에만 파일 생성 가능.. 이 제한을 일일이 준수하기 어려우므로 
보안이 적용된 파일 관리 메서드를 별도로 제공..

FileOutputStream openFileOutput(String name, int mode)
FileInputStream openFileInput(String name)

 MODE_PRIVATE 혼자만 사용하는 배타적인 모드로 파일 생성 .. (디폴트)
 MODE_APPEND 파일이 이미 존재할 경우 덮어쓰기 모드로 열지 않고 추가 모드로 연다. ( 기존 내용에 추가 )
 MODE_WORLD_READABLE 다른 응용 프로그램이 읽을 수 있도록 허용
 MODE_WORLD_WRITEABLE 다른 응용 프로그램이 쓸 수 있도록 허용

// 파일 저장

FileOutputStreamfos = openFileOutput("text.txt", Context.MODE_WORLD_READABLE);


String str = mEdit.getText().toString();


                                

fos.write(str.getBytes());


fos.close();


mEdit.setText("Write Success");



파일 경로 : /data/data/패키지명/files/ 디렉토리 .. 


- 직접적으로 확인은 불가하다 .. ( Root Explorer(App) 이용해서 확인 .. 루트 권한 필요 )


// 파일 읽기

FileInputStream fis = openFileInput("text.txt");


byte[] data = new byte[fis.available()];


while(fis.read(data) != -1){}


fis.close();


mEdit.setText(new String(data));



*SD Card 이용 I/O

기본 java I/O 와 동일 


// 파일 저장

String sdPath = Environment.getExternalStorageDirectory().getAbsolutePath();


File dir = new File(sdPath,  "testing");


dir.mkdir();


File file = new File(dir, "file.txt");


FileOutputStream fos = new FileOutputStream(file);


String str = mEdit.getText().toString();


fos.write(str.getBytes());


fos.close();


mEdit.setText("write success");






// 파일 읽기

String sdPath = Environment.getExternalStorageDirectory().getAbsolutePath();

FileInputStream fis = new FileInputStream(sdPath + "/testing/file.txt");

byte[] data = new byte[fis.available()];

while(fis.read(data)!=-1){}

fis.close();

mEdit.setText(new String(data));



※ SD Card 디렉토리 생성시 에러상황 .. 해결법 ..


위와 같이 코드를 이용해 디렉토리 생성시 에러가 발생 할 경우 아래의 내용을 추가해야한다.. 


AndroidManifest.xml 


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


SD card의 파일을 엑세스 하려면 Manifest에 퍼미션을 지정해야한다.


※ SD Card 관련 정보 보기


1. Environment.getExternalStorageState()

SD card 현재 상태 .. mounted : 읽고 쓰기 가능한 상태 .. unmounted : 불가능 상태

2. Environment.getExternalStorageDirectory().getAbsolutePath()

SD card 가 마운트된 경로 .. 

3. Environment.getRootDirectory().getAbsolutePath()

4. Environment.getDataDirectory().getAbsolutePath()

5. Environment.getDownloadCacheDirectory().getAbsolutePath() 



Posted by injunech
2013.05.27 15:33


Android WebView예제를 작성해보았습니다. 이전에 작성했던 Fragment 예제에 추가되어있던 WebView인데 해당 글에서 설명을 하지 않아 따로 작성합니다. Fragment를 상속받을때와는 다르게 Activity를 상속받아 작성하였습니다. 사용된 예제는 주소 입력창과 Go 버튼을 추가하여 작성하였습니다.


사용한 API

 WebViewClient API

  http://developer.android.com/reference/android/webkit/WebViewClient.html

 사용한 상속 Public Method

 boolean

 shouldOverrideUrlLoading(WebView view, String url)
  - URL에 따른 페이지 Loding

 void

 onPageFinished(WebView view, String url)
  - 페이지 Loding이 완료되면 알려주는 Method


 WebChromeClient API

  http://developer.android.com/reference/android/webkit/WebChromeClient.html

 void

 onProgressChanged(WebView view, int newProgress)
  - 페이지의 현재 진행사항을 알려줍니다. (Loding 


 WebViewClient API는 기본적인 WebView의 화면을 보여주기 위해서 상속받아 작성하였고, WebChromeClient는 현재 페이지를 Loding하고, Finished 될 때 ProgressBar를 처리하기 위해서 상속받아 사용하였습니다.


예제 코드

Activity - WebView를 처리하는 코드입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package net.thdev.webviewexample;
 
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
 
@SuppressLint({ "SetJavaScriptEnabled", "NewApi" })
public class WebViewActivity extends Activity {
    private String mInputUrl = "http://www.google.com";
     
    private EditText mEditText;
    private WebView mWebView;
    private WebSettings mWebSettings;
    private ProgressBar mProgressBar;
    private InputMethodManager mInputMethodManager;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_webview);
         
        mEditText = (EditText)findViewById(R.id.edit_Url);
        mWebView = (WebView)findViewById(R.id.webview);
        mProgressBar = (ProgressBar)findViewById(R.id.progressBar);
        findViewById(R.id.btn_go).setOnClickListener(onClickListener);
         
        mInputMethodManager = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
         
        mWebView.setWebChromeClient(new webViewChrome());
        mWebView.setWebViewClient(new webViewClient());
        mWebSettings = mWebView.getSettings();
        mWebSettings.setBuiltInZoomControls(true);
         
        mWebView.loadUrl(mInputUrl);
        mEditText.setHint(mInputUrl);
    }
     
    //Button Event를 처리
    View.OnClickListener onClickListener = new View.OnClickListener() {
         
        @Override
        public void onClick(View v) {
            switch(v.getId()) {
            case R.id.btn_go:
                //InputMethodManager를 이용하여 키보드를 숨김
                mInputMethodManager.hideSoftInputFromWindow(mEditText.getWindowToken(), 0);
                mInputUrl = httpInputCheck(mEditText.getText().toString());
                 
                if(mInputUrl == null) break;
                 
                //페이지를 불러온다
                mWebView.loadUrl(mInputUrl);
                mEditText.setText("");
                mEditText.setHint(mInputUrl);
                break;
            }
        }
    };
     
    class webViewChrome extends WebChromeClient {
         
        @Override
        public void onProgressChanged(WebView view, int newProgress) {
            //현제 페이지 진행사항을 ProgressBar를 통해 알린다.
            if(newProgress < 100) {
                mProgressBar.setProgress(newProgress);
            } else {
                mProgressBar.setVisibility(View.INVISIBLE);
                mProgressBar.setLayoutParams(new LinearLayout.LayoutParams(0, 0));
            }
        }
    }
     
    class webViewClient extends WebViewClient {
         
        //Loading이 시작되면 ProgressBar처리를 한다.
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            mProgressBar.setVisibility(View.VISIBLE);
            mProgressBar.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 15));
            view.loadUrl(url);
            return true;
        }
         
        @Override
        public void onPageFinished(WebView view, String url) {
            mWebSettings.setJavaScriptEnabled(true);
            mEditText.setHint(url);
            super.onPageFinished(view, url);
        }
    }
     
    //http://를 체크하여 추가한다.
    private String httpInputCheck(String url) {
        if(url.isEmpty()) return null;
         
        if(url.indexOf("http://") == ("http://").length()) return url;
        else return "http://" + url;
    }
}

XML - WebView XML 예제코드입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
 
        <EditText
            android:id="@+id/edit_Url"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:inputType="textUri"
            android:layout_weight="1"
            android:singleLine="true"
            android:hint="" />
 
        <Button
            android:id="@+id/btn_go"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="0"
            android:text="@string/btn_go"
            />
    </LinearLayout>
     
    <ProgressBar
        android:id="@+id/progressBar"
        android:layout_width="match_parent"
        android:layout_height="0dip"
        android:max="100"
        android:progress="0"
        android:secondaryProgress="1"
        android:visibility="invisible"
        style="?android:attr/progressBarStyleHorizontal"
        />
         
    <WebView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/webview"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
         
    </WebView>
</LinearLayout>

추가한 Permission

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

결과 화면

 간단하게 작성한 WebView입니다. 진행사항을 표시하기 위해서 WebViewChromeClient를 상속 받아 처리하였습니다. 잠시 보여지고 숨겨지는 간단한 ProgressBar를 추하였습니다. ActionBar를 사용해도 가능하지만 3.0 미만의 별도의 처리를 해야하기에 여기서는 제외시켰습니다. 다음에 ActionBar 예제를 다뤄보겠습니다. 이상 WebView 예제를 마치겠습니다.


다운로드

 다운로드는 예전에 작성해둔 Fragment의 Swipe 예제를 링크하겠습니다. 그 때 작성한 예제코드와 지금의 예제코드가 동일합니다. 아리 링크를 통해 다운로드 가능합니다.

  http://db.tt/dGZ5ckDq



Posted by injunech
2013.05.26 02:07


public Bitmap mergeBitmap(Bitmap src, Bitmap mergeBitmap) {
int width = src.getWidth();
int height = src.getHeight();

mergeBitmap2 = Bitmap.createScaledBitmap(mergeBitmap, width,
height, true);

int maskPixel;int tilePixel;int mergedPixel;
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
maskPixel = mergeBitmap2.getPixel(x, y);
tilePixel = src.getPixel(x, y);

mergedPixel = Color.argb(Color.alpha(maskPixel),
Color.red(maskPixel), Color.green(maskPixel),
Color.blue(maskPixel));

mergeBitmap2.setPixel(x, y, mergedPixel);

mergedPixel = Color.argb(Color.alpha(tilePixel),
Color.red(tilePixel), Color.green(tilePixel),
Color.blue(tilePixel));

mergeBitmap2.setPixel(x, y, mergedPixel);
}
}

return mergeBitmap2;



Posted by injunech
2013.05.17 13:59


안드로이드 앱 개발자가 제안하는 디자인 방법론 - ANDROID UI TIPS



1. 특정 해상도의 기준을 잡아 디자인을 하되, 보이는 것이 다가 아님을 주의하라.


안드로이드 기기는 다양한 해상도를 지원한다. 특정 해상도를 잡아서 작업을 하지만 실제 단말에서는 그 해상도를 사용 하는 사람은 많아야 20% 일것이다. 

항상 해상도보다 더 작거나 더 큰 경우가 있다는것을 생각 하고 디자인 하라.









2. 안드로이드 특성상 메뉴버튼과 백버튼은 하단에 위치 한다. 


하단에 하드웨어 방식뿐만 아니라 소프트웨어 방식의 버튼이 존재 한다는것을 기억하라. 소프트웨어 버튼일 경우 하단에 또다른 버튼을 배치 한다면 2단의 버튼이 생성되어 오작동을 불러 일으킬 수 있다.





3. 터치한 영역을 사용자에게 재확인 시켜라.


모바일 특성상 웹과는 다르게 화면이 작다. 사용자가 특정 콘텐츠를 눌렀으면 눌렀다는것을 확인 시켜줘야 한다. 터치한 버튼의 액션에 대한 Pressed이미지를 준비하라.







4. 이미지 파일 사이즈(용량)를 확인 하라.


안드로이드는 JAVA에 의해 구동된다. JAVA특성으로 인해 메모리 관리가 생각 보다는 힘들다. 예를 들어 4x4사이즈의 나인패치 이미지가 10KB씩 큰경우가 있다. 보통 1KB에 비해 10배나 커지게 된다. 이런 사이즈가 커질수록 메모리를 많이 잡아 먹게 되어 결국 성능저하, 누적되면 앱이 죽을 수도 있다.



 

 

 

 

 

5. UI 가이드의 dip단위 또는 이미지 크기는 짝수를 사용 하라.


dip단위는 px변환 과정에서 정수가 아닌 소수가 나올 수 있기때문에 화면에 디스플레이하는데 오차가 발생 하게 된다. 이런 오차를 최대한 줄이기 위해서는 특별한 경우가 아니라면 짝수 크기를 사용하라. 


 

 




6. UI 가이드 라인작성시 절대적인 수치보다, 상대적인 표현을 하라.


해상도 별로 DIP이 다르기 때문에 절대적인 수치는 화면이 짤리거나, 줄어들 수 있다. 유동적이라는 생각으로 상대적인 표현으로 가이드하라. 단, 마진이나 패딩은 제외. 









Posted by injunech
2013.05.17 13:59


안드로이드 앱 개발자가 제안하는 디자인 방법론 - 4. 가이드 작성법 1




이전시간에 안드로이드는 dp(or dip)단위를 쓰기 때문에 어떠한 해상도에서든 같은 크기를 보여준다고 이야기 했으며 스케일링이 된다고 설명했다. 하지만 폰마다 가로 dp가 모두 다르기때문에 스케일링 만으로 다양한 기기를 지원하기가 어렵다. 


2013/03/11 - [개발관련/Android] - 안드로이드 앱 개발자가 제안하는 디자인 방법론 - 3. DPI, DIP(DP) 개념



그렇다면 어떤식으로 디자인 해야 되며, 가이드라인을 만들지에 대해 알아 보자.



왜 스케일링 만으로 모든폰을 지원 못하는지에 대해 간단한 예제를 통해 알아 보자.



디자이너가 좌우 2개의 이미지와 중간에 타이틀을 넣고 싶어 하는 액션바를 디자인 한다고 가정해보자. 1280x720사이즈를 기본으로 위와 같은 작업은 가이드작업을 할 것이다.

이 가이드를 바탕으로 개발자는 아래와 같은 레이아웃 작업을 할것이다.


Test Case

drawable-xhdpi 폴더 r.png, p.png, g.png, r.png


Layout

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<!--
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#EEEEEE">
     
    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="5dip"
        android:src="@drawable/b" />
     
    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/g" />
     
    <TextView
        style="@style/ActionBarTextView"
        android:text="TITLE" />
     
    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/r" />
     
    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginRight="5dip"
        android:src="@drawable/p" />