본문 바로가기

구글과인터넷/안드로이드

Android에서 외부 한글폰트 넣어 적용하기 관련

출처: http://sunmo.blogspot.kr/2010/12/android-%ED%8F%B0%ED%8A%B8%EA%B8%80%EC%94%A8%EC%B2%B4%EB%B3%80%EA%B2%BD-%ED%95%98%EA%B8%B0-fonttype-change.html


[Android] 폰트(글씨체)변경 하기 (FontType Change)

 

 

 

 

안드로이드를 개발하다보면 제공해주는 글씨체가 3개밖에 없습니다.

그래서 보다 더 깔끔하고 이쁘게 꾸미기 위해

폰트를 변경하는 방법을 적어보도록 하겠습니다.

C:\WINDOWS\Fonts폴더에 보시면 윈도우에 제공해주는 폰트들이 있습니다.

그중에 아래 그림의 아이콘이 안드로이드에서 사용가능한 폰트파일 입니다.

 

원하시는 폰트를 복사해서

안드로이드 프로젝트에 assets/fonts 폴더 아래 넣어주게 합니다.

그리고

 

자바파일:
TextView tv=(TextView)findViewById(R.id.custom);
Typeface face=Typeface.createFromAsset(getAssets(), "fonts/폰트이름.ttf");

main.xml 파일:

<TextView
            android:id="@+id/custom"
            android:text="Hello, world!"
            android:textSize="20sp" />

 

 

이런식으로 폰트를 변경 할 수 있습니다.

현재는 TextView 단일 위젯만 변경이 가능하지만, 혹시 클래스나

레이아웃 전체를 변경 하실 수 있는 방법을 아시는 분은 좀 알려주세요 ㅠ.ㅠ

 

 

 

 

ps. 안드로이드로 사용가능한 폰트 몇개 올려둡니다.

 

//////////////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////////////


출처: http://astro.tistory.com/53

Android 앱을 개발하면서 Android 플랫폼에 기본 탑재 되어 있는 폰트들만 쓸 수 있다면 UI가 너무 단순해 지지 않을까요?

Android 플랫폼에서 기본으로 제공하고 있는 폰트들은 다음과 같습니다.

sans, serif, monospace

위 세가지 폰트는 모두 Acsender에서 Open Handset Alliance에 제공한 드로이드 폰트입니다. 위 세가지 폰트의 경우에는 다음과 같이 Layout XML파일에서 아주 쉬운 방법으로 앱 개발 시 적용할 수 있습니다. 




    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Crazy 한글"
        android:textColor="@color/black"
        android:textSize="20dp"
        android:typeface="sans">
    </TextView>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Crazy 한글"
        android:textColor="@color/black"
        android:textSize="20dp"
        android:typeface="serif">
    </TextView>

     <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Crazy 한글"
        android:textColor="@color/black"
        android:textSize="20dp"
        android:typeface="monospace">
    </TextView>   

위 방법은 정말 쉽지 않은가요? 하지만 위 폰트들로 만족스럽진 않습니다. 정말 기본 폰트이기 때문에 무난한 느낌이 강합니다. 좀 더 사용자에게 친근하고 임팩트 있게 다가가려면 그 앱의 성격에 맞는 글자 스타일 또한 UI에서 빠져서는 안되기 때문입니다.

UI에 맞는 폰트를 쓰기위해 모두 이미지로 작업하는 것이 얼마나 소모적인 일인지는 모두 공감할 것입니다. 물론 외부 폰트 파일을 Android Project에 넣어 놓고 사용하는 방법이 존재합니다. 구글에서 검색하면 무료 영문 폰트, 한글 폰트 들이 존합니다. 물론 상용 앱을 만들 때는 그 폰트가 가지고 있는 라이센스를 확인하는 것은 필수입니다. 검색을 통해 사용할 폰트( TTF 형식의 파일만 가능 )를 다운로드 받는 것이 우선이겠죠? 그럼 외부 폰트를 적용하는 방법에 대해 설명하겠습니다. 

