[Android Studio|Kotlin] View
Published: 2022-02-27 06:20:09


**basic Setting** 
```
    buildFeatures {
        viewBinding = true
    }
```

**1) custom View**
[MainActivity.kt]
```
class MainActivity : AppCompatActivity() {
    val binding by lazy {ActivityMainBinding.inflate(layoutInflater)}
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(binding.root)

        val customView = CustomView(this)
        binding.frameLayout.addView(customView)
    }
}
```
[CustomView.kt]

```
class CustomView(context: Context) : View(context) {
    override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)

        val paint = Paint()
        paint.color = Color.BLACK
        paint.textSize = 100f

        canvas?.run {
            drawText("Hello", 0f, 100f, paint)
            customDrawCircle(canvas)
            customDrawRect(canvas)
        }
    }
    fun customDrawCircle(canvas:Canvas) {
        val paint = Paint()
        paint.style = Paint.Style.FILL
        paint.color = Color.BLUE

        canvas.drawCircle(150f, 300f, 100f, paint)
    }
    fun customDrawRect(canvas: Canvas) {
        val paint = Paint()
        paint.style = Paint.Style.STROKE
        paint.strokeWidth = 20f
        paint.color = Color.GREEN

        val rect = RectF(50f, 450f, 250f, 650f)
        canvas.drawRect(rect, paint)
    }
}
```
[activity_main.xml]

```
<androidx.constraintlayout.widget.ConstraintLayout
<TextView />
<FrameLayout />
</androidx.constraintlayout.widget.ConstraintLayout
```
**2) custom Widget**
[MainActivity.kt]

```
class MainActivity : AppCompatActivity() {
    val binding by lazy {ActivityMainBinding.inflate(layoutInflater)}
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(binding.root)
    }
}
```
[CustomText.kt]

```
class CustomText : AppCompatTextView {
    constructor(context: Context) : super(context) { }
    constructor(context: Context, attrs:AttributeSet) : super(context, attrs) {
        val attrList = context.obtainStyledAttributes(attrs, R.styleable.CustomText)
        for(i in 0 until attrList.indexCount) {
            val attr = attrList.getIndex(i)
            when(attr) {
                R.styleable.CustomText_delimeter -> {
                    attrList.getString(attr)?.let {
                        process(it)
                    }
                }
            }
        }
    }
    constructor(context: Context, attrs:AttributeSet, defStyleAttr:Int) : super(context, attrs, defStyleAttr ) {}
    fun process(delimeter: String) {
        if(text.length == 8) {
            val first4 = text.substring(0,4)
            val mid2 = text. substring(4,6)
            val last2 = text.substring(6)

            text = "$first4$delimeter$mid2$delimeter$last2"
        }
    }
}
```
[res > values > attrs.xml]

```
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="CustomText">
        <attr name="delimeter" format="string"/>
    </declare-styleable>
</resources>
```
[activity_mains.xml]

```
<androidx.constraintlayout.widget.ConstraintLayout
<com.example.myapplication.CustomText
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:text="20220226"
 app:delimeter="-"/>
</androidx.constraintlayout.widget.ConstraintLayout
```
**3-1) ViewPager & TabLayout**
[MainActivity.kt]
```
class MainActivity : AppCompatActivity() {
    val binding by lazy {ActivityMainBinding.inflate(layoutInflater)}
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(binding.root)

        val list = listOf(FragmentA(), FragmentB(), FragmentC(), FragmentD() )
        // create adapter
        val pagerAdapter = FragmentPagerAdapter(list, this)
        // connect adapter and viewpager
        binding.viewPager.adapter = pagerAdapter

        // Create a list of titles as many as the number of tab menus
        val titles = listOf("A", "B", "C", "D")
        // connect TabLayout ViewPager2
        TabLayoutMediator(binding.tabLayout, binding.viewPager) { tab, position ->
            tab.text = titles.get(position)
        }.attach()
    }
}

class FragmentPagerAdapter(val fragmentList:List<Fragment>, fragmentActivity: FragmentActivity)
    : FragmentStateAdapter(fragmentActivity) {
    override fun getItemCount() = fragmentList.size
    override fun createFragment(position: Int) = fragmentList.get(position)
}
```
create [FragmentA.kt], [FragmentB.kt], [FragmentC.kt], [FragmentD.kt]
create with ([fragment_a.xml], [fragment_b.xml], [fragment_c.xml], [fragment_d.xml],)
[activity_main.kt]

