홈으로 홈으로 | 무료회원가입 | 아이디/비번찾기 | 즐겨찾기
추천음악방송메인홈1대1상담음악방송청취
뽕짝아가씨(무료음악채널)
okTrot(무료음악채널)
전통가요(무료음악채널)

온라이브스토어(앱다운로드)
온라이브(방송등록및청취)

환상의뽕짝파티 무료음악
명작트로트메들리 무료음악
트로트메들리관광 무료음악
동영상노래방
가사검색

POP Player
신나는 고스톱
컴퓨터 오목
작은 음악다방
자동러시 웹플레이어신청

보안∵서버∵쿠키
윈도우∵프레임
이미지∵배경
시간∵달력∵계산
상태바∵타이틀바
음악∵영상
폼∵전송∵테이블
키보드∵마우스
효과∵링크∵메뉴
Script∵php
기타
PHP 강좌
윈도우관련팁
웹관련팁
홈페이지제작팁
기본강좌
레지스트리
윈도우서버
리눅스서버
Android
안드로이드 앱 커스텀 글꼴 넣기
4년 전

안드로이드 앱 커스텀 글꼴 넣기


저는 안드로이드의 기본 글꼴 Droid Sans가 그다지 못생겼다고 생각하지는 않지만 글꼴은 앱의 인상에 상당히 큰 영향이 있는 것 같습니다. 특히 버튼 등 이미지로 만들어 놓은 UI와 동적으로 변하는 텍스트의 글꼴이 다르면 많이 어색합니다. 그래서 이 글에서는 앱 수준에서 전체적인 글꼴을 바꾸는 방법을 알아보겠습니다.

준비

재배포가 자유로운 글꼴을 준비합니다. 사실 그런 한글 글꼴은 나눔글꼴이 거의 유일하죠. 영문 글꼴은 선택의 폭이 훨씬 넓습니다.

참고로 TrueType 글꼴보다 OpenType 글꼴의 용량이 훨씬 적은 것 같으니, otf 파일을 사용하시면 앱 용량이 무식하게 커지는 것을 막을 수 있습니다. 요즘 나오는 기종은 괜찮은데, 저처럼 내장 메모리가 적은 디자이어 같은 폰을 쓰시는 분들에게는 용량이 크면 좀 치명적이거든요.

기본

글꼴 파일을 assets/ 디렉토리에 넣습니다. 그리고 글꼴을 불러온 뒤, 글꼴을 지정하기 원하는 뷰에 setTypeface 메소드를 호출하면 됩니다. 코드로 나타내면 다음과 같이 됩니다.
Typeface typeface = Typeface.createFromAsset(getAssets(), "font.ttf");
TextView textView = (TextView) findViewById(R.id.textView);
textView.setTypeface(typeface);

// 굵은 글꼴이 따로 있을 때 추가로 해줘야 하는 부분
Typeface boldTypeface = /* ... 위와 같은 방법 ... */;
textView.setTypeface(boldTypeface, Typeface.BOLD);


여기까지만 보면 상당히 쉬워보이지만 한가지 문제가 있습니다.

용량이 큰 글꼴 집어넣기

바로, assets 디렉토리에 넣은 글꼴 파일의 용량이 클 경우 읽어오지 못하는 문제가 발생합니다. 대부분의 한글 글꼴은 용량이 크기 때문에 일반적인 방법으로는 읽어올 수가 없습니다. 과연 어떻게 해야 읽어올 수 있을까요?

한참 구글링한 끝에 쪼개서 넣고 합치는 방법을 발견했지만 뭔가 깔끔하지가 않아서, 근본적인 문제(왜 용량이 큰 asset은 읽어오지 못할까)를 조사해봤습니다.

알고 보니 apk 파일을 만드는 과정에서 특정 확장자(jpg, png, mp3 등)가 아닌 파일은 압축이 되며, 압축이 되고 나면 압축 해제 시 용량이 1MB를 넘는 경우 런타임에 사용할 수 없어진다고 합니다. (출처, 진저브레드부터는 이 제한이 사라졌습니다. 아마도 최소 요구 메모리가 늘어났기 때문으로 보입니다.)

