그냥 간단하게 텍스트뷰를 누르면 웹뷰에 연결되어서 걸려있는 url로 넘어가는 기능을 하나 넣어보고 싶었다.

 

우선 간단하게 사용법을 알아보자.

 

XML파일코드

<WebView
    android:id="@+id/webView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:visibility="gone"
    />

 

위젯에서 웹뷰를 가져와서 해당 레이아웃을 가득차게 만들어주고 가려준다.

val webView = findViewById<WebView>(R.id.webView)

 

액티비티 파일에서 웹뷰 객체를 만든다.

// WebView 설정
val webSettings: WebSettings = webView.settings
webSettings.javaScriptEnabled = true // JavaScript 활성화
// WebViewClient를 설정하여 새 창이 아니라 현재 WebView에서 링크가 열리도록 함
webView.webViewClient = WebViewClient()

 

웹뷰를 사용하기 위해선 WebSettings, webViewClient 클래스를 import해야한다.

blogTextView.setOnClickListener {
    val url = "https://happenedtodeveloper.tistory.com/" // 원하는 링크 주소로 변경
    webView.visibility = WebView.VISIBLE
    webView.loadUrl(url)
}

githubTextView.setOnClickListener {
    val url = "https://github.com/Bladepark" // 원하는 링크 주소로 변경
    webView.visibility = WebView.VISIBLE
    webView.loadUrl(url)
}

 

TextView가 클릭되면 gone에서 visible로 바꿔주고 url을 로드해서 웹뷰가 동작하도록 만들어준다.

 

해봤는데 이런 net::ERR_CACHE_MISS 에러가 뜬다면 현재 프로젝트에 인터넷을 쓸 수 있는 권한이 설정되어있지 않은거다.

프로젝트의 manifests 파일에 가서 <uses_permission android:name="android.permission.INTERNET"/> 코드로 인터넷 권한을 설정해주면 된다.

'Android Studio' 카테고리의 다른 글

Android AddTextChangedListener & TextWatcher  (1) 2023.12.18
Android Fragment Lifecycle  (1) 2023.12.18
Android Studio 폰트 설정 및 적용 방법  (0) 2023.12.13
Android Studio Activity Lifecycle  (0) 2023.12.13
Android Studio UI - Layout  (0) 2023.12.12

안드로이드에서 기본 제공하는 폰트들도 괜찮지만 좀 더 예쁜 폰트들을 쓰고 싶을 때가 있다.

기본적인 폰트 변경 방법과 폰트 다운로드 과정 및 적용 과정을 소개한다.

 

우선 무료로 사용가능한 폰트들을 다운 받을 수 있는 사이트를 소개한다.

 

https://noonnu.cc/

 

눈누

상업용 무료한글폰트 사이트

noonnu.cc

 

간단히 폰트(Font)에 대해서 알아보자면, 폰트는 컴퓨터로 표현되는 디지털 글꼴이며 쉽게 이미지와 마찬가지로 글자를 이루는 데이터의 집합이라고 생각하면 된다. 

 

글꼴의 표현방식으로는 비트맵 글꼴과 벡터 글꼴이 있는데 너무 자세히 다루진 않고 그냥 간단히만 알자.

비트맵(bitmap) 글꼴은 픽셀(Pixel)이 모여 전체 글꼴을 구성하는 방식이고 벡터(Vector) 글꼴은 점과 점 사이의 곡선으로 이미지를 구성하는 방식이다.

 

벡터 글꼴이 크기를 변경해도 깨지지 않는 장점이 있어 오늘날 많이 쓰인다고 한다.

폰트를 다운 받을 때 보면 OTF(오픈타입)와 TTF(트루타입) 중 선택해서 다운 받으라고 하는 걸 보게 될 것이다.

OTF TTF 둘 다 모두 벡터글꼴의 저장 형식을 나타내는 포맷이다. 둘의 가장 큰 차이는 곡선을 구현하는 방식의 차이인데 현재로서는 크게 중요하지 않기 때문에 다음에 기회가 되면 포스팅하겠다.

 

쉽게 OTF는 고해상도 출력 작업이 필요한 사용자(디자이너, 그래픽전문가 등)들이 사용하는 버전이라 생각하면 되고

우리는 일반 문서 작업에 적합한 TTF 다운 받으면 된다. 

 

