Tag Archives: 안드로이드

안드로이드 테마 기능 적용하기

안드로이드 10부터 시스템 수준에서 어두운 테마(Dark theme)를 지원하기 시작했고, 이제 안드로이드 앱들은 테마(밝은/어두운/시스템) 기능을 필수적으로 지원해야 할 때이다. 어두운 테마로 변경하면, 앱에서 사용하는 컴포넌트의 색을 어두운 계열로 변화 시켜 시인성을 높이고, 사용자 눈의 피로도를 줄이고, 배터리의 사용을 절약시키는 이점도 부가적으로 얻을 수 있다.

  
– 안드로이드 10 에뮬레이터의 설정 화면에서 어두운 테마 켜기

안드로이드 10에서 사용자가 설정 화면에서 어두운 테마를 선택했다면, 설치된 앱들도 어두운 색상으로 동작하길 원할 것이기에 사용자에게 일관적인 UI/UX를 경험할 수 있게 하기에 테마 기능 적용은 중요한 UX 요구사항이라고 볼 수 있게 되었다. 테마 변경을 살펴보기 전에 안드로이드 화면의 색상값에 대해서 한번 살펴보자.


– 안드로이드 화면에서의 테마 색상 요소 값

위 테마 색상은 스타일 파일(/res/styles.xml)에서 아래와 같이 확인할 수 있다.

앱에서 AppCompat 테마를 사용하는 경우에는, parent=”Theme.AppCompat.DayNight”로 선언을 해야 하고, MaterialComponents 테마를 사용하는 경우, parent=”Theme.MaterialComponents.DayNight”로 선언해야 한다.

이제 테마 기능을 추가해 보자. 테마 기능을 추가하는데 필요한 구성은 다음과 같다:

– 테마별 색상 변경을 위한 폴더 구조
– 스타일 파일(styles.xml)의 변경 요소들
– 테마 변경을 위한 코드 작성
– 테마 변경과 관련된 이슈들

1. 테마별 색상 변경을 위한 폴더 구조

1.1 테마 파일과 색상 파일

안드로이드 앱에서 기본값으로 읽는 테마와 색상 정보는 /res/values/ 폴더에 스타일 파일(styles.xml)과 색상 파일(colors.xml)에 선언한다. 어두운 테마가 읽는 테마 정보와 색상 정보는 /res/values-night/ 폴더에 같은 파일 이름으로 선언한다. 많은 경우에는 /res/values-night/ 폴더에 색상 파일만 위치시켜도 테마 기능이 잘 동작한다.

1.2 이미지 파일

만약 밝은 테마와 어두운 테마별로 보이는 이미지가 다른 경우, 밝은 테마에 보이는 이미지는 drawable-..hdpi 폴더에 어두운 테마에 보이는 이미지는 darwable-night-…hdpi 폴더에 넣어준다. mipmap을 사용하는 경우에도 drawable과 같은 패턴으로 mipmap-night-… 폴더를 사용하면 된다.

테마 변경 결과 화면을 먼저 살펴보자.

   

이 화면과 예제 소스는 https://github.com/mcsong/ThemeDemo 에서 확인할 수 있다.

2. 스타일 파일에서의 변경 요소들

스타일 파일(styles.xml)에서의 요소들에 대해서 살펴보자. 안드로이드 테마를 변경하는 경우에 색상 파일(colors.xml)만 변경해도 잘 동작할 것이다. 하지만, 시작 화면(Splash Screen) 테마의 경우에는 안드로이드 10 이후부터 어두운 테마에 어울리는 스타일을 읽어 들여야 하므로 /res/values-night/ 의 스타일 파일에 시작 화면 테마도 선언해야 한다.

시작 화면 테마는 앱이 화면(MainActivity가 주로 로딩)을 보이기 전에 보이는 화면의 구성이라고 보면 된다. 안드로이드 앱을 실행하면 런타임이 앱을 읽어 들이는 시간에 사용자가 느리다는 것을 인지하게 되고, 이것을 개선하는 방법으로 시작 화면 테마 사용을 권장하고 있다. 간단한 예제는 아래의 링크에서 확인할 수 있다.

