2013년 1월 31일 목요일

[Android] Spannable 객체 사용

Span 새로 맞춘 문자서식, 문단서식, 이미지 정보등 문자열 표현하는 용어나 어떤 동작이나 행위로 인해 추가로 전달하는 정보를 말한다.

안드로이드에서는 스타일 문자를 처리하는 기능을 갖고 있는 클래스들은 공통적으로 Span이라하는 영문명이 접두어 또는 접미어로 들어간다.

◆String.xml
<?xml version=”1.0” encoding=”utf-8”?>
<resources>
<string name=”style_text_1”>This is bold! and This is highlighted!</string>
</resources>

◆Java Code
 private void spannable() {
  TextView tv = (TextView) findViewById(R.id.tv);
  Spannable sp = tv.getEditableText();
  sp.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), 0, 12, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
  sp.setSpan(new BackgroundColorSpan(Color.GREEN), 18, 37, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
 }
  • Spannable  sp는 Editable 로 받을 수 있기때문에 tv.setText() method 대신tv.getEditableText() method를 사용 하였다.
  • StyleSpan Class 는 문자열의 속성을 변경 할 수 있으며 위 소스는 android.graphics.Typerface.BOLD 처리 한것이다.
  • BackgroundColorSpan Class는 문자열의 백그라운드를 설정 할수 있다.

