본문 바로가기
안드로이드 스튜디오

안드로이드: Fragment , NullSafety,Resource

by 질서정연_ 2020. 8. 16.

<Fragment>

button.setOnClickListener{
            //프라그먼트를 동적으로 작동하는 방법
            //Fragment 붙이는 방법 replace/add
            val fragmentManager: FragmentManager = supportFragmentManager

            //Transaction
            //작업의 단위 -> 시작과 끝이 있다.
            val fragmentTransaction = fragmentManager.beginTransaction() //시작
            //할일
            fragmentTransaction.replace(R.id.container, fragmentOne) // 할일
            fragmentTransaction.commit() //보통 commit은 끝을 뜻함.
            //끝을 내는 방법
            //commit     -> 시간 될 때 해 (좀 더 안정적)
            //commitnow  -> 지금 당장해
        }

구성요소가 다양해서 엑티비티가 엄청 길어질 수 있음

 

프라그먼트의 엑티비티 라이프 사이클도 관리해줘야함. 

엑티비티 종속적이기 때문임. 

프라그먼트 사용이 나중에 유지보수할때 더 좋음. 

 

 

<LinearLayout
android:layout_width="match_parent"
android:background="@drawable/gradient"
android:layout_height="200dp"/>

 

이 부분 List라고 생각. 이 부분을 Fragment로 넘겨줄거임 . 

그럴거면 쟤를 지울거임.

프라그먼트 사용할때 중요한거. 

이 프라그먼트 뷰 컴포넌트를 어떤 프라그먼트가 담당할지 써줘야함. 

<fragment

android:id="@+id/fragment_one"

android:name="com.example.myapplication.FragmentOne"
android:layout_width="match_parent"
android:layout_height="300dp"/>

얘가 이 프라그먼트를 책임지겠다.

반드시 아이디도 지정해줘야함. FragmentOne이 이 뷰를 책임지는거임.

 

라이프 사이클 중 override fun onCreateView 얘가 뷰를 그리는 애임

프라그먼트가 인터페이스를 처음으로 그릴 때 호출된다.

그래서 얘 안에서 뷰를 그려주면 됨. 뷰 그릴 때 

프라그먼트가 위의 xml에 들러붙음. 쟤의 부모 뷰의 fragment에 붙음. 

 

inflater.inflate(R.layout.fragment_one,container,false)

이 프레그먼트의 레이아웃임

붙을 자리를 말함. 어디에 붙을지

붙을지 말지 정해주는 애인데 그냥 false 넣기

 

inflate의 return 형식이 View이므로 걍 return .

 

액티비티보다 fragment가 먼저 호출이 되었음. 

 

manifest에는 activity만 추가되고 fragment는 추가되지 않는다. 

 

xml말고 코드로도 fragment 추가할 수 있다. 

 

아 날아감..

- Activity -> Fragment : argument bundle
이 부분 코드 보고 다시 적기

<정적으로 Fragment를 Activity에 붙여주기>

<fragment
        android:id="@+id/fragment_one"
        android:name="com.example.myapplication.FragmentOne"
        android:layout_width="match_parent"
        android:layout_height="300dp" />

<동적으로 붙여주기>

-xml

<LinearLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:background="#FFC107"
        android:orientation="vertical"/>
button.setOnClickListener{
            //프라그먼트를 동적으로 작동하는 방법
            //Fragment 붙이는 방법 replace/add
            val fragmentManager: FragmentManager = supportFragmentManager

            //Transaction
            //작업의 단위 -> 시작과 끝이 있다.
            val fragmentTransaction = fragmentManager.beginTransaction() //시작
            //할일
            fragmentTransaction.replace(R.id.container, fragmentOne) // 할일
            fragmentTransaction.commit() //보통 commit은 끝을 뜻함.
            //끝을 내는 방법
            //commit     -> 시간 될 때 해 (좀 더 안정적)
            //commitnow  -> 지금 당장해
        }
button2.setOnClickListener {
            //Fragment remove/detach 하는 방법
            val fragmentManager: FragmentManager = supportFragmentManager
            val fragmentTransaction = fragmentManager.beginTransaction()
            fragmentTransaction.remove(fragmentOne)
            fragmentTransaction.commit()
        }

Activity에 데이터 담아서 넣어주려면 bundle만들어서 Activity에 bundle을 장착해야한다. 

val fragmentOne : FragmentOne = FragmentOne()
        //프라그먼트에 data를 넣어주는 방법
        var bundle : Bundle = Bundle()
        bundle.putString("hello","hello")
        fragmentOne.arguments = bundle

Fragment -> Activity : 자체구현 (리스너 구현)>

dataPassListener = context as OnDataPassListener