그래서 결론적으로, 글꼴 파일의 확장자를 mp3로 바꾸면 압축 대상에서 제외되며, 읽어올 수 있게 됩니다! 다소 황당하지만 이 방법을 쓰면 1MB 제한을 벗어날 수 있습니다.

레이아웃 전체에 적용하기

앞서 살펴본 코드에서는 한번에 뷰 하나씩 일일히 글꼴을 적용해 줘야 했는데요. 귀찮기도 할 뿐더러 실수할 확률이 높고 레이아웃이 바뀔 때마다 고쳐야 한다는 문제가 있습니다.

그러니 AndroidManifest.xml 같은 곳에 지정할 수 있는 방법이 있으면 좋겠지만 안타깝게도 그런 건 없습니다. 그래서 최상위 뷰를 찾아서 트리를 타고 내려가면서 글꼴을 적용한다는 아이디어를 생각해냈습니다. 대략 다음과 같이 하면 됩니다.
private Typeface mTypeface;

@Override
protected void onCreate(Bundle icicle) {
    super.onCreate(icicle);
    setContentView(R.layout.fontTest);
    mTypeface = Typeface.createFromAsset(getAssets(), "font.ttf.mp3");
    ViewGroup root = (ViewGroup) findViewById(android.R.id.content);
    setGlobalFont(root);
}

void setGlobalFont(ViewGroup root) {
    for (int i = 0; i < root.getChildCount(); i++) {
        View child = root.getChildAt(i);
        if (child instanceof TextView)
            ((TextView)child).setTypeface(mTypeface);
        else if (child instanceof ViewGroup)
            setGlobalFont((ViewGroup)child);
    }
}


일단 전체적인 구조는, 뷰 여러 개를 담고 있는 ViewGroup(LinearLayout 등)을 만나면 재귀적으로 호출해서 트리를 타고 내려가는 겁니다. 위의 코드에서 주의할 점 몇 가지를 살펴보겠습니다.
•findViewById(android.R.id.content)는 최상위 뷰를 찾기 위한 코드입니다. 안드로이드 내부에 의존하기 때문에 조금 불안하긴 하지만, 일단 잘 돌아가니까 놔둡시다.
•루트 뷰를 찾아서 setGlobalFont를 부르는 작업은 반드시 setContentView를 호출한 후에 해야 합니다.
•setGlobalFont에서는 현재 TextView의 글꼴만 바꿔주고 있는데 TextView의 서브클래스가 아닌 뷰의 글꼴을 바꾸시려면 직접 추가해주셔야 합니다. 참고로 Button이나 EditText 등 대부분의 텍스트를 가진 뷰들은 TextView를 상속하고 있습니다.

앱 전체에 적용하기

위에서 설명한 방법을 사용해도 여전히 각 액티비티마다 글꼴 지정 코드를 넣어야 합니다. 수고를 덜기 위해서 별도의 기반 클래스를 하나 만들어서 사용하면, 액티비티 클래스마다 따로 지정하지 않고 상속만 해서 글꼴을 적용할 수 있습니다.
public class BaseActivity extends Activity {
    private static Typeface mTypeface;

    @Override
    public void setContentView(int layoutResID) {
        super.setContentView(layoutResID);

        if (BaseActivity.mTypeface == null)
            BaseActivity.mTypeface = Typeface.createFromAsset(getAssets(), "font.ttf.mp3");

        ViewGroup root = (ViewGroup) findViewById(android.R.id.content);
        setGlobalFont(root);
    }

    // 아까랑 같은 setGlobalFont
}

public class MainActivity extends BaseActivity { ... }


setContentView를 오버라이드 했습니다. 별로 좋은 방법 같지는 않지만 onCreate를 오버라이드 하는 것보다는 간단하니 이렇게 하는게 낫겠습니다.