◆Span 객체들
 private void spannable(){
   TextView tv = (TextView) findViewById(R.id.tv);
   
   SpannableString ss = new SpannableString("When in Rome do as the Romans do.");
   ss.setSpan(new RelativeSizeSpan(0.5f), 0, 3, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
   ss.setSpan(new ForegroundColorSpan(Color.RED), 0, 8, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
   ss.setSpan(new AbsoluteSizeSpan(30), 6, 11, 0);
   ss.setSpan(new StrikethroughSpan(), 13, 18, 0);
   tv.setText(ss, BufferType.SPANNABLE);
  }
  • RelativeSizeSpan(0.5f) : 폰트 사이즈를 변경하는 Class 이다.
  • ForegroundColorSpan(Color.RED) : 폰트의 색상을 변경하는 Class 이다. 
  • AbsoluteSizeSpan(30) : 폰트의 크기를 물리적인 크기로 변경하는 Class 이다.
  • StrikethroughSpan() : 해당 문자를 삭제한 형태로 표기한다.
  • 이 외에 URLSpan 이라는 클래스도 있다. 기능은 링크 연결을 한다.(인터넷, 전환연결 등)

관련글

[Android] CharSequence 와 String 비교

JAVA 와 XML 에서의 문자열 관리하는 방법에는 근본적인 차이가 존재한다.

String Calss 란?
JAVA에서 String 객체내 보관하는 문자열은 유니코드로 변형하여 보관하므로 HTML과 같이 마크업 문자를 입력하고 출력할 때 문제가 발생한다. 따라서 String 객체에 입력되는 문자열은 마크업 문자를 입력하여 사용할 수 없는 문자열인란 의미로 변경금지 문자라 부른다.

CharSequence 란?
반면에 CharSequence 객체내 보관하는 문자열은 같은 String 클래스와 같은 유니코드라 하더라도 마크업 문자를 사용하여 변형과 가공이 가능한 문자열이란 의미로 스타일 문자 또는 연속되는 문자라고 한다.

◆ CharSequence 객체의 제공 Method
  • char charAt(int index) : 인덱스가 가리키는 문자를 반환한다.
  • int length() : CharSequence 객체의 문자수를 반환한다.
  • CharSequence subsequence(int start, int end) : start부터 end까지의 문자를 반환한다.
  • String toString() : CharSequence 객체를 문자열로 반환한다.

◆ XML 문서와 JAVA 프로그램간의 출력하거나 읽을 때 사용 할 수 있도록 XML 버퍼타입을 제공한다.버퍼타입은 Enum 타입으로 지원한다.
  • NORMAL : 디폴트 CharSequence 객체로 반환된다. XML 문서내 문자열은 입력시 소스 문자가 스타일 문자면 스타일 문자로 반환되고 아닌 경우는 일반 String 객체의 문자열로 반환된다.
  • SPANNABLE : 마크업문자를 넣을 수 있는 스타일 문자이다. 항상 스타일 문자로 반환된다.
  • EDITABLE : 편집가능한 스타일 문자이다. EditText는 EDITABLE 속성으로 반환된다.

◆ TextView 클래스에서 제공하는 메서드
  • CharSequence getText()
  • void setText (CharSequence text)
  • void setText (int resid, TextView.BufferType type)
  • void setText (CharSequence text, TextView.BufferType type)

◉String.xml에서 마크업 문자로 작성.
<?xml version=”1.0” encoding=”utf-8”?>
<resources>
    <string name=”styled_text”>기본(Plain), <b>강조 bold</b> <i>이텔리체 italic</i> 
              <b><i>bold-italic</i></b></string>>
</resources>

◉CharSequence 객체로 받아서 처리 할 때.
private void charSequence() {
 CharSequence cs = getText(R.string.styled_text);
 tv.setText(cs);
}

이와 같이 getText() method로 읽어 CharSequence 객체 필드로 보관하면 스타일이 유지된다. 강조나 이탤리체가 적용 안되보이는것은 폰트가 지원을 안하기 때문이다. 지원하는 폰트를 사용하면 적용이 잘된다.

◉String 객체로 받아서 처리 할 때.
private void string() {
 String str = getString(R.string.styled_text);
 tv.setText(str);
}

이와 같이 getString() method로 읽어  String 객체 필드로 보관하면 스타일이 유지되지 않는다. 위에 설명 했다시피 String은 변경금지 문자이기 때문이다.


관련글


2013년 1월 30일 수요일

[Android] XML 특수문자 처리(String.xml)


  • String.xml 에서 특수문자를 처리할때 아래 표와 같이 사용하면 된다.


  • String.xml 에서 마크업 문자를 사용하여 스타일 문자를 만들때는 아래와 같이 사용한면된다.


관련글




[Android] 사용자 모형 Java Code로 만들기


Java Code로 모형 만드는 방법은 크게 4가지가 있다.
  • 직사각형은 RectShape Class로 생성한다.
  • 타원은 OvalShape Class로 생성한다.
  • 모서리가 둥근 사각형은 RoundRectShape 클래스로 생성한다.
  • 다각형은 Path Class 로 생성하여 점과 점사이를 연결하는 방식으로 만든다.

사각형
private void rectShape() {
 ShapeDrawable drawable = new ShapeDrawable(new RectShape());
 drawable.setIntrinsicWidth(200);
 drawable.setIntrinsicHeight(100);
 drawable.getPaint().setColor(Color.BLUE);
 ImageView ivRect = (ImageView) findViewById(R.id.imageView1);
 ivRect.setImageDrawable(drawable);
}
  • setIntrinsicHeight(int height), setIntrinsicWidth (int width) method는 모형의 높이와 너비를 나타낸다.
  • getPaint() method는 색상이나 문자, 비트맵의 이미지를 넣을 수 있는 Paint객체를 반환한다.

타원
private void ovalShape() {
 ShapeDrawable drawable = new ShapeDrawable(new OvalShape());
 drawable.setIntrinsicWidth(200);
 drawable.setIntrinsicHeight(100);
 drawable.getPaint().setColor(Color.RED);
 ImageView ivOval = (ImageView) findViewById(R.id.imageView2);
 ivOval.setImageDrawable(drawable);
}

라운드 모서리 사각형
private void roundRectShape() {
 float[] outerR = new float[] { 12, 12, 12, 12, 0, 0, 0, 0 };
 RectF inset = new RectF(6, 6, 6, 6);
 float[] innerR = new float[] { 12, 12, 0, 0, 12, 12, 0, 0 };
 ShapeDrawable drawable = new ShapeDrawable(new RoundRectShape(outerR,inset, innerR));
 drawable.setIntrinsicWidth(200);
 drawable.setIntrinsicHeight(100);
 drawable.getPaint().setShader(new LinearGradient(0, 0, 50, 50, new int[] {0xFFFF0000, 0XFF00FF00, 0XFF0000FF }, null,Shader.TileMode.REPEAT));
 ImageView ivRoundRect = (ImageView) findViewById(R.id.imageView3);
 ivRoundRect.setImageDrawable(drawable);
}
  • public RoundRectShape(float[] outerRadii, RectF inset, float[] innerRadii) 생성자는 라운드된 사각형을 그린다. 
    • outerRadii는 두 개의 실수 배열을 쌍으로 외부 사각형의 모서리 라운드 형태를 구성한다. 처음 왼쪽 위으 모서를 시작하여 시계방향으로 모서리의 각을 정의한다.
    • inset는 외부와 내부 라운드된 사각형간의 거리이다.
    • innerRadii는 두개를 쌍으로 내부 사각형의 모서리 라운드를 구성한다.
  • public Shader setShader(Shader shader)는 색상을 입히는 기능을 한다. 하위 클래스는 BitmapShader, ComposeShader, LinearGradient, RadialGradient, SweepGradient와 같은 클래스들이 있다.
  • public LinearGradient(float x0, float y0, float x1, float y1, int[] colors, float[] positions, Shader.TileMode tile )
    • 선형 색상 바르기 객체를 생성한다.
    • x0, y0 는 x축과 y축의 색상 바르기 시작점을 나타낸다.
    • x1, y1 는 색상 바르기 종착점을 나타낸다.
    • tile은 이미지의 타일 모드를 나타낸다.
  • public RadialGradient(float x, float y, float radius, int[] colors, float[]positions, Shader.TileMode tile)
    • 방사형 색상 바르기 객체를 생성한다.
    • x,y는 방사형 중심으로 색상 바르기를 나타낸다.
    • radius는 반지름을 나타낸다.
    • tile은 이미지의 타일 모드를 나타낸다.
  • public SweepGradient (float cx, float cy, int[] colors, float[] positions)
    • 쓸어내기 효과를 나타낸다.
    • cx와 cy는 쓸어내기의 중심을 나타낸다.

마름모 모형
private void pathShape() {
 Path path = new Path();
 path.moveTo(50, 0);
 path.lineTo(0, 50);
 path.lineTo(50, 100);
 path.lineTo(100, 50);
 path.close();

 ShapeDrawable drawable = new ShapeDrawable(new PathShape(path, 100, 100));
 drawable.setIntrinsicWidth(200);
 drawable.setIntrinsicHeight(100);

 int[] pixels = new int[] { 0xFFFF0000, 0xFF00FF00, 0XFF0000FF, 0 };
 Bitmap bm = Bitmap.createBitmap(pixels, 2, 2, Bitmap.Config.ARGB_8888);
 drawable.getPaint().setShader(new BitmapShader(bm, Shader.TileMode.REPEAT,Shader.TileMode.REPEAT));

 ImageView ivPath = (ImageView) findViewById(R.id.imageView4);
 ivPath.setImageDrawable(drawable);
}
  • moveTo(float x, float y) method는 다각형응ㄹ 그릴 최초 위치로 이동한다.
    • x와 y는 상대적인 위치로 화면의 위치와는 무관하다.
  • lineTo(float x, float y) method는 마지막 위치로부터 상대적인 위치의 좌표축으로 라인을 그린다.
  • public static Bitmap createBitmap(int[] colors, int width, int height, Bitmap.Config config) method는 주어진 색상을 사용하여 너비와 높이를 비트맵으로 만든다.
  • public BitmapShader(Bitmap bitmap, Shader.TileMode tileX, Shader.TileMode tileY) method는 비트맵을 사용하여 색상 바르기를 위한 세이더 객체를 생성한다.


관련글



[Android] 모형 자르기(Clip Drawable)

<?xml version=”1.0” encoding=”utf-8”?>
<clip
    xmlns:android=”http://schemas.android.com/apk/res/android”
    android:drawable=”@drawable/drawable_resource”
    android:clipOrientation=[”horizontal” | ”vertical”]
    android:gravity=[”top” | ”bottom” | ”left” | ”right” | ”center_vertical” |
                     ”fill_vertical” | ”center_horizontal” | ”fill_horizontal” |
                     ”center” | ”fill” | ”clip_vertical” | ”clip_horizontal”] />


  • android:drawable : Drawable resource을 참조하여 이미지를 설정한다.
  • android:clipOrientation : 이미지를 자르기 위해 이동하는 방향.
    • 자를 대고 이미지를 자른다고 생각하고 자가 이동하는 방향을 나타낸다.(좌,우,위,아래)
  • android:gravity: 자의 위치가 어느 방향으로 이동할지를 나타낸다.
    • android:clipOrientation이랑 틀린 점은 android:clipOrientation은 자가 움직일 수 있는 방향만을 제시했다면 android:gravity에서는 오른쪽에서 왼쪽으로 또는 왼쪽에서 위쪽으로 등과 같이 어디를 기준으로 setLevel() method에서 정해준 수치많큼 이동할 수 있는 방향을 제시한다.


<clip />에서는 자르는 방법을 제공하지 않고 자바 프로그램에서 setLevel()메서드를 이용하여 자르기 된다.
아래는 '안드로이드 개발자 사이트'에 있는 예제 소스이다.

<?xml version=”1.0” encoding=”utf-8”?>
<clip xmlns:android=”http://schemas.android.com/apk/res/android”
    android:drawable=”@drawable/android”
    android:clipOrientation=”horizontal”
    android:gravity=”left” />

<ImageView
    android:id=”@+id/image”
    android:background=”@drawable/clip”
    android:layout_height=”wrap_content”
    android:layout_width=”wrap_content” />

ImageView imageview = (ImageView) findViewById(R.id.image);
ClipDrawable drawable = (ClipDrawable) imageview.getDrawable();
drawable.setLevel(drawable.getLevel() + 1000);

<참고>
android:cliporientation="horizontal" 이므로 자르는 위치가 좌우로 움직인다.
android:gravity="left" 이므로 자는 왼쪽으로 움직인다.
위에서도 언급 했듯이 <clip />에서는 자르는 명령이 없다.
자바코드에서 잘라줘야 된다.

drawable.setLevel(drawable.getLevel() + 1000);

이 부분이 자르는 곳이다. <clip />에서 자를 좌우로 움직이며 왼쪽으로 움직이라고 설정해 놨으므로 이 기준을 가지고 위의 자바 코드에서 자를 수 있다.
위에 나온 1000이라는 수치를 자르기 레벨이라 하며 0 ~ 10,000 까지 제공한다. 반을 자를려면 5000을 주면 된다.


관련글

[Android] 모형 겹치기(Layer List)

<?xml version=”1.0” encoding=”utf-8”?>
<layer-list
    xmlns:android=”http://schemas.android.com/apk/res/android” >
    <item
        android:drawable=”@[package:]drawable/drawable_resource”
        android:id=”@[+][package:]id/resource_name”
        android:top=”dimension”
        android:right=”dimension”
        android:bottom=”dimension”
        android:left=”dimension” />
</layer-list>
  • android:drawable : Drawable resource 참조하여 이미지를 설정한다.
  • android:id : 유니크한 아이디를 만들 수 있다.
  • android:top : 상단 여백을 준다.
  • android:right : 왼쪽 여백을 준다.
  • android:bottom : 하단 여백을 준다.
  • android:left : 오른쪽 여백을 준다.

아래와 같이 <bitmap />을 사용할 수도 있다.
<item android:drawable=”@drawable/image” />

위의 코드를 아래와 같이 <bitmap />를 사용하여 똑같이 표현 할 수도 있다.
<item>
  <bitmap android:src=”@drawable/image”
          android:gravity=”center” />
</item>


아래는 '안드로이드 개발자 사이트'에 있는 예제 코드이다.
<?xml version=”1.0” encoding=”utf-8”?>
<layer-list xmlns:android=”http://schemas.android.com/apk/res/android”>
    <item>
      <bitmap android:src=”@drawable/android_red”
        android:gravity=”center” />
    </item>
    <item android:top=”10dp” android:left=”10dp”>
      <bitmap android:src=”@drawable/android_green”
        android:gravity=”center” />
    </item>
    <item android:top=”20dp” android:left=”20dp”>
      <bitmap android:src=”@drawable/android_blue”
        android:gravity=”center” />
    </item>
</layer-list>
관련글

[Android]상태 리스트 모형 (Selector)

<?xml version=”1.0” encoding=”utf-8”?>
<selector xmlns:android=”http://schemas.android.com/apk/res/android” 
    android:constantSize=[ ”true” | ”false” ]
    android:dither=[ ”true” | ”false” ]
    android:variablePadding=[ ”true” | ”false” ]>
    <item 
        android:drawable=”@[package:]drawable/drawable_resource”
        android:state_pressed=[ ”true” | ”false” ]
        android:state_focused=[ ”true” | ”false” ]
        android:state_selected=[ ”true” | ”false” ]
        android:state_checkable=[ ”true” | ”false” ]
        android:state_checked=[ ”true” | ”false” ]
        android:state_enabled=[ ”true” | ”false” ]
        android:state_window_focused=[ ”true” | ”false” ]/>
</selector>

<Selector /> 속성
  • android:constantSize : 이미지의 크기를 동일하게 할 것인가.(Default -> false)
  • android:dither : 화면상의 색상수와 이미지의 생상수가 차이가 존재하면 원래의 색감으로 맞추어주는 기능이다.(Default -> true)
  • android:variablePadding : 이미지에 따라 자동으로 패딩을 맞추어 주는 기능이다.

<Item /> 속성
  • android:state_pressed : 컴포넌트를 눌렀을 때.
  • android:state_focused : 컴포넌트가 포커스 되었을 때.
  • android:state_selected :  컴포넌트가 선택되어 졌을 때.
  • android:state_checkable : 체크 버튼처럼 선택 가능하도로 뷰를 만들 때.
  • android:state_checked : 체크 버튼처럼 선택되어졌을 때.
  • android:state_enable : 컴포넌트가 활성화 되어 졌을 때.
  • android:state_window_focused : 해당 컴포넌트를 담고 있는 창이 포커스 되었을 때. 즉 다른 애플리케이션에 의해 가려져 있다가 화면의 전면이 다시 나타났을 때.

아래는 '안드로이드 개발자 사이트'에 있는 예제 코드이다.
<?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/button_pressed” /> <!-- pressed -->
    <item android:state_focused=”true”
          android:drawable=”@drawable/button_focused” /> <!-- focused -->
    <item android:state_hovered=”true”
          android:drawable=”@drawable/button_focused” /> <!-- hovered -->
    <item android:drawable=”@drawable/button_normal” /> <!-- default -->
</selector>

<?xml version=”1.0” encoding=”utf-8”?>
<Button
    android:layout_height=”wrap_content”
    android:layout_width=”wrap_content”
    android:background=”@drawable
관련글

[Android] 형태모형(Shape Drawable)

Shape Tag 속성 및 하위 Tag 속성
<?xml version=”1.0” encoding=”utf-8”?>
<shape xmlns:android=”http://schemas.android.com/apk/res/android” 
    android:shape=[ ”rectangle” | ”oval” | ”line” | ”ring” ]>
    <corners 
        android:radius=””/> 
    <gradient 
        android:startColor=”” 
        android:centerColor=”” 
        android:endColor=”” 
        android:useLevel=”” 
        android:angle=”” 
        android:type=[ ”linear” | ”radial” | ”sweep” ]
        android:centerX=”” 
        android:centerY=”” 
        android:gradientRadius=””/>
    <padding 
        android:left=”” 
        android:right=”” 
        android:top=”” 
        android:bottom=””/>
    <size 
        android:width=”” 
        android:height=””/>
    <solid 
        android:color=””/>
    <stroke 
        android:width=”” 
        android:color=”” 
        android:dashWidth=”” 
        android:dashGap=””/>
</shape>


  • <shape /> : 형태 모형을 정의한다는 루트 요소이다. 속성은 'android:shape'이며 값은  rectangle, oval, line, ring 이다.
  • <corners /> : 가장자리를 둥글게 처리하는 요소이다. <shape />요소의 속성이 'android:shape="rectangle" ' 일때만 유효하다.
    • 'android:radius' : 사각형의 테두리 곡선을 나타낸다.
    • 'android:topLeftRadius',  'android:topRightRadius', 'android:bottomLeftRadius', 'android:bottomRightRadius' 각각 사용 할수 없다.UnsupportedOperationException 예외가 발생한다.
  • <gradient /> : 색상의 기울기를 처리하는 요소이다.
    • 'android:type' : 색상 기울기 패터을 지정한다.
      • linear : 선형으로 색상바르기. (Default)
      • radial : 방사형으로 색상바르기. 시작 컬러값과 중심 컬러값이 동일하다.
      • sweep: 쓸어내기식 색상바르기.
    • 'android:angle' : 색상의 기울기 각도로 정수로 환산한다. 값은 45의 배수이야하며, 디폴트 값은 0이다.android:type="linear" '의 경우에만 적용된다.
      • 0이면 좌측에서 우측으로 색상의 기울기가 지정된다.
      • 90이면 아래에서 위쪽으로 색상의 기울기가 지정된다.
    • 'android:centerX' : X축 중심의 상대위치를 의미한다. 사각형의 X축의 중심은 0.5로 환산하고 0 ~ 1.0의 실수값을 갖게 된다. 따라서 0에 가까운 값을 갖는다면 사각형 왼쪽면으로 중심이 이동하고 1에 가까우면 사각형의 오른쪽으로 중심이 이동한다. 만약 ' android:type="linear" '면 적용 되지 않는다.
    • 'android:centerY' : Y축 중심의 상대위치를 의미한다. 이하 속성은 'android:centerX'와 동일하다.
    • 'android:startColor' : 색상 기울기의 시작 컬러값을 나타낸다.
    • 'android:endColor' : 색상 기울기의 끝 컬러값을 나타낸다.
    • 'android:centerColor' : 'android:startColor' 값과 'android:endColor' 값 사이의 중간 컬러값을 나타낸다.
    • 'android:gradientRadius' : 색상 기울기의 반지름 값으로 실수를 계산한다. ' android:type="radial" '의 경우에만 적용된다.
  • <padding /> : 패딩값을 지정한다. 형태 모형을 지정하는게 아니고 <shape /> 요소 내 사용하는 뷰의 패팅값으로 사용한다. 단위는 Dimension 이다.
  • <size /> : 형태 모형의 크기를 정한다. 형태 모형의 크기는 결과적으로 뷰의 크기이다.
  • <solid /> : 단색으로 채울 때 처리하는 요소이다.
  • <stroke /> : 테두리나 선을 그릴 때 사용하는 요소이다. <shape />요소의 속성이 'android:shape="line" ' 일때 반드시 설정해 줘야 된다. 설정하지 않으면 NullPointerException 예외가 발생한다. 
    • 'android:dashGap' : 점선의 간격을 나타낸다. 간격은 치수로 표기한다.
    • 'android:dashWidth' : 점선의 두께값을 나타낸다.

2013년 1월 29일 화요일

[Android] Bitmap 모형

XML Bitmap 코드
<?xml version=”1.0” encoding=”utf-8”?>
<bitmap xmlns:android=”http://schemas.android.com/apk/res/android” 
     android:src=”@[package:]drawable/drawable_resource”
     android:antialias=[ ”true” | ”false” ]
     android:dither=[ ”true” | ”false”]
     android:filter=[ ”true” | ”false” ]
     android:gravity=[ ”top” | ”bottom” | ”left” | ”right” | ”center_vertical” | 
         ”fill_vertical” | ”center_horizontal” | ”fill_horizontal” | 
         ”center” | ”fill” | ”clip_vertical” | ”clip_horizontal” ]
     android:tileMode=[ ”disabled” | ”clamp” | ”repeat” | ”mirror” ]>
</bitmap>
  • android:src : 비트맵 이미지 소스
  • android:antialias : antialias 적용 여부
  • android:dither : dither효과 적용 여부
  • android:filter : 이미지를 축소하거나 늘렸을 때 기본 이미지를 변환시켜 선명도를 높이는 필터링 효과를 적용할 것인지 확인한다.
  • android:gravity : 이미지 위치를 나타낸다.
  • android:tileMode : tileMode를 설정하면 gravity 속성은 무시된다.

<참고>
  • Aliasing : 픽셀로 선을 표시하면 계단 현상이 발생한다. 이런 현상을  Aliasing이라 부른다.'android:antialias' 속성은 곡선을 부드럽게 처리 만들지를 정해주는 속성으로 해상도가 낮은 화면에서는 효과가 줄어든다.
  • Dithering : 화면의 제한된 컬러를 사용하여 본래의 높은 비트로 된 이미지의 컬로 효과를 최대한 복원하려는 영상처리 기법이다. 일반적으로 높은 비트의 컬러를 다른 컬러 패턴으로 대체하여 눈으로 하여금 연속적인 색상으로 인식하게 만든다.


JAVA Bitmap 코드
Bitmap 모형은 getResources()메서드와 getDrawable() 메서드를 사용하여 읽는다.
private void addResourceDrawable(LinearLayout layout, int resource) {
 View view = new View(this);
 final Drawable d = getResources().getDrawable(resource);
 view.setBackground(d);
 view.setLayoutParams(new LinearLayout.LayoutParams(d.getIntrinsicWidth(), d.getIntrinsicHeight()));
 layout.addView(view);
}
  • getIntrinsicWidth() method 와 getIntrinsicHeight() method는 모형이 가지고 있는 기본적인 너비와 높이를 제공한다.

모형을 조정하여 화면에 출력하고 싶다면 BitmapFactory class를 사용하여 만든다.
private void addResourceDrawable(LinearLayout layout, int resource) {
 View view = new View(this);
 BitmapFactory.Options opts = new Options();
 opts.inScaled = true;
 opts.inDither = true;
 final BitmapDrawable d = new BitmapDrawable(getResources(), BitmapFactory.decodeResource(getResources(), resource, opts));
 view.setBackground(d);
 view.setLayoutParams(new LinearLayout.LayoutParams(d.getIntrinsicWidth(), d.getIntrinsicHeight()));
 layout.addView(view);
}
  • BitmapDrawable class를 이용하여 간편하게 bitmap 파일을 Drawable파일로 변경 가능하다.
  • BitmapFactory.Options 클래스는 비트맵을 생설할때 적용하는 밀도라든가 크기 변경, Dither등의 옵션을 제공한다.
  • inSampleSize = 4의 뜻은 원본사이즈의 1/4 이라는 의미이다. 파일 용량이 너무 큰 이미지들은 Memory leak이 발생 할 확률이 높으므로 이 경우에는  inSampleSize 옵션을 이용하여 이미지를 줄인 다음 decodeResource() method로 읽어 드리면 된다. Tip으로 inSampleSize의 값은 2의 배수로 설정해 주는게 속도가 빠르다고 합니다. 

2013년 1월 28일 월요일

[Android] GridView 몇가지 속성

GridView 구현은 ListView구현과 별 다른게 없으나 GridView에서만 사용되는 속성이 몇가지 있어 그 내용을 정리해 보려고 합니다.

<?xml version=”1.0” encoding=”utf-8”?>
<linearlayout xmlns:android=”http://schemas.android.com/apk/res/android”
    android:layout_width=”match_parent”
    android:layout_height=”match_parent”
    android:orientation=”vertical” >

    <GridView
        android:id=”@+id/gridView”
        android:layout_width=”match_parent”
        android:layout_height=”match_parent”
        android:verticalSpacing=”10dip”
        android:horizontalSpacing=”10dip”
        android:numColumns=”auto_fit”
        android:columnWidth=”60dip”
        android:stretchMode=”columnWidth”
        android:gravity=”center”/>

</LinearLayout>


  • numColumns : GridView의 행에 나열할 컬럼의 개수(1~n개)를 지정한다. 'auto_fit'으로 설정하면 사용 가능한 공간에 따라 자동으로 컬럼의 개수가 정해진다.
  • verticalSpacing과 horizontdalSpacing : GridView의 셀 간격을 설정한다.
  • columnWidth : 컬럼의 너비를 설정한다.
  • stretchMode : numColumns를 'auto-fit'로 설정했을 경우 남는 좌우 공간을 어떻게 분배할지 결정한다. 'columnWidth'는 남은 공간이 칼럼들에게 골고루 할당되며, 'spacingWidth'는 컬럼들에게 여백으로 남은 공간을 골고루 할당한다.



[Android] Spinner 구현

Spinner를 구현하는 방식에는 2가지가 있습니다.
xml에서 'android:prompt' 와 'android:entries'속성을 이용하여 구현하는 방식과
자바코드에 createFromResource(context, textArrayResId, textViewResId); method 와 setDropDownViewResource(resource); method를 이용하여 setAdaptger(adapter); 하는 방식이 입니다.

개인적으로는 2번째 방식을 많이 사용하지만 2가지 경우에 대해 설명 드리겠습니다.

설명에 앞서 공통으로 사용 할 Listener 코드입니다. Spinner에서는 onSelectedListener를 사용합니다.

private class MyOnItemSelectedListener implements OnItemSelectedListener {

 @Override
 public void onItemSelected(AdapterView parent, View view, int pos,
   long id) {
  // TODO Auto-generated method stub
  Toast.makeText(parent.getContext(),
    "The planet is " + parent.getItemIdAtPosition(pos),
    Toast.LENGTH_LONG).show();
 }

 @Override
 public void onNothingSelected(AdapterView parent) {
  // TODO Auto-generated method stub
  // Do nothing
 }

}


1. xml 방식.
<?xml version=”1.0” encoding=”utf-8”?>
<linearlayout xmlns:android=”http://schemas.android.com/apk/res/android”
    android:layout_width=”match_parent”
    android:layout_height=”match_parent”
    android:orientation=”vertical” >

    <Spinner
        android:id=”@+id/spinner1”
        android:layout_width=”match_parent”
        android:layout_height=”wrap_content” 
        android:prompt=”@string/planet_prompt”
        android:entries=”@array/planets_array”/>

</LinearLayout>

android:prompt="@string/planet_prompt" 속성은 Spinner에 표기되는 제목 속성이며,
android:entries="@array/planets_array" 속성은 스피너에 출력되는 자료를 연결 하는 속성입니다.
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

  Spinner spinner = (Spinner) findViewById(R.id.spinner1);
  spinner.setOnItemSelectedListener(new MyOnItemSelectedListener());

 }


2.JAVA코드 방식.
<?xml version=”1.0” encoding=”utf-8”?>
<linearlayout xmlns:android=”http://schemas.android.com/apk/res/android”
    android:layout_width=”match_parent”
    android:layout_height=”match_parent”
    android:orientation=”vertical” >

    <Spinner
        android:id=”@+id/spinner1”
        android:layout_width=”match_parent”
        android:layout_height=”wrap_content”/>

</LinearLayout>

'android:prompt' 속성과 'android:entries'을 xml에서 제외 시켜 주고 JAVA 코드에서 작성하면 된다.
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

  spinner.setPrompt(getResources().getString(R.string.planet_prompt));
  ArrayAdapter adapter = ArrayAdapter.createFromResource(this, R.array.planets_array,
    android.R.layout.simple_spinner_item);
  adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
  spinner.setAdapter(adapter);
  spinner.setOnItemSelectedListener(new MyOnItemSelectedListener());
 } 