형변환을 해줌

 

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        Log.d("life_cycle","F onViewCreated")

        pass.setOnClickListener {
            dataPassListener.onDataPass("Good Bye")
        }
        
        super.onViewCreated(view, savedInstanceState)
    }

 리스너 장착한것. 

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_fragment)
        Log.d("life_cycle","onCreate")

        val fragmentOne : FragmentOne = FragmentOne()
        //프라그먼트에 data를 넣어주는 방법
        var bundle : Bundle = Bundle()
        bundle.putString("hello","hello")
        fragmentOne.arguments = bundle

 

 

 

우리가 만들어준 리스너

당장 이니셜라이즈 하는것을 늦추기 위해서 lateinit 키워드 넣어줌. 

 

 Activity는 리스너를 항상 OnCreate안에서 했었는데 

Fragment는 리스너를 OnViewCreated에 넣는다. 

dataPassListener.onDataPass("Good Bye"

onDataPassd애를 호출 

 

pass.setOnClickListener {
dataPassListener.onDataPass("Good Bye")

리스너로 데이터를 넣어주는 애

-> 받아주는 애가 있어야함. -> Activity에 장착. 

 

Activity로 가서 리스너 인터페이스  구현해준다. 

class FragmentActivity : AppCompatActivity(), FragmentOne.OnDataPassListener{}

 

interface OnDataPassListener{
fun onDataPass(data: String?)
}

이 내용 없는 함수이기 때문에 반드시 Activity에서 구현 해줘야한다. 

 

dataPassListener = context as OnDataPassListener 형변환

context를 OnDataPassListener로 바꾸겠다는 말  

"abcd".toInt() -> 앞의 스트링을 인트로 

abcd as Int (둘 다 같은거임)

 

버튼 클릭했을 때 리스너가 가진 함수를 울리도록. 

 

val number3 = number1?.plus(number)

number + 쓰지말고 number1?.plus(number)

이렇게 더해주기 

 

val number : Int = 10
val number1 : Int? = null

// val number3 = number? + number1 //: 의 뒤가 비어있으면 타입 추론함.
val number3 = number1?.plus(number)
Log.d("number", "number3 : " +number3)

number1 이 null이기 때문에 

number1?.plus(number) ?의 뒷부분이 실행되지 ㅇ낳아서

number3 : null이 출력됨. 

 

fun plus2(a:Int , b:Int?) : Int{
return b?.plus(a)
}

b가 null이 될 수 있기 때문에 오류가난다. 

 

fun plus2(a:Int , b:Int?) : Int?{
return b?.plus(a)
}

이렇게 해주기 

 

<삼항연산자, 앨비스 연산자>

//null이면 물음표 뒤를 실행.

val number4 = number1 ?:10
//number1 null이면 number4 = 10
//number1 null이 아니면 number4 = number1

null이 아니면 앞에게 들어가고 null이면 뒤에게들어감. 

 

lateCar = Car(10) 나중에 초기화 할거다.. 

그래서 뒤에 lateCar = Car(10)

비추.

 

<!!에 대해서>

val number : Int = 10
val number1 : Int? = 20 //null이 아니면 물음표 뒤를 실행.

val number5 : Int = number1 +10

하면 오류남. number1이 null이 가능한 애이기 때문임/

 

val number5 : Int = number1!!+10

(null이 아니라는것을 보장) 사용하는게 좋지 않음. 

 

<Resource>

textview를 엄청 많이 사용하고 있다고 가정하면 

android:background="@color/textview_color"/>

이렇게 해서 color에서바꿔주면 다 바뀌니까 편리함 

string도 이렇게 등록할 수 있음 .

android:text="@string/hello"

colors와 string은 관리적인 요소에서 편리함.

 

<style name="MyTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">#404040</item>
<item name="colorPrimaryDark">#000000</item>
<item name="colorAccent">@color/colorAccent</item>
</style>

 

이렇게 쓰는거 안좋음.

colors에서 만들어서 쓰는게 좋다. 

<style name="MyTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/mythemeLight</item>
<item name="colorPrimaryDark">@color/mythemeDark</item>
<item name="colorAccent">@color/textview_color</item>
</style>

이렇게.

 

그 후 manifest에서

android:theme="@style/MyTheme">

이렇게 해준다.

 

<item name="windowNoTitle">true</item>

style에서 이거 추가하면 제목이 없어짐. 

 

//1
val ment = resources.getString(R.string.hello)
Log.d("mentt","ment: "+ ment)

//2
val ment2 = getString(R.string.hello)
Log.d("mentt","ment: "+ment2)

val color = getColor(R.color.textview_color)
Log.d("mentt","color : "+ color)

 

엑티비티에서 가져오고 싶으면 이렇게 해주면 된다.

 

button.setBackgroundColor(getColor(R.color.textview_color))

엑티비티에서 불러오면 버튼 색을 바꿀 수 있음.

댓글