시작 화면 테마 구성 방법 : https://android.jlelse.eu/launch-screen-in-android-the-right-way-aca7e8c31f52

예제 프로젝트에서도 시작 화면 테마를 사용하고 있으니, 예제 프로젝트의 소스를 살펴보면 시작 화면 테마를 어떻게 사용하고 있는지 알 수 있다. 이제 스타일 파일을 살펴보자.

    
    




– /res/values/styles.xml 파일

이 파일은 밝은 테마를 구성하는 스타일 파일이고, 밝은 계열의 색으로 배경을 구성한다. 그리고, android:windowLightNavigationBar의 값을 true로 설정해서 안드로이드 기기 아래의 컨트롤 버튼을 잘 보이게 한다.

    
    






– /res/values-night/styles.xml 파일

이 파일은 어두운 테마를 구성하는 스타일 파일이고, 어두운 계열의 색으로 배경을 구성한다. 그리고, android:windowLightNavigationBar의 값을 false로 설정해서 아래 컨트롤 버튼을 잘 보이게 한다.

3. 테마 변경을 위한 코드 작성

테마 변경을 위한 소스 코드는 https://github.com/mcsong/ThemeDemo을 기준으로 살펴보자.

package net.sjava.examples.theme;
import android.app.Application;

public class ThemeApp extends Application {

  @Override
  public void onCreate() {
    super.onCreate();

    ThemeUtil.applyTheme(this);
  }
}

– ThemeApp.java 소스 코드

이 클래스는 어플리케이션 소스를 상속받아서, 앱을 실행하면 가장 먼저 실행해서 예제 앱에서 변경한 테마를 읽게 한다.

package net.sjava.examples.theme;

import android.content.Context;
import android.os.Build;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatDelegate;

public class ThemeUtil {

  static final String THEME_KEY = "theme_value";

  public static void applyTheme(@NonNull Context context) {
    int option = SharedPrefsUtil.getInt(context, THEME_KEY, 0);
    applyTheme(context, option);
  }

  // 0 : light, 1 : dark, 2 : daytime
  public static void applyTheme(@NonNull Context context, int option) {
    // 테마 값 저장
    SharedPrefsUtil.putInt(context, THEME_KEY, option);

    if (option == 0) {
      AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
      return;
    }

    if (option == 1) {
      AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
      return;
    }

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
      AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
    } else {
      AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY);
    }
  }
}

– ThemeUtil.java 소스 코드

이 소스는 실제로 테마를 변경하는 소스로, 테마를 변경하면 변경된 값을 저장한다. 시스템에 따라 테마를 활성화시키는 것을 살펴보면, 안드로이드 10에서는 설정에서 어두운 테마를 활성화시킬 수 있고, 안드로이드 9와 이하 버전에서는 배터리가 절전 모드인 경우 또는 현재 시간이 저녁시간대인 경우에 어두운 테마가 활성화 된다. 그래서 안드로이드 10에서는 AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM의 값으로, 안드로이드 10 이하 버전에서는 AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY의 값으로 시스템에 적용된 테마를 앱에 적용할 수 있다.

    findViewById(R.id.theme_light_button).setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        ThemeUtil.applyTheme(v.getContext(), 0);
      }
    });

    findViewById(R.id.theme_dark_button).setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        ThemeUtil.applyTheme(v.getContext(), 1);
      }
    });

    findViewById(R.id.theme_system_default_button).setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        ThemeUtil.applyTheme(v.getContext(), 2);
      }
    });

– 테마를 변경하는 소스

예제 프로젝트의 MainActivith.java 소스를 살펴보면, 위의 코드를 확인할 수 있다. 개별 버튼을 누르면 테마가 변경되는 것을 확인할 수 있다.

4. 테마 변경과 관련된 이슈들

이제 앱에서 테마를 쉽게 변경할 수 있다. 하지만, 이것도 기존의 앱에서 업그레이드하다 보면 문제가 발생 할 수 있고, 테마 기능을 추가하면서 문제가 된 이슈에 대해서 살펴보자.