Spinner 구현이 어려운 내용은 없으나 테스트 하다가 의문점은 android:prompt 속성이 갤럭시 노트2에서는 적용이 안되는 점이였습니다. 여러 Device를 테스트 해 보지는 못했지만 아마 아이스크림 샌드위치로 넘어오면서 사라진게 아니면 Device를 타는 것 같습니다.





2013년 1월 17일 목요일

[Android] View 의 화면 출력 코드

View를 상속 받아서 화며에 출력하는 코드이다. 이전에 작성한 View Class의 Callback Method 를 참조하여 보면 된다.
  • MainActivity.java
public class MainActivity extends Activity {

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  this.setTitle("화면 출력 과정");
  // 선형레이아웃을 만든다.
  LinearLayout root = new LinearLayout(this);
  root.setOrientation(LinearLayout.VERTICAL);
  root.setGravity(Gravity.CENTER);
  root.setLayoutParams(new LinearLayout.LayoutParams(
    LinearLayout.LayoutParams.MATCH_PARENT,
    LinearLayout.LayoutParams.MATCH_PARENT));

  // 리소스에서 비트맵 모형을 읽어 bitmap 객체를 만든다.
  Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
  MakeView view = new MakeView(this, bitmap);
  // view.setLayoutParams(
  // new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
  // LinearLayout.LayoutParams.WRAP_CONTENT));
  root.addView(view);
  setContentView(root);
 }

 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
  // Inflate the menu; this adds items to the action bar if it is present.
  getMenuInflater().inflate(R.menu.activity_main, menu);
  return true;
 }

}


  • MakeView.java