각설하고 우선 안드로이드 스튜디오의 res 패키지 밑에 font 디렉토리를 하나 생성하자.

 

이후 원하는 폰트의 TTF를 다운받자.

폰트사이트에 들어가 원하는 폰트를 클릭하면 설치 페이지로 이동이라는 버튼이 있다. 누르고 페이지를 찾아보면 타입폰트가 나누어져 있다.우리는 true type font 인 ttf를 다운받자.

 다운로드 받고 해당.ttf 파일을 복사하여 font 디렉토리에 붙여넣기 해준다.

 

나의 경우 string들을 한꺼번에 관리해주기 위해 values에 styles.xml을 만들어서 fontfamily에 폰트를 먹였다.

결과는??

이쁘게 폰트가 잘 설정 되었다.

'Android Studio' 카테고리의 다른 글

Android Fragment Lifecycle  (1) 2023.12.18
Android Studio WebView 사용법 및 ERR_CACHE_MISS 해결법  (0) 2023.12.14
Android Studio Activity Lifecycle  (0) 2023.12.13
Android Studio UI - Layout  (0) 2023.12.12
Android Studio UI - View  (0) 2023.12.11

Activity

안드로이드에서 Activity는 화면에 표시되는 UI 구성을 위해 가장 기본이 되는 요소이다. UI 구성을 위한 틀의 개념!

안드로이드 앱은 지정된 Activity를 통해 사용자에게 UI를 표시하게 된다.

 

맨 처음 그냥 아무 수정없이 프로젝트를 생성하면 보게 되는 것이 MainActivity인데 이 Activity가 바로 앱이 실행되고 최초로 보여지는 Activity이다. (꼭 이름이 MainActivity이어야 하는건 아니다.)

 

 

위와 같이 manifest파일을 보면 현재 앱이 가지고 있는 액티비티를 모두 볼 수 있고 그중 카테고리에 LAUNCHER라는 단어를 통해 실행 되었을 때 가장 먼저 실행되는 액티비티 또한 알 수 있다.

 

Activity의 생명주기 (Activity Lifecycle)

액티비티는 사람과 같이 태어나고 죽기까지의 생명주기가 있다. 사실 사람처럼은 아니고 시작과 종료 사이에 특정 행위를 수행하기 위한 상태가 있다고 생각하면 된다.

 

예를 들자면, 게임을 하다가 애인에게 영상통화가 왔고 나는 잠시 그 영상통화를 받고 다시 게임에 왔는데 게임이 진행되던 내용이 모두 사라지고 처음부터 다시 시작한다면 아주 골 때릴 것이다.

 

혹은 어떤 앱을 설치해서 설문조사를 하는데 설문조사 내용에 다 답변하여 제출 하기 전까지는 핸드폰이 다른 어떤 행동을 하는걸 허락하지 않는다면 그것도 정말 곤욕스러울 것이다. 

 

위와 같이 잠시 앱 사용을 중단하고 다른 앱을 실행시키는 일은 정말 많다. 그래서 액티비티에 각 상황마다의 상태를 정의하고 그 상태에서의 특정행위를 실행할 수 있도록 만들어주는 것이 생명주기의 필요성 중 하나이다.

 

이제 액티비티 생명주기의 콜백 메소드(상태에 따라 불려지는 함수)를 보면서 이해해보자.

위 다이어그램은  Activity Lifecycle 을 시각적으로 나타낸 것이다.

핵심 콜백 메소드로 onCreat(), onStart(), onResume(), onPause(), onStop(), onDestroy() 가  있다.

(콜백 함수의 정의로 두 가지가 있는데 하나는 다른 함수의 인자로써 이용되는 함수이면 콜백함수라 불리우고 나머지 하나는 어떤 이벤트에 의해 호출되어지는 함수도 콜백함수라 불리어진다.여기서는 후자의 속하는 것 같다.)

 

각각의 콜백 메소드가 언제 호출되고 호출이 되었을 때 어떤 동작들이 주로 구현되는지 예를 통해 살펴보자.