```
<androidx.constraintlayout.widget.ConstraintLayout 
<androidx.viewpager2.widget.ViewPager2 android:id="@+id/viewPager"
<com.google.android.material.tabs.TabLayout android:id="@+id/tabLayout"
<androidx.constraintlayout.widget.ConstraintLayout 
```

**4) tablayout, viewpager and recyclerview**
[MainActivity.kt] 
```
class MainActivity : AppCompatActivity() {
    val binding by lazy {ActivityMainBinding.inflate(layoutInflater)}
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(binding.root)

        val list = listOf("MON", "TUE", "WED","THR", "FRI","SAT","SUN")
        // create adapter
        val pagerAdapter = CustomPagerAdapter(list)
        // connect adapter and viewpager
        binding.viewPager.adapter = pagerAdapter
        //Create a list of tab titles - skip
        // connect tablayout and viewpager
        TabLayoutMediator(binding.tabLayout, binding.viewPager) { tab, position ->
            tab.text = list.get(position)
        }.attach()
    }
}
class CustomPagerAdapter(val textList:List<String>) : RecyclerView.Adapter<CustomPagerAdapter.Holder>() {
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
        val binding = ItemViewpagerBinding.inflate(LayoutInflater.from(parent.context), parent, false)
        return Holder(binding)
    }
    override fun getItemCount() = textList.size
    override fun onBindViewHolder(holder: Holder, position: Int) {
        holder.setItem(textList.get(position))
    }
    class Holder(val binding:ItemViewpagerBinding) : RecyclerView.ViewHolder(binding.root) {
        fun setItem(text:String) {
            binding.textView.text = text
        }
    }
}
```
[activity_main.xml]

```
<androidx.constraintlayout.widget.ConstraintLayout
<com.google.android.material.tabs.TabLayout android:id="@+id/tabLayout"
</com.google.android.material.tabs.TabLayout
<androidx.viewpager2.widget.ViewPager2 android:id="@+id/viewPager"
/>
</androidx.constraintlayout.widget.ConstraintLayout
```
[item_viewpager.xml]

```
<androidx.constraintlayout.widget.ConstraintLayout
<TextView android:id="@+id/textView"
</androidx.constraintlayout.widget.ConstraintLayout
```
**5) tablayout, viewpager and recyclerview**
[MainActivity.kt]
```
class MainActivity : AppCompatActivity() {
    val binding by lazy {ActivityMainBinding.inflate(layoutInflater)}
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(binding.root)

        val list = loadData()
        // create adapter
        val pagerAdapter = CustomPagerAdapter(list)
        // connect adapter and viewpager
        binding.viewPager.adapter = pagerAdapter
        //Create a list of tab titles
        val titles = listOf("MON", "TUE", "WED","THR", "FRI","SAT","SUN")
        // connect tablayout and viewpager
        TabLayoutMediator(binding.tabLayout, binding.viewPager) { tab, position ->
            tab.text = titles.get(position)
        }.attach()
    }
    fun loadData() : List<Page> {
        val pageList = mutableListOf<Page>()
        pageList.add(Page(1, "Cloudy"))
        pageList.add(Page(2, "Clear"))
        pageList.add(Page(3, "Cloud"))
        pageList.add(Page(4, "Rain"))
        pageList.add(Page(5, "Snow"))
        pageList.add(Page(6, "Typhoon"))
        pageList.add(Page(7, "Fog"))
        return pageList
    }
}
class CustomPagerAdapter(val pageList:List<Page>) : RecyclerView.Adapter<CustomPagerAdapter.Holder>() {
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
        val binding = ItemViewpagerBinding.inflate(LayoutInflater.from(parent.context), parent, false)
        return Holder(binding)
    }
    override fun getItemCount() = pageList.size
    override fun onBindViewHolder(holder: Holder, position: Int) {
        holder.setItem(pageList.get(position))
    }
    class Holder(val binding:ItemViewpagerBinding) : RecyclerView.ViewHolder(binding.root) {
        fun setItem(page:Page) {
            with(binding) {
                textDay.text = "${page.day} DAY"
                textWeather.text = page.weather
            }
        }
    }
}
data class Page(val day:Int, val weather:String)
```
[activity_main.xml]