1. Project 디렉터리에서 assets폴더에 하위 폴더로 fonts폴더 생성 후 사용하고자 하는 폰트파일을 저장합니다.







2. 자바 코드에서 외부 글꼴을 사용할 수 있도록 지정 후 사용하고자 하는 컨트롤에 설정합니다. 

TextView fontTextView = (TextView) findViewById(R.id.font_text_view);
Typeface typeface = Typeface.createFromAsset(getAssets(), "fonts/nanumpen.ttf");
fontTextView.setTypeface(typeface);
 
위 방식또한 그리 어렵지 않게 할 수 있습니다. 하지만 이렇게 간단하게 끝나면 Android 개발이 아닌 것이죠? Android 앱 개발은 온갖 삽질을 통해 개발자를 단련시키기 때문입니다. (스트레스도 무진장 많이 받죠...ㅠ.ㅠ)

영문 전용 폰트라면 위 방식대로 하면 전혀 문제없이 외부폰트를 사용할 수 있습니다. 하지만 한글 폰트라면 이야기가 달라집다. 한글 폰트가 적용되지 않는 문제가 발생합니다. 분명 한글 폰트 파일을 넣어 위 방식대로 했지만 실행해 보면 한글폰트가 기본 폰트로 적용되어 있는 것을 볼 수 있습니다. 간혹 적용되는 한글 폰트도 있어 저는 안드로이드에 맞는 한글 폰트를 따로 적용해야한다는 어처구니 없는 결론을 한달 전에 내리게 되었습니다.

제가 내린 그 결론은 물론 잘못되었습니다. 그리고 시중에 나와있는 안드로이드 개발 서적들에서도 적용되지 않는 한글폰트가 있다고만 알려주지 해결책은 제시하지 못하는 듯합니다. (아님 제가 검색 능력이 부족해 모르거나요 ^^;;)

서론이 또 길어졌습니다. 결론 부터 말하자면 asset폴더에 폰트파일을 넣어 사용하는 것에 문제가 있는 것입니다.  assets는 실제 앱의 리소스가 아니라 그냥 미가공된 파일로 존재하게 됩니다. 그래서 리소스폴더인 res와는 달리 하위 디렉터리의 깊이가 정해져 있지 않으며 assets/fonts 처럼 하위 폴더로 관리가 가능한 것입니다. 그리고 이 파일들은 리소스 ID가 정해지지 않기 때문에 /assets로 시작하는 상대 경로에서 /assets를 제외한 경로명을 이용하여 불러올 수 있습니다. 이 assets폴더안의 파일을 사용할 때 Android 플랫폼 2.3 (진저브레드)이전 버전에서는 사용할 수 있는 파일의 최대 크기가 1048576 byte로 1Mbyte정도로 제한되어 있습니다.Android 플랫폼 2.3 (진저브레드) 버전부터는 최대 크기 제한이 사라져 위 외부폰트 적용 방식대로 사용할 수 있지만 안드로이드 단말 사용자가 진저브레드로 업데이트 한다는 보장도 없을 뿐더러 앱의 하위 호환성에도 문제가 발생하게 됩니다. 그래서 앱에서 외부의 스타일리쉬한 한글 폰트를 사용하기 위해서는 아래와 같은 방법으로 개발을 해보는 것도 좋을 듯 합니다.   

트루타입의 한글폰트들은 폰트의 스타일에 따라 다르겠지만 기본적으로 1Mbyte를 넘기는 파일들이 대다수입니다. 그럼 assets폴더에 폰트파일을 저장할 때 1Mbyte단위로 분할 하여 저장하고 앱이 설치되고 처음 실행 할 때 해당 폰트파일을 단말내부(앱 내부 캐시공간, SD카드)에 분할된 폰트파일을 다시 하나로 합쳐 사용하면 된다는 생각이 들었고 제가 구현한 코드는 다음과 같습니다. ( 귀차니즘에 대충 코딩했으니 이해해주세요..^^)