그 전에 foreground(포그라운드) 와 background(백그라운드) 를 알아야 한다. 포그라운드는 사용자가 현재 액티비티에 포커스하고 있을 때를 말한다. 즉, onResume()에서 onPause()호출사이를 말한다. 백그라운드는 포그라운드의 반대로 포커싱되고 있지 않은 상태를 말한다. 다만, 말그대로 백그라운드에서 제한된 기능의 실행은 되고있는 상태이다.

더보기

onCreate()

액티비티가 생성될 때 호출되며 액티비티 전체 수명 주기 동안 딱 한 번만 초기화 및 시작 로직을 실행한다.

주로 UI에 필요한 레이아웃 그리고 데이터들을 정의하고 설정하는 등의 동작을 한다.

setContentView를 통해 XML 레이아웃 파일을 넘겨줌으로써 초기화면을 띄운다.

또한, onCreated() 는 파라미터로 savedInstanceState를 받는데 그 안에 있는 액티비티의 이전 상태가 저장된 bundle객체를 통해 이전 상태를 복원하여 화면에 표시할 수 있게끔 하는 기능도 수행한다.(첫화면은 null을 담고 있다.)

onCreate() 호출 이후 시스템은 액티비티가 STARTED 상태에 진입함에 따라 onStart()와 onResume()을 연달아 호출한다.

더보기

onStart()

onStart() 메소드가 호출되면 액티비티가 실제로 사용자에게 보여지고 포그라운드 작업으로써 사용자와의 상호작용을 할 수 있도록 준비하는 동작이 실행된다. onStart() 메소드는 onCreate()와 onResume() 단계의 사이에 호출되며 굉장히 빠른 속도로 실행되고 액티비티가 RESUMED상태에 들어감과 동시에 시스템이 onResume()메소드를 호출하게 된다.

더보기

onResume()

액티비티가 RESUMED 상태에 진입하며 포그라운드에 액티비티가 표시되고 사용자와 앱이 상호작용 가능한 상태가 된다.

지금부터 어떤 방해 이벤트나 인터럽트(전화가 오거나 화면이 꺼지거나 대화상자 표시 등)가 발생하여 포커싱을 놓치지 않는 이상 앱은 RESUMED 상태에 머무른다.

더보기

onPause()

RESUMED상태에서 방해 이벤트나 인터럽트 발생으로 액티비티가 PAUSED 상태에 들어가게 되면 시스템은 onPause() 메소드를 호출한다. 이 때는 해당 액티비티가 포커싱되지 않아 포그라운드에 있지 않게 되므로 다시 RESUMED 상태에 들어가기 전까지 계속 실행되어서는 안되지만 언젠가 다시 시작할 수 있는 작업을 잠시 일시중지하는 작업을 수행한다.

 

액티비티가 다시 시작되면  메모리 상 남아있던 액티비티 인스턴스를 다시 불러와 onResume()메소드를 호출한다. 액티비티가 완전히 화면에서 보이지 않게 되면 onStop()메소드를 호출하고 액티비티는 STOPPED 상태에 진입한다.

 

키포인트 두 가지 중 첫번째는 onPause()메소드를 사용하여 배터리 수명에 영향을 미칠 수 있는 모든 시스템 리소스, 하드웨어 센서 등을 할당 해제하면 자원을 효율적으로 사용할 수 있다는 것.

두번째는 onPause()  아주 잠깐 실행되기 때문에 무언갈 저장하는 작업을 실행하기엔 시간이 부족할 수 있다는 것. 따라서 onPause() 내에서는 사용자 데이터 저장, 네트워크 호출, DB 트랜잭션 등을 실행해서는 안 된다. 이렇게 부하가 큰 작업들은 onStop() 에서 수행해야 한다.

더보기

onStop()

Activity가 종료되거나, 다른 Activity가 화면을 가릴 졌을 경우 등의 상황에 호출된다.

액티비티가 STOPPED 상태에선 해당 Activity Object가 메모리에만 남아있게 된다. 여기서는 자동으로 onSaveInstanceState()가 실행되어, 데이터를 Key-value 형태로 값을 저장하여 onCreate()에서 다시 복원을 하여 데이터만 있다면 화면을 다시 불러올 수 있다. 시스템이 더 우선순위가 높은 프로세스를 위해 메모리를 확보해야하는 경우 이 액티비티를 메모리 상에서 죽이게 되는데 메모리 상에서 죽어도 Bundle의 VIew객체 상태를 그대로 저장해둬서 상태 복원이 가능하다.