public class MakeView extends View {
 private final Bitmap mBitmap;

 public MakeView(Context context, Bitmap mBitmap) {
  super(context);
  this.mBitmap = mBitmap;
  // TODO Auto-generated constructor stub
 }

 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  // TODO Auto-generated method stub
  super.onMeasure(widthMeasureSpec, heightMeasureSpec);
  final DisplayMetrics metrics = getResources().getDisplayMetrics();
  setMeasuredDimension(mBitmap.getScaledWidth(metrics), mBitmap.getScaledHeight(metrics));
 }

 @Override
 protected void onDraw(Canvas canvas) {
  // TODO Auto-generated method stub
  super.onDraw(canvas);
  canvas.drawBitmap(mBitmap, 0.0f, 0.0f, null);
 }
}


뷰에 적용할 크기는 setMeasuredDimension()를 호출하여 설정한다.
setMeasuredDimension() 메서드는 꼭! onMeasure() Callback Method 내에서 호출되어야 한다.

view.setLayoutParams()메서드만으로는 뷰의 위치와 크기가 정할 수 없다. 뷰 클래스를 상속받는 클래스에서  onMeasure() Callback Method를 Override하여 뷰의 위치와 크기를 정해 주어야 한다. 이때 사용하는 메서드가 setMeasuredDimmension()메서드이다.