우선, 코드상에서 안드로이드 10 버전에 추가된 API를 확인하려면, compileSdkVersion 29로 컴파일 SDK 버전을 맞추면 된다. 그리고, 빌드하는 앱의 SDK 버전은 28 또는 29로 맞추면 되겠다. 혹시 29를 사용하면 문제가 있는 경우에는 targetSdkVersion을 28로 설정해서 컴파일해도 된다. 그래서 빌드 파일(build.xml)에 아래와 같이 사용하면 된다.

android {
   compileSdkVersion 29

   defaultConfig {
      applicationId "net.sjava.appstore.demo"
      minSdkVersion 15
      targetSdkVersion 28
      versionCode 1
      versionName "1.0"
   }
......
}

안드로이드 앱에서 테마를 변경하려면 액티비티(Activity)를 다시 생성해야 한다. 그래서, 프레그먼트(Fragment)에서 테마를 변경하려면 테마를 변경하고, 액티비티의 recreate() 메서드를 수동으로 호출해야 했다. 최신 androidx.appcompat:appcompat:1.1.0 를 사용하면, 액티비티의 recreate() 메서드를 호출하지 않아도 액티비티를 다시 생성해서 테마 변경을 바로 확인할 수 있게 한다.

그리고, 아래와 같이 configChange의 uiMode를 선언한 경우에는 시스템에서 어두운 테마로 변경해도 액티비티의 recreate()가 호출되지 않기 때문에 주의해야 한다.


마지막으로 외부 라이브러리를 사용한 경우 테마별 사용한 색이 달라서 이질감이 들 수 있는 경우가 있다. 사용하는 라이브러리에서 안드로이드 기본색을 사용하지 않고 자신의 색을 사용하는 경우에 이런 문제가 발생할 수 있다. 이 경우 라이브러리 소스를 가져와서 소스를 수정해서 사용하는 방법으로 해결하면 된다.

+ 예제 프로젝트 설명

+ reference

– 테마 예제: https://github.com/mcsong/ThemeDemo
– 앱 시작 시간: https://developer.android.com/topic/performance/vitals/launch-time#java
– 머티리얼 디자인 적용: https://developer.android.com/guide/topics/ui/look-and-feel?hl=ko
– 스타일 및 테마: https://developer.android.com/guide/topics/ui/look-and-feel/themes?hl=ko
– 어두운 테마: https://developer.android.com/guide/topics/ui/look-and-feel/darktheme?hl=ko

안드로이드 화면에 실행중인 앱 확인하는 방법

안드로이드 5(롤리팝) 이후부터는 안드로이드 기기에 실행중인 앱을 알 수 없게 되었습니다. 그래서, 안드로이드 5 이후 버전에서는 기기에 저장하고 있는 통계 데이터를 기반으로 완전히 정확하지는 않지만, 대략적으로 정확한 정보를 가져올 수 있습니다. UsageStatsManager를 사용해서 현재 안드로이드 기기의 화면에 실행중인 앱을 검색하는 방법을 살펴보자.

아래는 UsageStatsManager를 사용해서 안드로이드 기기에 저장되어 있는 이벤트 데이터를 검색하고, 이벤트가 포그라운드(Event.MOVE_TO_FOREGROUND 또는 Event.ACTIVITY_RESUMED)인 것을 확인해서 마지막 포그라운드 이벤트에 해당하는 패키지 이름을 가져온다. 이 정보는 대체로 정확하고, 아래 코드로 가져온 패키지가 현재 화면에서 실행중인 것을 확인 할 수 있다.

1. 앱의 AndroidManifest.xml에 아래의 권한을 추가


2. 안드로이드 기기에서 실행중인 앱 가져오기

