16 Apr 2019
|
Android
Kotlin
colors.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#F48FB1</color>
<color name="colorPrimaryDark">#F48FB1</color>
<color name="textColorPrimary">#EC407A</color>
<color name="windowBackground">#FFFFFF</color>
<color name="navigationBarColor">#000000</color>
<color name="colorAccent">#c8e8ff</color>
</resources>
dimens.xml
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
<dimen name="tab_max_width">264dp</dimen>
<dimen name="tab_padding_bottom">16dp</dimen>
<dimen name="tab_label">14sp</dimen>
<dimen name="custom_tab_layout_height">72dp</dimen>
</resources>
styles.xml
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="RanMaterialTheme.Base">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
<style name="RanMaterialTheme.Base" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="windowNoTitle">true</item>
<item name="windowActionBar">false</item>
</style>
</resources>
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/add_tab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_gravity="end"
android:text="+"/>
<android.support.design.widget.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toStartOf="@id/add_tab"
app:tabGravity="fill"
app:tabMode="scrollable"/>
</RelativeLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
</android.support.design.widget.CoordinatorLayout>
MainActivity.kt
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.support.design.widget.TabLayout
import android.support.v7.widget.Toolbar
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val toolbar = findViewById<Toolbar>(R.id.toolbar)
setSupportActionBar(toolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
val list = ArrayList<String>()
list.add("Year")
list.add("Month")
list.add("Week")
list.add("Day")
val adapter = TodoListPagerAdapter(supportFragmentManager)
adapter.setList(list)
viewpager.adapter = adapter
val tabLayout = findViewById<TabLayout>(R.id.tabs)
tabLayout.setupWithViewPager(viewpager)
add_tab.setOnClickListener {
list.add("Added")
adapter.setList(list)
}
}
}
15 Apr 2019
|
Kotlin
is와 as
코틀린에서는 타입 체크할 때 is 키워드를 사용하며, Java에서의 instanceof와 동일한 역할을 합니다.
그리고 타입 캐스팅시에는 as 키워드를 사용합니다.
fun setLayoutParam(view: View) {
if (view is LinearLayout) {
var param = view.layoutParams as LinearLayout.LayoutParams
param.gravity = Gravitiy.CENTER
view.layoutParams = param
} else if (view is RelativeLayout) {
var param = view.layoutParams as RelativeLayout.LayoutParams
param.addRule(RelativeLayout.ALIGN_PARENT_CENTER)
view.layoutParams = param
}
}
NullPoint Exception 방지
코틀린에서는 ? 기호를 이용해서 해당 변수가 null 값을 가질 수 있음을 알려주며, 기본적으로는 non null 상태입니다.
var str:String? = "hello"
str = null
그리고 변수를 사용할 때도 변수뒤에 ? 기호를 붙여서 Nullpoint Exception 처리를 할 수 있습니다.
fun test() {
var str: String? = "hello"
str = null
var length: Int? = str?.length
}
위의 예제에서 만약 str 변수가 null이 되면 str?.length도 null을 리턴하기 때문에 length 변수가 null이 됩니다.
즉, 위험할 수 있는 코드이기 때문에 아래와 같이 표현할 수 있습니다.
fun test() {
var str: String? = "hello"
str = null
var length: Int = str?.length ?: 0
}
위와 같이 코드를 작성하면 str?.length가 null일 경우 숫자 0 으로 리턴하기 때문에 length 변수는 항상 값을 가질 수 있습니다.
그리고 !! 기호를 사용하게 되면 명시적으로 변수에 절대 null을 참조할 수 없다는 것을 지정할 수 있습니다.
fun test() {
var str: String? = "hello"
var length: Int = str!!.length
}
== 와 ===
==와 ===는 비교 연산자로 ==는 Java에서 사용하던 ==와 동일한 역할을 합니다. 그리고 내부적으로 NULL 체크를 하기 때문에 좀 더 간략하게 코드를 작성할 수 있습니다. 다만, a == b에서 a와 b 모두 null인 경우 true가 되기 때문에 주의할 필요는 있습니다.
===의 경우는 두 변수가 정말 똑같은 주소값을 갖고 있는지 판단하며 Java에서의 equals()와 동일합니다.
15 Apr 2019
|
Kotlin
코틀린은 자바에서와는 달리 리스트(List)나 맵(Map) 등의 자료 구조에 읽기 전용 객체와 수정이 가능한 객체로 나누어 놓았습니다.
코틀린에서는 리스트를 생성할 때 클래스를 선언하지 않아도 만들 수 있는 함수를 제공하고 있습니다. 리스트를 생성하는 함수는 listOf이며, 맵을 생성하는 함수는 mapOf입니다. 이 함수를 이용하면 읽기 전용의 리스트가 만들어집니다.
fun init() {
val numList = listOf(1, 3, 7, 5, 10)
val strList = listOf("snowdeer", "ran", "yang")
val map = mapOf(1 to "one", 2 to "two", 3 to "three")
}
읽기 전용 리스트를 만들면 get, first, last 등 데이터를 읽을 수 있는 함수들만 제공됩니다.
만약, 수정이 가능한 리스트들을 만들고 싶으면 mutableListOf, mutableMapOf 함수를 사용하면 됩니다.
fun init() {
val numList = mutableListOf(1, 3, 7, 5, 10)
val strList = mutableListOf("snowdeer", "ran", "yang")
val map = mutableMapOf(1 to "one", 2 to "two", 3 to "three")
}
15 Apr 2019
|
Android
Kotlin
팩토리 메소드(newInstance)로 Fragment를 생성하는 예제 코드입니다.
import android.os.Bundle
import android.support.v4.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
private const val ARG_TITLE = "TITLE"
class TodoListFragment : Fragment() {
private var title: String? = ""
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
title = it.getString(ARG_TITLE)
}
}
companion object {
fun newInstance(title: String): TodoListFragment {
return TodoListFragment().apply {
arguments = Bundle().apply {
putString(ARG_TITLE, title)
}
}
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_todolist, container, false)
}
}
15 Apr 2019
|
Android
Kotlin
AndroidManifest.xml 에서 다음과 같은 오류가 발생할 경우 해결하는 방법입니다.
App is not indexable by Google Search; consider adding at least one Activity with an ACTION-VIEW intent filter.
적어도 하나 이상의 액티비티의 인텐트 필터에 다음 라인을 추가하면 됩니다.
<action android:name="android.intent.action.VIEW"/>