setMeasuredDimmension() 메서드에 의하여 상단 레이아웃의 너비와 크기에 맞추어 뷰의 너비와 크기를 맞추게 되므로 ViewGroup.LayoutParams.WRAP_CONTENT와 ViewGroup.Layoutparams.WRAP_CONTENT 속성을 제거해도 동일한 결과를 나타낸다.

onMeasure() 와 onDraw()는 기본적인 Callback Method 이다.


[Android] 새로운 예외 정의 코드

public class MyException extends Exception {
 private static final long serialVersionUID = 1L;
 private final int ERROR_CODE = 300;
 private String reason;

 public MyException(String reason) {
  super();
  this.reason = reason;
 }

 public int getException() {
  return ERROR_CODE;
 }

 public String toString() {
  return reason;
 }
}

[Android] KeyEvent 및 dispatchKeyEvent 정리

아래 소스는  onKeyDown() , onKeyUp(), onKeyLongPress() Callback Method를 Override 받은 상태이다.

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
 // TODO Auto-generated method stub
 if (keyCode == KeyEvent.KEYCODE_Q && event.getRepeatCount() == 0) {
  event.startTracking();
 }
 return super.onKeyDown(keyCode, event);
}

@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
 // TODO Auto-generated method stub
 if (keyCode == KeyEvent.KEYCODE_BACK && event.isTracking() && !event.isCanceled()) {
   return true;
 }
 return super.onKeyUp(keyCode, event);
}