```
<androidx.constraintlayout.widget.ConstraintLayout
<com.google.android.material.tabs.TabLayout android:id="@+id/tabLayout"
<androidx.viewpager2.widget.ViewPager2 android:id="@+id/viewPager"
</androidx.constraintlayout.widget.ConstraintLayout
```
[item_viewpager.xml]

```
<androidx.constraintlayout.widget.ConstraintLayout
<TextView android:id="@+id/textDay"
<TextView android:id="@+id/textWeather"
</androidx.constraintlayout.widget.ConstraintLayout
```

6) add tablayout,viewpager, recyclerView and retrofit

[app > manifests > AndroidManifest.xml ] 

``` 
<uses-permission android:name="android.permission.INTERNET"/>
```
[Gradle Scripts > build.gradle]
``` 
dependencies {
    // fragment
    implementation "androidx.fragment:fragment-ktx:1.4.1"
    // retrofit
    implementation 'com.squareup.retrofit2:retrofit:2.9.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
}
```


[MainActivity.kt]

```
class MainActivity : AppCompatActivity() {
    val binding by lazy { ActivityMainBinding.inflate(layoutInflater)}
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(binding.root)

        // 1. load page data
        val list = listOf( FragmentA(), FragmentB(), FragmentC() )
        // 2. create adapter
        val pagerAdapter = FragmentPagerAdapter(list, this)
        // 3. connect adapter and viewpager
        binding.viewPager.adapter = pagerAdapter

        // Create a list of titles as many as the number of tab menus
        val titles = listOf("tabname1", "tabname2", "tabname3" )
        // connect TabLayout ViewPager2
        TabLayoutMediator(binding.tabLayout, binding.viewPager) { tab, position ->
            tab.text = titles.get(position)
        }.attach()
    }
}
class FragmentPagerAdapter(val fragmentList:List<Fragment>, fragmentActivity: FragmentActivity)
    : FragmentStateAdapter(fragmentActivity) {
    override fun getItemCount() = fragmentList.size
    override fun createFragment(position: Int) = fragmentList.get(position)
}
```
[ApiService.kt]

```
interface ApiService {
    @GET("/apptech")
    fun getPosts(): Call<MutableList<Apptech>>
}
```
[ServiceGenerator.kt]

```
object ServiceGenerator {
    private val client = OkHttpClient.Builder().build()
    private val retrofit = Retrofit.Builder()
        .baseUrl("https://****.herokuapp.com")
        .addConverterFactory(GsonConverterFactory.create())
        .client(client)
        .build()

    fun <T> buildService(service: Class<T>): T {
        return retrofit.create(service)
    }
}
```
[Apptech.kt]

```
data class Apptech(
    val apptech_brand: String? = null,
    val apptech_title: String? = null,
    val apptech_period: String? = null,
    val apptech_point: Int? = null,
    val apptech_time: String? = null,
    val apptech_url: String? = null
)
```
[ApptechAdapter.kt]