글꼴을 불필요하게 여러번 불러오지 않도록 하기 위해 static으로 선언해서 필요할 때만 불러오도록 하였습니다. 취향에 따라 싱글턴 패턴을 적용하시거나, Application 클래스를 이용하셔도 됩니다.
추천추천 : 344 추천 목록
번호 제목
3,015
 iframe 높이 100% 맞추기
3,014
 curl 함수를 이용한 HTTP REFERER 변경
3,013
 윈도우10 시스템 파일 및 Dism 검사
3,012
 텍스트 줄바꿈, 글자자르기 CSS
3,011
 jQuery Mobile에서 유용한 코드 10가지.
3,010
 [PHP] dirname()함수와 $_SERVER 관련 상수들
3,009
 [PHP] 파일 크기, 사이즈 불러오는 함수, filesize()
3,008
 [jQuery] jQuery Quick API
3,007
 [ transition ] 링크 hover 색상 변화 속도 조절
3,006
 PHP 5.3.0 에서 사라진 함수들 대체
3,005
 어떤 파일들이 include 나 require 되었는지 확인하는 함수(get_included_files)
3,004
 PHP 날짜 형식 및 계산하기(날짜 더하고 빼기)
3,003
 jQuery Mobile에서 유용한 코드 10가지.
3,002
 값이 배열 안에 존재하는지 확인하는 in_array함수
3,001
 사용자가 웹브라우저에서 뒤로가기를 했을때 감지하는 방법
3,000
 [jQuery]버튼 활성화, 비활성화
2,999
 jQuery show() / hide() / toggle() 사용법
2,998
 jquery 여러가지 이벤트
2,997
 border-radius 속성
2,996
 네이버 오픈API 음성합성 API 사용하는 PHP 샘플코드
2,995
 UTF8 한글 자르기..
2,994
 iconv 에러 발생시 계속 처리하기 옵션
2,993
 [PHP] 현재 페이지의 도메인 , URL 정보 알아내기.
2,992
 [PHP] 막강 기능 배열..
2,991
 [CSS] - Input clear `X ` 버튼 제거 ( IE, Chrome, Firefox )
2,990
 [Mobile] - 모바일웹 Href 태그속성들
2,989
 [JqueryMobile] - 현재화면의 가로세로 사이즈 구하기
2,988
 [JqueryMobile] - 화면의 가로, 세로 사이즈 구하는 방법
2,987
 jquery로 가로 넓이(width), 세로 높이(height) 자동 조절
2,986
 iframe 높이 jquery로 자동조절하기
2,985
 jQuery 오른쪽 영역의 높이를 왼쪽 영역의 높이와 동일하게 하기
2,984
 jquery에서 테이블 짝수, 홀수 번째 TR 배경색 변경하기
2,983
 jquery에서 테이블에 마우스 오버시 해당 행의 배경색상 변경하기
2,982
 jquery 스크립트내 특정값 확인하기 (디버깅)
2,981
 jquery cookie (jquery.cookie.js)
목록
인기절정뽕짝파티
트로트재생목록
인기트로트모음
지루박디스코메들리
밤무대애창곡
전자올겐경음악
종합성인가요방
못잊을옛날노래
카바레 음악
트롯디스코팡팡
관광 메들리
트롯카페
가요감상실
추억의옛노래
스페셜가요광장
BillBoard Free
추천가요모음
경음악.전자올겐
스페셜음악여행
WOLRD POPs
K-POP\BillBoard
JP\CN
POP TOP BEST
K.R.노래방

추천가요\인기
F뮤직 인기\발라드
F뮤직 애창\트로트
트로트성인가요
인기가요
프리미엄 POP
경음악\기타
프리미엄 최신가요
프리미엄 성인가요
가요1번지(종합)
뮤직하우스
동요\연변\반주\기타
가요축제\트롯1번지
댄스\메들리\리믹스
카페\명상\경음악\기타
뮤직트로트 부산광역시부산진구 가야동 ㅣ 개인정보취급방침
Copyright (C) musictrot All rights reserved.