@Override
public boolean onKeyLongPress(int keyCode, KeyEvent event) {
 // TODO Auto-generated method stub
 if (keyCode == KeyEvent.KEYCODE_Q) {
  Log.v(TAG, "길게 누름...");
  return true;
 }
 return super.onKeyLongPress(keyCode, event);
}

@Override
public boolean dispatchKeyEvent(KeyEvent event) {
 // TODO Auto-generated method stub
 Log.v(TAG, "dispatchKeyEvent..");
 return super.dispatchKeyEvent(event);
}

# 테스트 결과

  • 최신 버전에서는 하드 키보드나 소프트 키보드를 통해 일반 키들을 입력하면  onKeyDown() Callback Method를 지원하지 않고 바로 onKeyUp() Callback Method 만 지원하고있다.
  • onKeyDown() Callback Method가 호출 되려면 일반 키보드키가 아닌 MENU 나 Back 버튼을 누르면 호출 된다.
  • onKeyLongPress() Callback Method를 호출하려면 onKeyDown() Callback Method에서 event.startTracking() 메서드를 호출하여야 지원 가능하며 onKeyUP() Callback Method에서는 지원하지 않는다.
  • startTracking() 메서드는 onKeyDown() Callback Method 이외에서는 사용 할 수 없다.
  • dispatchKeyEvent() Callback Method는 모든 KeyEvent를 관리하는 Callback Method이므로 위와 같이 다른 KeyEvent Callback Method 함께 사용 하지 못하며 dispatchKeyEvent()만 사용 할 수 있다.