폰트파일을 분할하는 방법으로는 직접 프로그래밍 해서 쓰는 방법, 프로그램을 구해서 나누는 방법이 있습니다. 전 직접 프로그래밍해서 분할했지만 나중에 보니 Mac OS에서는 콘솔을 통해 다음과 같은 명령어를 실행하여 파일을 분할 하실 수 있습니다.
Windows에서는 free 프로그램이 많으니 구글에서 검색해서 사용하시면 됩니다. 

[ Mac OS에서 파일 분할 하기 ]
$ split -b 1000000 newfont.ttf newfont_

 
[assets에 분할되어 있는 폰트파일 다시 합쳐서 정상 폰트파일 로컬에 저장하기]
// assets에 분할되어 있는 폰트파일 다시 합쳐서 정상 폰트파일 로컬에 저장하기
private void copyFont() throws IOException{
        AssetManager assetManager = null;
        InputStream[] arrIs = new InputStream[5]; // assets 폴더에 있는 분할된 파일 갯수 5개
        BufferedInputStream[] arrBis = new BufferedInputStream[5]; // assets 폴더에 있는 분할된 파일 갯수 5개

        FileOutputStream fos = null;    
        BufferedOutputStream bos = null;
        
        String outFileName = "/data/data/" + getPackageName() + "/newfont.ttf";
        //String outFileName = Environment.getExternalStorageDirectory().getAbsolutePath() + "/font_test/newfont.ttf";
                
        try
        {
            File f = new File(outFileName);

            // 혹시나 파일이 있으면 지우고 0바이트의 파일을 새로 만든다.
            if(f.exists())
            {
                f.delete();
                f.createNewFile();
            }

            assetManager = this.getAssets();

            for(int i = 0; i < arrIs.length; i++)
            {
                arrIs[i] = assetManager.open("fonts/newfont" + (i + 1) + ".ttf");
                arrBis[i] = new BufferedInputStream(arrIs[i]);
            }

            fos = new FileOutputStream(f);
            bos = new BufferedOutputStream(fos);

            int read = -1;
            byte[] buffer = new byte[1024];

            for(int i = 0; i < arrIs.length; i++)
            {
                while((read = arrBis[i].read(buffer, 0, 1024)) != -1)
                {
                    bos.write(buffer, 0, read);
                }

                bos.flush();
            }
            Log.i("FONT COPY", "Copying Complete ");                
        }
        catch(Exception e){
            Log.i("FONT COPY Exception", e.toString());                
        }
        
        finally
        {
            for(int i = 0; i < arrIs.length; i++)
            {
                try{if(arrIs[i] != null) arrIs[i].close();}catch(Exception e){}
                try{if(arrBis[i] != null) arrBis[i].close();}catch(Exception e){}
            }

            try{if(fos != null) fos.close();}catch(Exception e){}
            try{if(bos != null) bos.close();}catch(Exception e){}

            arrIs = null;
            arrBis = null;
        }
    }

[분할 후 합친 정상폰트 파일 적용 방법]
try {
    copyFont();
} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}
        
String outFileName = "/data/data/" + getPackageName() + "/newfont.ttf";
//String outExtFileName = Environment.getExternalStorageDirectory().getAbsolutePath() + "/font_test/newfont.ttf";
        
TextView fontTextView = (TextView) findViewById(R.id.font_text_view);
Typeface typeface = Typeface.createFromFile(outFileName);
fontTextView.setTypeface(typeface);

안드로이드는 그냥 되는게 없는 것 같습니다. 개발자 단련 플랫폼의 종결자!!! 안드로이드!!
아래는 외부 폰트가 적용된 스크린샷입니다. 개발자의 절절함이 보이지 않습니까?