액티비티를 만들 때처럼 kt파일과 layout로 만든다.
파일 생성 또한 액티비티 밑에 Fragment파일이 존재한다.
gradle에
implementation("androidx.fragment:fragment-ktx:1.6.1")를 추가 해야 한다.
package com.example.fragmentprac
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private const val ARG_PARAM1 = "param1"
private const val ARG_PARAM2 = "param2"
/**
* A simple [Fragment] subclass.
* Use the [FirstFragment.newInstance] factory method to
* create an instance of this fragment.
*/
class FirstFragment : Fragment() {
// TODO: Rename and change types of parameters
private var param1: String? = null
private var param2: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
param1 = it.getString(ARG_PARAM1)
param2 = it.getString(ARG_PARAM2)
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_first, container, false)
}
companion object {
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment FirstFragment.
*/
// TODO: Rename and change types and number of parameters
@JvmStatic
fun newInstance(param1: String, param2: String) =
FirstFragment().apply {
arguments = Bundle().apply {
putString(ARG_PARAM1, param1)
putString(ARG_PARAM2, param2)
}
}
}
}
생성만 하면 이런 코드들이 자동생성되며,
액티비티처럼 레이아웃도 자동생성 할 수 있다.
<?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=".FirstFragment">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/hello_blank_fragment" />
</FrameLayout>
처음엔 FrameLayout으로 지정이 되며, 원하는대로 레이아웃 지정.
보여줄 2개의 Fragment layout을 작성하고
//첫번째 Fragment layout
<?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"
android:layout_width="match_parent"
android:background="#F19B9B"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="프래그먼트 1"
android:textSize="40sp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
//두번 째 layout
<?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"
android:layout_width="match_parent"
android:background="#C785D3"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="프래그먼트 2"
android:textAllCaps="false"
android:textSize="40sp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
메인화면에서 버튼과 FrameLayout으로 프래그먼트 영역을 지정한다.
<?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">
<FrameLayout
android:id="@+id/frameLayout"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
app:layout_constraintBottom_toTopOf="@+id/fragment1_btn"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</FrameLayout>
<Button
android:id="@+id/fragment1_btn"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="Frag1"
android:textAllCaps="false"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/fragment2_btn"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/frameLayout" />
<Button
android:id="@+id/fragment2_btn"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="Frag2"
android:textAllCaps="false"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/fragment1_btn"
app:layout_constraintTop_toBottomOf="@+id/frameLayout" />
</androidx.constraintlayout.widget.ConstraintLayout>
메인Activity에서 적용하면
package com.example.fragmentprac
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.fragment.app.Fragment
import androidx.fragment.app.commit
import com.example.fragmentprac.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
private val binding by lazy { ActivityMainBinding.inflate(layoutInflater) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
binding.apply {
fragment1Btn.setOnClickListener {
setFragment(FirstFragment())
}
fragment2Btn.setOnClickListener {
setFragment(SecondFragment())
}
}
setFragment(FirstFragment())
}
//setFragment 함수를 지정해준다.
private fun setFragment(frag : Fragment) {
supportFragmentManager.commit {
replace(R.id.frameLayout, frag)
setReorderingAllowed(true)
addToBackStack("")
}
}
}
액티비티 간 이동이 아닌 같은 액티비티 안에서 가운데만 바뀌는 걸 확인 할 수 있다.
다이얼로그는 세가지 영역이 있다.
종류
1). 기본 다이얼로그(AlertDialog)
binding.button3.setOnClickListener {
//무슨말을 쓰며, 아이콘은 뭘 쓸건지
var builder = AlertDialog.Builder(this)
builder.setTitle("기본 다이얼로그 타이틀입니다")
builder.setMessage("기본 다일로그 메세지")
builder.setIcon(R.mipmap.ic_launcher)
//어떤 버튼을 누를거고 버튼 눌렀을 때 어떤 작업을 할지
val listener = object : DialogInterface.OnClickListener{
override fun onClick(p0: DialogInterface?, p1: Int){
when(p1) {
DialogInterface.BUTTON_POSITIVE ->
binding.textView5.text = "Positive"
DialogInterface.BUTTON_NEUTRAL ->
binding.textView5.text = "Neutral"
DialogInterface.BUTTON_NEGATIVE ->
binding.textView5.text = "Negative"
}
}
}
builder.setPositiveButton("Positive",listener)
builder.setNegativeButton("Negative",listener)
builder.setNeutralButton("Neutral",listener)
builder.show()
}
}
}
2). 커스텀 다이얼로그(CustomDialog)
//dialog.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">
<LinearLayout
android:layout_width="406dp"
android:layout_height="161dp"
android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<EditText
android:id="@+id/editTextText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ems="10"
android:inputType="text"
android:text="Name" />
<EditText
android:id="@+id/editTextText2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ems="10"
android:inputType="text"
android:text="gd" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
binding.button4.setOnClickListener {
val builder = AlertDialog.Builder(this)
builder.setTitle("커스텀 다이얼로그")
builder.setIcon(R.mipmap.ic_launcher)
val v1 = layoutInflater.inflate(R.layout.dialog, null)
builder.setView(v1)
// p0에 해당 AlertDialog가 들어온다. findViewById를 통해 view를 가져와서 사용
val listner = DialogInterface.OnClickListener { p0,p1 ->
val alert = p0 as AlertDialog
val edit1: EditText? = alert.findViewById(R.id.editTextText)
val edit2: EditText? = alert.findViewById(R.id.editTextText2)
}
builder.setPositiveButton("ㅇㅋ",listner)
builder.setNegativeButton("ㄴㄴ",null)
builder.show()
}
3). 날짜 다이얼로그(DatePickerDialog)
//날짜 다이얼로그
binding.button5.setOnClickListener {
val calender = Calendar.getInstance()
val year = calender.get(Calendar.YEAR)
val month = calender.get(Calendar.MONTH)
val day = calender.get(Calendar.DAY_OF_MONTH)
val listener = DatePickerDialog.OnDateSetListener { datePicker, i, i2, i3 ->
// i년 i2월 i3일
binding.textView5.text = "${i}년${i2}월${i3}일"
}
var picker = DatePickerDialog(this, listener, year, month, day)
picker.show()
}
}
}
4). 시간 다이얼로그(TimePickerDialog)
//시간 다이얼로그
binding.button6.setOnClickListener {
val calendar =Calendar.getInstance()
val hour = calendar.get(Calendar.HOUR)
val minute = calendar.get(Calendar.MINUTE)
val listener = TimePickerDialog.OnTimeSetListener { timePicker, i, i2 ->
binding.textView5.text = "${i}시 ${i2}분"
}
val picker = TimePickerDialog(this, listener,hour,minute, false)
picker.show()
}
5). 진행 다이얼로그(ProgressDialog)
커스텀 다이얼로그와 비슷하게 xml파일을 생성한다.
//progressbar.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="match_parent"
android:gravity="center"
android:orientation="vertical">
<ProgressBar
android:id="@+id/progressbar"
android:layout_width="match_parent"
android:layout_height="76dp"
android:layout_gravity="center"
android:layout_marginTop="48dp"
android:indeterminate="false"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="loading..."
android:textSize="16sp"
android:layout_marginTop="16dp"/>
</LinearLayout>
kt파일
// 5. 프로그레스 다이얼로그
// binding.button7.setOnClickListener {
// // 권장하진 않지만 사용은 가능하다.
// pro = ProgressDialog.show(this, "타이틀입니다.", "메시지입니다.")
//
// // 핸들러를 통해서 종료 작업을 한다.
// val handler = Handler()
// val thread = Runnable { pro?.cancel() }
// handler.postDelayed(thread, 5000) // 딜레이는 5초
// }
//
//6. 프로그래스 다이얼로그 다른 방식. (커스텀과 비슷)
binding.button7.setOnClickListener {
val builder = AlertDialog.Builder(this)
builder.setTitle("프로그래스바")
builder.setIcon(R.mipmap.ic_launcher)
val v1 = layoutInflater.inflate(R.layout.progressbar, null)
builder.setView(v1)
builder.show()
}
package com.example.alam
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Intent
import android.graphics.BitmapFactory
import android.media.AudioAttributes
import android.media.RingtoneManager
import android.net.Uri
import android.os.Build
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.core.app.NotificationCompat
import com.example.alam.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
private val binding by lazy { ActivityMainBinding.inflate(layoutInflater) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
binding.button.setOnClickListener {
notification()
}
}
fun notification() {
val manager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
val builder: NotificationCompat.Builder
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// 26 버전 이상
val channelID = "one-channel"
val channerName = "My Channel One"
val channel = NotificationChannel(
channelID,
channerName,
NotificationManager.IMPORTANCE_DEFAULT
).apply {
//채널에 다양한 정보 설정
description = "My Channel One Description"
setShowBadge(true)
val uri: Uri = RingtoneManager.getDefaultUri((RingtoneManager.TYPE_NOTIFICATION))
val audioAttributes = AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.setUsage(AudioAttributes.USAGE_ALARM)
.build()
setSound(uri, audioAttributes)
enableVibration(true)
}
//채널을 NotificationManager에 등록
manager.createNotificationChannel(channel)
//채널을 이용하여 builder 생성
builder = NotificationCompat.Builder(this, channelID)
} else {
builder = NotificationCompat.Builder(this)
}
val bitmap = BitmapFactory.decodeResource(resources, androidx.core.R.drawable.notification_bg)
val intent = Intent(this, SecondActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
val pendingIntent = PendingIntent.getActivity(
this,
0,
intent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
builder.run {
setSmallIcon(R.mipmap.ic_launcher)
setWhen(System.currentTimeMillis())
setContentTitle("새로운 알림입니다.")
setContentText("알림이 잘 보이나요?")
setStyle(
NotificationCompat.BigTextStyle()
.bigText(
"이것은 긴텍스트 샘플입니다. 아주 긴 텍스트를 쓸때는 여기다 하면 됩니다.이것은 긴텍스트 샘플입니다. \n" +
"아주 긴 텍스트를 쓸때는 여기다 하면 됩니다.이것은 긴텍스트 샘플입니다. 아주 긴 텍스트를 쓸때는 여기다 하면 됩니다. "
)
)
setLargeIcon(bitmap)
//긴 텍스트 대신 이미지로 할때
// setStyle(NotificationCompat.BigPictureStyle()
// .bigPicture(bitmap)
// .bigLargeIcon(null))
addAction(R.mipmap.ic_launcher, "Action", pendingIntent)
}
manager.notify(11, builder.build())
}
}
(/ω\)
오늘 엄청 많이하셨네요!!