위 테스트에서 알 수 있듯이 하드키보드와 소프트키보드 내 중복되어 표시되는 일반 문자와 숫자는 개발자에게  onKeyUp() Callback Method만 제공하고, onKeyDown()메서드는 안드로이드 내부 시스템에서 처리한다.

또한 dispatchKeyEvent() Callback Method라고 하더라도 Power키 같은 특수한 기능을 하는 키들은 전혀 작동하지 않는다. 그이유는 화면 상의 작업보다 특수한 기능들이 우선이기 때문이다.(ex. 전화 수신과 통화 기능 화면상에서 작업이 우선이다.)

[Android] Listener와 Callback Method 그리고 Trigger

Callback Method는 프로그래머가 그 메서드를 호출하여 직접 실행하는 것이 아니라 이벤트 또는 메시지 등을 받았을 때 자동으로 실행되는 메서드를 말한다. 안드로이드에서는 on으로 시작하는 메서드는 대부분 Callback Method 이다.

아래 표는 Listener 와 Callback Mehtod 그리고 Trigger를 정리한 표이다.




[Android] android.view.View 클래스에서 제공하는 콜백 메서드 표.

View를 extends 하여 화면을 구성 할 경우 참고하면 된다.

화면 출력과 관련하여 가장 기본적인 메서드는 onMeasure()onDraw() 콜백 메서드 이다.

아래의 표는 android.view.View 클래스에서 제공하는 콜백 메서드 표이다.



[Android] getSystemService(String name) 반환 객체 표

getSystemService() 메서드를 사용하여 성공적으로 객체를 생성하게 된다면 대부분 'Manager'라는 접미어가 붙은 관리 매니저 객체를 반환한다.