onStop() 메소드안에서는 필요하지 않은 리소스를 해제하거나 조정해야하며 CPU를 비교적 많이 소모하는 작업을 종료해야 한다. 예를 들어 GPS의 위치 인식 정확도를 낮추기, DB에 정보를 저장하기가 있다. 

만약 사용자가 다시 액티비티로 돌아오게 되면, 'STOPPED' 상태에서 다시 시작되어 onRestart()  onStart()  onResume() 이 연달아 호출되며 'RESUMED' 상태로 변화하여 다시 포그라운드 액티비티로써의 태스크를 시작하며 사용자와 상호작용을 시작한다.

사용자에 의해, 혹은 시스템에 의해 액티비티가 완전히 실행 종료될때면 시스템은 onDestroy() 콜백 메소드를 호출하게 된다.

더보기

onDestroy()

액티비티가 완전히 소멸되기 전에 이 콜백 메소드가 호출된다. 아래와 같은 경우 액티비티가 완전히 소멸된다.

  1. finish() 가 호출되거나 사용자가 앱을 종료하여 액티비티가 종료되는 경우
  2. 화면 구성이 변경되어 (기기 회전 등) 일시적으로 액티비티를 소멸시키는 경우

액티비티가 종료되는 경우 onDestroy()  마지막 라이프사이클 콜백 메소드가 된다. 만약 위의 2번 사유로 인해 호출된거라면, 시스템이 즉시 새롭게 변경된 액티비티 인스턴스를 생성하여 onCreate() 를 호출한다.

만약 onDestroy() 가 호출되기 까지 해제되지 않은 리소스가 있다면, 모두 여기서 해제해줘야 한다. Memory Leak (메모리 누수) 의 위험이 있다.

이후, 액티비티는 메모리 상 완전히 소멸되게 된다.

레이아웃이란?

ViewGroup의 파생 클래스로서, 포함 된 View를 정렬하는 기능

 

레이아웃의 종류

01. Linear Layout (*Orientation -> vertical or horizontal)

  • 컨테이너에 포함 된 뷰들을 수평 또는 수직으로 일렬 배치하는 레이아웃
  • 자식 뷰를 수평,수직으로 일렬 배치하는 레이아웃으로, 가장 단순하고 직관적이며 사용빈도가 높다.
  • LinearLayout의 자식(Children)으로 배치되는 View위젯들은 오직 한 방향 (가로 또는세로)으로만 배치
  • 위젯의 크기(높이 또는 너비)와 관계없이 한 줄로만 배열
  • 아래 그림과 같이 가로 방향으로 배치 될 때는 가로로 한 줄(onlyonerow)
  • 세로 방향으로 배치될 때는 세로로 한 줄(onlyonecolumn)로 표시
  • LinearLayout의 자식들은 중첩(overrap)되지 않고,지정한 방향으로 쌓이는(stacked)형태로 표시
  • LinearLayout은 자식(Children)들이 배치 될 때,전체 영역 대비 비율의개념으로지정할수있는Weight(가중치)를 설정
  • 예) 전체 크기를 10으로 본다면, 첫 번째 View위젯은 3, 두 번째View위젯은7의영역을차지하도록 만듦

02. Relative Layout

  • 뷰를 서로 간의 위치 관계나 컨테이너와의 위치 관계를 지정하여 배치하는 레이아웃
  • RelativeLayout은 자식(Children)View위젯들이 서로 간의 상대적 배치 관계에 따라 화면에 표시 될 위치가 결정되도록 만들어주는Layout클래스
  • 예)"A를 화면에 표시하고 B는A의 오른쪽에 표시”,"C를 첫번째 자식으로 두고 D가 C아래에 위치하도록 배치”
  • View위젯들을 포함하는 Relative Layout(View위젯 입장에서는 부모(Parent))자체가 상대적 위치의 기준점으로 사용될수도있습니다.
  • 만약 RelativeLayout의 자식(Children)들에 "상대적인"배치 기준을 지정하지 않는다면, RelativeLayout내부에서 중첩되어 표시된다

03. Table Layout

  • 표 형식으로 차일드를 배치하는 레이아웃
  • 자식(Children) View위젯들을 테이블(행과 열로 구성)로 나누어 표시하는 Layout클래스

  • stretchColumns : 늘릴 열을 지정(인텍스는 0부터 시작 됨)