public static String getTopPackageName(@NonNull Context context) {
  UsageStatsManager usageStatsManager = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);

  long lastRunAppTimeStamp = 0L;

  final long INTERVAL = 1000 * 60 * 5;
  final long end = System.currentTimeMillis();
  // 1 minute ago
  final long begin = end - INTERVAL;

  LongSparseArray packageNameMap = new LongSparseArray<>();
  final UsageEvents usageEvents = usageStatsManager.queryEvents(begin, end);
  while (usageEvents.hasNextEvent()) {
    UsageEvents.Event event = new UsageEvents.Event();
    usageEvents.getNextEvent(event);

    if(isForeGroundEvent(event)) {
      packageNameMap.put(event.getTimeStamp(), event.getPackageName());
      if(event.getTimeStamp() > lastRunAppTimeStamp) {
        lastRunAppTimeStamp = event.getTimeStamp();
      }
    }
  }

  return packageNameMap.get(lastRunAppTimeStamp, "");
}

3. 이벤트가 포그라운드 이벤트인지 확인

private static boolean isForeGroundEvent(UsageEvents.Event event) {
  if(event == null) {
    return false;
  }

  if(BuildConfig.VERSION_CODE >= 29) {
    return event.getEventType() == UsageEvents.Event.ACTIVITY_RESUMED;
  }

  return event.getEventType() == UsageEvents.Event.MOVE_TO_FOREGROUND;
}

위 코드를 사용해서 완전히 정확하지는 않지만, 대체로 정확하게 안드로이드 화면에서 실행중인 앱을 알 수 있다.

VM, 원격 PC 연결 클라이언트 개발에 참고할 만한 프로젝트들

이 글의 내용은, 가상화 프로젝트를 하면서 윈도, 안드로이드 앱을 개발하면서 사용하거나 살펴본 오픈소스 및 바이너리에 대한 정리이다. VM(가상화된 PC)이나 원격 PC에 접근하는데 많이 알려진 RDP(Remote Desktop Protocol), SPICE(Simple Protocol for Independent Computing Environments), 그리고 VNC(Virtual Network Computing) 프로토콜을 주로 사용한다. 이 프로토콜은 원격 PC 화면을 스트리밍하기 위해서 개발되었다.

* RDP
RDP의 경우에는 마이크로소프트에서 개발한 프로토콜이고, 거의 모든 윈도가 이 프로토콜을 구현한 클라이언트인 mstsc.exe가 번들로 배포된다. 그리고, 윈도 7에서 성능을 향상한 RemoteFX와 같은 기능을 사용하기 위해서는 별도로 업데이트할 수 있다.
– 프로토콜 스펙 : https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/5073f4ed-1e93-45e1-b039-6e30c385867c

* SPICE 프로토콜
SPICE 프로토콜의 경우에는 오픈소스 프로젝트이다. 이 프로젝트는 레드햇(RedHat, 2007년에 Qumranet 회사 인수)에서 소스를 오픈 했다.
– SPICE 프로토콜 스펙 : https://www.spice-space.org/static/docs/spice_protocol.pdf

* VNC 프로토콜
VNC 프로토콜의 경우에는 성능 문제가 있어서 제외했다.