getSystemService(String name) 메서드의 매개변수를 사용하여 다음 표와 같은 객체를 얻는다.







[Android] ScrollBar 모양 설정

<scrollviwe xmlns:android:”http:/schemas.android.com/apk/res/android”
     android:layout_width=”match_parent”
     android:layout_height=”match_parent”
     android:scrollbarTrackVertical=”@drawable/scrollbar_vertical_track”
     android:scrollbarThumbVertical=”@drawable/scrollbar_vertical_thumb”
     android:scrollbarSize=”11dip”>
 # scrollbar_vertical_track.xml 파일 내용
<shape xmlns:android:”http:/schemas.android.com/apk/res/android”>
     <gradient android:startColor = ”#505050” 
               android:endColor=”#C0C0C0”
               android:angle=”0”/>
     <corners andorid:radius=”0dip”/>
</shape>
# scrollbar_vertical_track.xml 파일 내용
<shape xmlns:android:”http:/schemas.android.com/apk/res/android”>
     <gradient android:startColor = ”#3333FF” 
               android:endColor=”#8080FF”
               android:angle=”0”/>
     <corners andorid:radius=”6dip”/>
</shape>

[Android] ImageView 속성

안드로이드 개발을 하면서 많이 쓰이는 View 중 하나인 ImagView 의 속성 입니다.


  • adjustViewBounds : 이미지가 표현하고자 하는 레이아웃 보다 클때 비율을 그대로 유지할지 확인 한다.
  • cropToPadding : 이미지가 레이아웃보다 크다면 잘라 낼 것인지에 확인한다. 보통 레이아웃에서 제공하는 공간(패딩이나 여백을 제외한 공간)에 맞추어 이미지를 잘라내게 된다.
  • maxHeight : 이미지뷰의 최대 높이
  • maxWidth : 이미지뷰의 최대 너비
  • tint : 이미지에 대한 엷은 색조를 나타낸다. 컬러값을 입력한다.
  • scaleType : 아래 표와 같이 이미지의 표시를 위한 크기변환(scaling)과 채워넣기 옵션을 말한다.


2013년 1월 11일 금요일

[Android] 임시 파일 생성

File file = new File(context.getFilesDir() + "sample.png");
 if (!file.exists()) {
  try {
   file.createNewFile();
  } catch (IOException e) {
   e.prinStackTrace();
  }
        }

2013년 1월 10일 목요일

[Android] Intent 활용 예제

안드로이드 Intent 활용 예제


  • 연락처 Intent
//   연락처 조회 
Intent intent = new Intent(Intent.ACTION_VIEW,
     Uri.parse("content://contacts/people" + String.valueOf(contact.getId()))); 
startActivity(intent); 
//   연락처 등록 
Intent intent = new Intent(Intent.ACTION_INSERT,
     Uri.parse("content://contacts/people")); 
startActivity(intent); 
//   연락처 수정 
Intent intent = new Intent(Intent.ACTION_EDIT,
     Uri.parse("content://contacts/people" + String.valueOf(contact.getId()))); 
startActivity(intent); 
//   연락처 삭제 
Intent intent = new Intent(Intent.ACTION_DELETE,
     Uri.parse("content://contacts/people" + String.valueOf(contact.getId()))); 
startActivity(intent); 

  • 전화 Intent
//   전화걸기 화면 
Intent intent = new Intent(Intent.ACTION_DIAL,
     Uri.parse("tel:" + TelNumber)); 
startActivity(intent); 
//   전화걸기 
Intent intent = new Intent(Intent.ACTION_CALL,
     Uri.parse("tel:" + TelNumber)); 
startActivity(intent); 

  • SMS Intent
//   SMS 발송 화면 
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.putExtra("sms_body", "The SMS text"); 
intent.setType("vnd.android-dir/mms-sms"); 
startActivity(intent); 
//   SMS 보내기 
Intent intent = new Intent(Intent.ACTION_SENDTO,
     Uri.parse("sms_body:" + "The SMS text")); 
intent.setType("vnd.android-dir/mms-sms"); 
startActivity(intent); 

  • 이메일 Intent
//   이메일 발송 화면 
Intent intent = new Intent(Intent.ACTION_SENDTO,
     Uri.parse("mailto:" + "The 이메일 text")); 
startActivity(intent); 

  • 브라우저 Intent
//   브라우저에서 URL 호출하기 
Intent intent = new Intent(Intent.ACTION_VIEW,
     Uri.parse("http://www.google.com/")); 
startActivity(intent); 
//   브라우저에서 검색 
Intent intent = new Intent(Intent.ACTION_WEB_SEARCH); 
intent.putExtra(SearchManager.QUERY, "검색어"); 
startActivity(intent); 

  • 지도 Intent
//  지도 화면 
Intent intent = new Intent(Intent.ACTION_SENDTO,
     Uri.parse("geo: 38.00, -35.03")); 
startActivity(intent);

  • 안드로이드 마켓 Intent
//   안드로이드 마켓에서 App 검색 
Intent intent = new Intent(Intent.ACTION_VIEW,
     Uri.parse("market://search?q=pname:전체패키지명")); 
startActivity(intent);
//   안드로이드 마켓에서 App 상세 화면 
Intent intent = new Intent(Intent.ACTION_WEB_SEARCH,
     Uri.parse("market://details?id=전체패키지명")); 
startActivity(intent);

  • App 삭제 Intent
//   안드로이드 마켓에서 App 삭제 
Intent intent = new Intent(Intent.ACTION_DELETE); 
intent.setData(Uri.parse("전체패키지명")); 
startActivity(intent);