TableRow

  • 정해진 규칙에 따라 크기가 결정되므로, layout_width/height를 지정할 필요가 없다.

04. Frame Layout

  • 컨테이너에 포함된 뷰들을 전부 좌상단에 배치하는 레이아웃
  • 하나의 자식 View위젯만 표시 할 때 사용하는 Layout클래스
  • FrameLayout에 여러 View위젯을 자식으로 추가하면 겹쳐진 형태로 표시되며,가장 최근에 추가된 View위젯이 가장 상위(ontop)에 표시

  • 모든 자식 View는 좌상단에 배치되며,여러 개의 자식View를 포함하는 경우나 열된순서대로 겹쳐져서 표시 됨

05. Constraint Layout

  • 제약 조건을 사용해 화면을 구성하는 방법
  • 복잡한 레이아웃을 단순한 계층구조를 이용해 표현 할 수 있는 ViewGroup
  • 형제 View들과의 관계를 정의해서 레이아웃을 구성한다는 점은 RelativeLayout과 비슷하지만 보다 유연하고 다양한 기능을 제공함
  • RelativeLayout에선 불가능했던 자식 뷰간의 상호 관계 정의 가능
  • ex)두개의 View를 위아래로 붙여서 컨테이너 중앙에 배치하기
  • LinearLayout을 써야만 했던 뷰비율 조절도 간단히 가능
  • 뷰계층을 간단하게 할 수 있어 유지보수도 좋고 성능도 좋고!

'Android Studio' 카테고리의 다른 글

Android Studio 폰트 설정 및 적용 방법  (0) 2023.12.13
Android Studio Activity Lifecycle  (0) 2023.12.13
Android Studio UI - View  (0) 2023.12.11
Android Studio Bookmarks 활용  (0) 2023.12.11
안드로이드가 뭐야?  (0) 2023.12.11

What is View?

  • View클래스는 모든 UI 컴포넌트들의 부모 클래스
  • View클래스의 속성은 모든 UI컴포넌트들에서 공통적으로 사용 할 수 있다.

 

What is Widget?

  • View의 서브 클래스 중에서 화면에 보이는 것들을 말함
  • 대표적인 위젯은 TextView, EditText, Button등이 있습니다.

 

실제 자주 사용하는 위젯 속성

 

TextView

id, layout_width, layout_height, background etc

text : 출력할 문자열 지정

textSize : 폰트 크기

textStyle : 텍스트 스타일(normal, bold, italic)

typeface : 텍스트 폰트(normal, sans, serif, monspace)

textColor : 문자열 색상

singleLine : 속성값 true이면 텍스트가 위젯의 폭보다 길 때 강제로 한 줄에 출력

 

EditText

입력이 가능한 Text 창

  • TextView의 모든 속성 상속(EditText는TextView의 서브클래스임)
  • inputType: 입력 시 허용되는 키보드 타입 설정 및 키보드 행위를 설정 
    • 키보드 타입 설정 값
      • “text”:일반적인 텍스트 키보드
      • “phone”:전화번호 입력 키보드
      • “textEmailAddress”:@문자를 가진 텍스트 키보드
      키보드 행위 설정 값
      • “textCapWords” : 문장의 시작을 대문자로 변환
      • “textAutoCorrect” : 입력된 단어와 유사한 단어를 제시하고 제시된 단어 선택 시,입력된 단어를 대치
      • “textMultiLine”:여러 줄을 입력 받을 수 있음

Button

  • Button클래스는 TextView의 서브클래스이므로, TextView의 모든 속성을 사용 할 수 있다.
    • singleLine: 텍스트가 위젯의 폭보다 길 때 강제로 한 줄에 출력
  • 버튼 내에 텍스트,아이콘을 표시 할 수 있음
    • 버튼 전체를 이미지로 그리기 위해서는 ImageButton사용

 

ImageButton

대부분의 버튼은 ImageView를 사용

1. ImageView 속성에 Clickable 옵션을 true로 설정

2. 이미지는 normal(아무 상태가 아닐 때) , pressed(클릭되었을 때), disable(클릭불가할 때) 3가지 준비