레드햇이 가상화 솔루션을 오픈소스로 열어서 oVirt(https://ovirt.org/)라는 프로젝트가 진행중이고, 오픈소스 가상화 솔루션 중에서는 가장 발전한 프로젝트이다. 그리고, 레드햇에서 제품으로 판매하는 가상화 솔루션도 oVirt를 기반하고 있다.

이제 이 프로토콜을 기반으로 개발하는 데 도움이 되는 프로젝트를 살펴보자.

* HTML 클라이언트
웹 소켓을 사용해서 원격 PC의 화면을 스트리밍한다. 아래 프로젝트를 기반으로 웹 앱을 개발할 수 있다.

– Guacamole : RDP와 VNC를 지원하는 아파치 프로젝트로, https://guacamole.apache.org/ 에서 확인할 수 있다.
– SpiceHtml5 : SPICE를 스트리밍하는 자바스크립트 프로젝트로, https://github.com/freedesktop/spice-html5 에서 확인할 수 있다.
– Myrtille : .NET 기반의 오픈소스 프로젝트로, https://cedrozor.github.io/myrtille 에서 확인할 수 있다.

* 윈도
윈도에서 RDP와 SPICE를 지원하는 프로젝트아래의 프로젝트를 사용해서 윈도에서 RDP와 SPICE를 지원할 수 있다.
– mstsc : 윈도 내장 RDP 클라이언트이다. 이 툴은 mstsc.exe 실행 옵션이나 rdp 파일을 사용하면 된다.
– virt viewer : 윈도에서 SPICE 서버에 연결하도록 지원한다. 이 툴은 https://releases.pagure.org/virt-viewer/ 에서 다운로드할 수 있고, https://pagure.io/virt-viewer/blob/master/f/NEWS 에서 Changelogs를 확인할 수 있다.
– FreeRDP : RDP 프로토콜을 지원하는 FreeRDP 프로젝트로, 소스는 https://github.com/FreeRDP/FreeRDP/tree/master/client/Windows 에서 확인할 수 있다.

* 맥
아래 프로젝트로 맥 클라이언트를 개발할 수 있다.
– FreeRDP : RDP 프로토콜을 지원하는 FreeRDP 프로젝트로, 소스는 https://github.com/FreeRDP/FreeRDP/tree/master/client/Mac 에서 확인할 수 있다.

* 안드로이드
안드로이드에서 RDP와 SPICE를 지원하는데 사용할 수 있는 프로젝트들이다.

– freerdp : RDP 기반의 오픈소스 프로젝트로, https://github.com/FreeRDP/FreeRDP/tree/master/client/Android 에서 확인할 수 있다.
– flexVDI : flexVDI에서 오픈한 SPICE 프로젝트로, https://github.com/flexVDI/launcher-mobile 에서 확인할 수 있다.

– VirtualDesktop : SPICE 프로토콜을 지원하는 안드로이드 앱 프로젝트, https://github.com/pisceslj/VirtualDesktop 에서 확인할 수 있다.

– oVirt 매니저 앱 : oVirt 서버에 접근해서 관리할 수 있는 기능을 제공하는 안드로이드 앱으로, https://github.com/oVirt/moVirt 에서 확인할 수 있다.

* iOS
iOS 에서 RDP와 SPICE를 지원하기 위해서 사용할 수 있는 프로젝트들이다.
– freerdp : RDP 기반의 오픈 소스 프로젝트로, https://github.com/FreeRDP/FreeRDP/tree/master/client/iOS 에서 확인할 수 있다.
– flexVDI : flexVDI에서 오픈한 SPICE iOS 오픈소스 앱으로, https://github.com/flexVDI/launcher-mobile 에서 확인할 수 있다.

개인적으로 RDP와 SPICE 위주로 윈도와 안드로이드 앱을 개발해 본 경험으로, 원격 프로토콜을 성능 관점으로 보면 RDP > SPICE > VNC 순이다. SPICE의 경우에는 꽤 괜찮은 성능을 보여주지만, 그에 반해서 리소스(클라이언트에서 서버에 다수의 소켓을 열어서 성능을 개선)를 많이 사용한다. 결론으로 원격 프로토콜은 RDP 쵝오 !!

* Reference
https://en.wikipedia.org/wiki/Simple_Protocol_for_Independent_Computing_Environments

안드로이드 외부 라이브러리 뷰 스타일 변경하기

안드로이드는 뷰의 크기, 색 등의 각종 스타일과 관련된 설정은 외부 파일(dimens.xml, colors.xml 등)에 저장해서, 한번에 많은 뷰의 스타일을 변경할 수 있도록 한다. 이 방법을 사용해서 테마나 스타일을 쉽게 변경할 수 있게 한다.

만약 앱과 라이브러리에서 동일한 속성 값을 사용한다면, 앱에서 정의한 속성을 사용한다. 그래서, 이 방법을 사용해서 외부 라이브러리 뷰의 스타일을 변경하는 방법을 살펴보겠다. 대부분의 라이브러리는 뷰의 속성을 외부 파일에 정의해서 릴리즈를 하지만, 속성값을 하드코딩한 경우에는 스타일 변경이 쉽지 않다.

라이브러리의 스타일을 변경하는 예제로, AboutLibraries(https://github.com/mikepenz/AboutLibraries)를 사용해 보자. 이 라이브러리가 사용하는 각종 스타일 값들을 살펴보고, 레이아웃에서 정의한 값들을 사용하는 부분과 이 정의 값을 변경해서 UI를 변경하는 예제를 살펴보자.

1. 스타일(styles.xml)

이 파일은 https://github.com/mikepenz/AboutLibraries/blob/develop/library/src/main/res/values/styles.xml 에서 확인 할 수 있다. 이 파일에서 앱이나 라이브러리의 스타일을 확인 할 수 있다. 아래는 스타일 파일에서 기본 스타일로 정의한 부분이다. 다른 앱들과 거의 비슷하다.

   


그러나, “AboutLibraries specific values” 주석아래를 살펴보면, item name=”about_libraries_window_background” 와 같이 커스텀 값이라는 것을 알 수 있다. 커스텀 값은 속성 파일(attrs.xml)에 정의해서 사용 할 수 있다. 속성 파일을 살펴보자.

2. 속성(attr.xml)

이 파일에서는 https://github.com/mikepenz/AboutLibraries/blob/develop/library/src/main/res/values/attrs.xml 에서 확인 할 수 있다. 이 파일은 안드로이드 앱이나 라이브러리에서 커스텀으로 사용하는 요소나 속성을 정의하는 용도이다. 이 내용은 XML 스키마를 정의해 봤다면 쉽게 이해가 갈 것이다. 하지만, 안드로이드에서 읽어들이는 값들이 정의되어 있기에, 이름과 포맷만 기술하게 되어 있긴 하다. 아래는 라이브러리에서 커스텀으로 정의한 속성의 일부이다.

 

 	
 	
 	
 	
 	
 	
 	
 	
 	
 	

위 속성에서 “about_libraries_window_background”는 색이고 참조(reference)라는 것을 알 수 있다. 다음으로 색을 살펴보자.

3. 색(colors.xml)

이 파일은 https://github.com/mikepenz/AboutLibraries/blob/develop/library/src/main/res/values/colors.xml 에서 확인 할 수 있다. 아래는 라이브러리가 사용하려고 정의한 색들 중에 일부이다.

 

#ECECEC
#FAFAFA
#212121
#727272
#212121
#AAA
#DADADA

색의 이름이 속성 파일에 정의한 이름으로 요소는 color로 시작하는 것을 알 수 있다.

4. 크기 정의(dimens.xml)

이 파일은 https://github.com/mikepenz/AboutLibraries/blob/develop/library/src/main/res/values/dimen.xml 에서 확인 할 수 있다. 이 파일은 안드로이드에서 뷰의 마진, 여백, 폰트 크기 등의 값을 정의한다. 이 라이브러리의 크기 값들은 아래와 같다.

 


12dp
72dp
20sp
14sp

16dp
16dp

이제 위 속성을 변경하지 않은 화면은 아래와 같다.

다음으로 속성을 변경하면, 어떤 UI가 변경되는지 살펴보기 위해서 간단하게 레이아웃 파일을 살펴보자.

5. 레이아웃 확인

이제 레이아웃 파일에서 개별 뷰의 스타일이 위에서 사용하는 속성을 사용하는지, 그리고 이 속성을 변경해서 뷰를 수정해 보자.

– 목록 컨테이너
목록 컨테이너는 https://github.com/mikepenz/AboutLibraries/blob/develop/library/src/main/res/layout/fragment_opensource.xml 에 정의되어 있다. 목록을 보여주는 컨테이너로 리사이클러뷰(RecyclerView)를 사용하고, 패딩 값으로 dimens.xml 파일에 정의한 속성 값을 사용하는 것을 알 수 있다. 이 속성 값을 변경해서 카드 레이아웃이 조금 좁거나 넓게 보이게 할 수 있다.

 

– 헤더 부분
목록의 헤더 부분(앱 아이콘, 이름, 버전 정보 등)은 https://github.com/mikepenz/AboutLibraries/blob/develop/library/src/main/res/layout/listheader_opensource.xml 에 정의되어 있다. 아래는 이 파일에서 앱 아이콘, 이름, 버전을 보여주는 일부 뷰이다. 여기에서도 이미지 크기는 dimens.xml 파일에 정의되어 있고, 앱 이름과 버전도 정의한 것을 알 수 있다.

 



– 항목(Item) 부분
목록의 항목은 https://github.com/mikepenz/AboutLibraries/blob/develop/library/src/main/res/layout/listitem_opensource.xml 에 정의되어 있다. 아래는 라이브러리 이름과 개발자 이름을 보여주는 부분이다. 여기도 목록의 헤더와 같이 textSize를 dimen.xml 에서 정의한 값으로 사용한다.

 


6, UI 변경 예제

이제 앱에서 텍스트 크기를 변경해서, 이 라이브러리 뷰가 사용하는 텍스트뷰의 스타일을 변경해 보자. 개발중인 앱의 앱 모듈에서 크기 정의 파일(/app/src/main/res/values/dimens.xml)을 열어서 아래의 값을 추가해 보자.

 
16sp
16sp

위 속성을 추가한 뒤의 결과는 아래와 같다.

다음으로 위에서 정의한 속성 파일의 사용자 정의 색을 변경해 보자. 개발중인 앱의 앱 모듈에서 크기 정의 파일(/app/src/main/res/values/color.xml)을 열어서 아래의 값을 추가해 보자.

 
#0368A1
#FBBB00

위에서 변경한 색이 어떻게 적용되는지 확인하려면, 라이브러리 코드를 보면 쉽게 확인할 수 있다. 예로, 헤더의 앱 이름 색을 변경하는 코드는  https://github.com/mikepenz/AboutLibraries/blob/develop/library/src/main/java/com/mikepenz/aboutlibraries/ui/item/HeaderItem.java 에서 알 수 있다. 이 클래스에서 아래의 코드로 앱 이름 텍스트뷰의 텍스트 색을 변경하는 것을 알 수 있다.

aboutAppName = (TextView) headerView.findViewById(R.id.aboutName);
aboutAppName.setTextColor(UIUtils.getThemeColorFromAttrOrRes(headerView.getContext(), R.attr.about_libraries_title_description, R.color.about_libraries_title_description));

뷰를 가지는 대부분의 안드로이드 라이브러리는 위와 거의 비슷한 구조이다. 그래서 외부 라이브러리를 개발하는 앱의 스타일에 맞춰서 사용하려면, 이 글의 과정으로 쉽게 스타일을 변경할 수 있다.

액션바(ActionBar) 제목 및 부제목 스타일 변경

이제 아주 많은 앱들이 v7의 툴바(Toolbar)를 사용해서 액션바(ActionBar)로 사용할 것이다. 그리고, 액티비티(Activity)에서 보여주는 정보에 따라서 액티비티의 제목(Title)과 부제목(SubTitle)을 사용할 수도 있다.

프로젝트를 만들고, 액션바에 제목과 부제목을 추가해보자.

위 화면에서 보듯이, 글자색이 보색이 아니라서 가독성이 떨어진다. 그리고, 글자의 크기로 인해서 액션바의 제목을 보여주는 영역이 꽉 찬 느낌을 준다.

그래서, 가독성을 좋게하고 글자의 크기나 색을 변경할 수 있는 방법을 살펴보자. 여기에서는 툴바를 사용해서 액션바의 제목과 부제목의 스타일을 변경하는 방법을 살펴보자.

1. 액션바의 제목과 부제목에 해당하는 스타일을 만든다.
/res/values/styles.xml 파일을 열어서 아래의 스타일을 추가한다.

    


 


이 코드는 2개의 스타일을 정의한다. 제목 텍스트 스타일로 ToolbarTitleText에서 18sp의 크기와 md_grey_100의 색을 사용한다. 그리고, 부제목으로 ToolbarSubTitleText에서 볼 수 있듯이 14sp의 크기와 md_grey_200의 색을 사용한다.

2. Toolbar에서 제목 텍스트와 부제목 텍스트 스타일 지정
이제 /res/layout/xxx.xml 파일을 열어서 툴바의 스타일을 아래와 같이 지정한다.

    
    
        
        

이제 위에서 정의한 스타일이 잘 적용되는지 확인해보면 아래와 같은 결과를 확인 할 수 있다.