```
class ApptechAdapter(val apptechData: MutableList<Apptech>) : RecyclerView.Adapter<ApptechAdapter.Holder>() {
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
        val binding = FragmentBItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
        return Holder(binding)
    }
    override fun getItemCount() = apptechData.size
    override fun onBindViewHolder(holder: Holder, position: Int) {
        //val apptech = apptechData.get(position)
        //holder.setApptech(apptech)
        return holder.setApptech(apptechData[position])
    }
    class Holder(val binding: FragmentBItemBinding) : RecyclerView.ViewHolder(binding.root) {
        fun setApptech(apptech: Apptech) {
            with(binding) {
                tvTitle.text = "${apptech.apptech_brand}"
                tvBody.text = "${apptech.apptech_title}"
                tvTime.text = "${apptech.apptech_time}"

                binding.root.setOnClickListener {
                    var url = "${apptech.apptech_url}"
                    val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
                    ContextCompat.startActivity(itemView.context, intent, null)
                }
            }
        }
    }
}
```
[FragmentA.kt]

```
class FragmentA : Fragment() {
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_a, container, false)
    }
}
```
[FragmentB.kt]

```
class FragmentB : Fragment() {
    lateinit var binding: FragmentBBinding
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        binding = FragmentBBinding.inflate(inflater, container, false)
        return binding.root
    }
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        val serviceGenerator = ServiceGenerator.buildService(ApiService::class.java)
        val call = serviceGenerator.getPosts()
        call.enqueue(object : Callback<MutableList<Apptech>> {
            override fun onResponse(call: Call<MutableList<Apptech>>, response: Response<MutableList<Apptech>>) {
                with(binding){
                    recyclerView.apply{
                        adapter = ApptechAdapter(response.body()!!)
                        layoutManager = LinearLayoutManager(activity)
                    }
                }
            }
            override fun onFailure(call: Call<MutableList<Apptech>>, t: Throwable) {
                t.printStackTrace()
                Log.e("error", t.message.toString())
            }
        })
    }
}
```
[FragmentC.kt]

```
class FragmentC : Fragment() {
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? { 
        return inflater.inflate(R.layout.fragment_c, container, false)
    }
}
```
[activity_main.xml]

```
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.google.android.material.tabs.TabLayout
        android:id="@+id/tabLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <com.google.android.material.tabs.TabItem
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Monday" />

        <com.google.android.material.tabs.TabItem
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Tuesday" />

        <com.google.android.material.tabs.TabItem
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Wednesday" />
    </com.google.android.material.tabs.TabLayout>

    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/tabLayout" />
</androidx.constraintlayout.widget.ConstraintLayout>
```
[fragment_a.xml]

```
<androidx.constraintlayout.widget.ConstraintLayout 
<\androidx.constraintlayout.widget.ConstraintLayout 
```
[fragment_b.xml]

```
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".fragment.FragmentB">
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</FrameLayout>
```
[fragment_b_item.xml]

```
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    xmlns:tools="http://schemas.android.com/tools"
    android:paddingTop="8dp"
    android:paddingBottom="8dp"
    android:paddingLeft="15dp"
    android:layout_marginTop="4dp"
    android:layout_marginBottom="4dp"
    android:layout_marginLeft="8dp"
    android:layout_marginRight="8dp"
    android:orientation="horizontal"
    android:background="@drawable/border_a">

    <TextView
        android:id="@+id/tvTitle"
        tools:text="Hello Title"
        android:layout_width="80dp"
        android:layout_height="match_parent"
        android:textColor="@color/black"
        android:textSize="20sp" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:paddingLeft="15dp"
        android:paddingRight="15dp" >

        <TextView
            android:id="@+id/tvBody"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textSize="14sp"
            tools:text="Hello Body"
            android:textAlignment="center"/>

        <TextView
            android:id="@+id/tvTime"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:textSize="14sp"
            tools:text="Hello Time"
            android:textAlignment="center"/>
    </LinearLayout>
</LinearLayout>
```
[fragment_c.xml]

```
<FrameLayout
<\FrameLayout
```
[res > drawable > border_a.xml]

```
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="#FFD0D0"></solid>
    <stroke android:width="3dp" android:color="#FF8484"/>
    <corners android:radius="15dp"/>
</shape>
```