3. 해상도 처리를 위해 dpi별 (mdpi, hdpi, xhdpi, xxhdpi,  xxxhdpi) 5개 이미지 준비

-> 1개의 버튼에 총 15개의 이미지 필요

 

9-patch 이미지

Image에서 늘어날 수 있는 영역과 원본 크기대로 표시되어야 할 영역을 구분하여, 이미지가 그려질 영역의 크기가 늘어나거나 줄어들더라도 원본이미지 형태를 유지하도록 만들어진 Image를 나인 패치(9-patch)이미지라고 한다.

ImageView

앱 화면에 이미지를 표시하는 용도

 

 기본 사용법

    • Layout리소스 XML파일에 ImageView를 추가
    • 화면에 표시 할 이미지를 Drawable리소스에 추가
    • 화면에 표시 할 이미지(Drawable)리소스 ID를 ImageView의"src"속성에 지정

Drawable리소스에 이미지 추가

    • 이미지 파일의 형식은 .jpg,.png가 가능하나 대부분.png를 사용함(투명도 때문)
    • 이미지 파일을 /res/drawable에 추가한다.
    • 해상도에 따른 다른 크기의 이미지는 별도의 폴더를 생성하고 복사(drawable-xhdpi등..)

Layout리소스 XML과 Kotlin소스 두가지 코드 모두에서 이미지뷰 추가 및 변경 가능

 

ImageView의 영역에 맞게 이미지 확대 또는 축소하는 방법

scaleType 속성 > android:scaleType

1) android:scaleType = "Center"

이미지의 크기와 비율을 유지하며 이미지의 중앙을 ImageView의 중심에 맞춥니다. 이때, ImageView보다 이미지가 클 경우 이미지가 잘릴 수 있습니다.

2) android:scaleType = "centerCrop"

이미지의 비율을 유지하며 가로,세로 중 짧은 쪽을 ImageView에 꽉 차게 출력합니다. 이때도 마찬가지로 ImageView를 벗어나는 부분은 출력되지 않습니다.

3) android:scaleType = "centerInside"

이미지의 가로, 세로 중 긴 쪽을 ImageView의 레이아웃에 맞춰 출력합니다. 이미지의 비율은 유지되며 남는 공간은 background의 색으로 채워집니다. fitCenter와 달리 이미지가 ImageView보다 작을 경우 크기가 유지됩니다.

4) android:scaleType = "fitCenter"

centerInside와 매우 유사합니다. 단, 이미지의 크기가 ImageView보다 작다면 ImageView의 크기에 따라 달라집니다.

5) android:scaleType = "fitStart"

ImageView 안에서 가로, 세로 비율을 유지하며 fit하게 출력됩니다. 단, fitCenter와 다르게 왼쪽 상단을 기준으로 정렬됩니다.

6) android:scaleType = "fitEnd"

감이 오시나요? fitStart와 마찬가지로 가로&세로 비율을 유지하며 fit하게 출력됩니다. 우측 하단을 기준으로 정렬됩니다.

7) android:scaleType = "fitXY"

가로, 세로 비율에 상관 없이 ImageView에 꽉 차게 보여집니다. 이미지가 찌그러진 상태로 보입니다.

8) android:scaleType = "matrix"

이미지의 크기, 비율을 유지하며 ImageView의 좌측상단을 기준으로 정렬됩니다. 이미지가 크다면 ImageView 외의 부분은 출력되지 않습니다.

안드로이드 스튜디오 왼쪽 하단에 보면 북마크 기능이 있다.

잘 활용하면 코드찾는 수고를 덜 수 있다.

Bookmarks -> crtl + shift + 지정 숫자

북마크를 원하는 코드줄로 가서

crtl + shift + 1 로 지정할 경우 아래와 같이 코드파일과 북마크에 1상자와 함께 생성된다. 

다른 코드를 보다가 북마크에 추가한 코드를 보고싶을 땐 crtl + 지정 숫자를 누르면 지정 숫자로 북마크에 추가한 코드줄로 이동하게 된다.

 

코드가 짧을 땐 별로 안쓰일 수 있지만 길 땐 정말 잘 활용될 것 같다.

+ 북마크 제거할때도 마찬가지로 crtl + shift +지정 숫자 로 제거 가능하고 북마크탭에서도 delete가능하다.

+ Recent posts