1. Permission 추가
// AndroidManifest.xml
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
2. xml
- TouchIamgeView에 대한 설명은 (https://kldaji.tistory.com/3) 해당 링크를 참조하자.
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/get_image_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<com.ortiz.touchview.TouchImageView
android:id="@+id/touch_image"
android:layout_width="400dp"
android:layout_height="400dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/get_image_button"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
3. fragment에 함수 추가
- $표시 붙은 부분은 사용자가 사용하는 이름으로 변경해주면 된다.
class $FragmentName : Fragment() {
// const
private val REQUEST_CODE = 100
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// binding
val binding: $FragmentNameBinding = DataBindingUtil.inflate(
inflater, R.layout.$fragment_name, container, false
)
// Get Image Button Click
binding.getImageButton.setOnClickListener {
// Pick Picture From Gallery
openGalleryForImage()
}
return binding.root
}
// Pick Picture From Gallery
private fun openGalleryForImage() {
val intent = Intent(Intent.ACTION_PICK)
intent.type = "image/*"
startActivityForResult(intent, REQUEST_CODE)
}
// Pick Picture From Gallery
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == Activity.RESULT_OK && requestCode == REQUEST_CODE){
// Set ImageView
touch_image.setImageURI(data?.data)
}
}
}
4. 갤러리에서 가져온 사진을 터치하면 새로운 Activity에 full screen 이미지로 나오게 하기.
<번외편>
(https://developer.android.com/training/basics/firstapp/starting-activity) 해당 문서를 참고하였다.
1) Activity 추가
class $ActivityName : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = $ActivityNameBinding.inflate(layoutInflater)
setContentView(binding.root)
}
}
<?xml version="1.0" encoding="utf-8"?>
<layout 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">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.ortiz.touchview.TouchImageView
android:id="@+id/touch_image"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
2) Intent 추가
class $FragmentName : Fragment() {
// const
private val REQUEST_CODE = 100
// image uri
private var uri: Uri? = null
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// binding
val binding: $FragmentNameBinding = DataBindingUtil.inflate(
inflater, R.layout.$fragment_name, container, false
)
// Get Image Button Click
binding.getImageButton.setOnClickListener {
// Pick Picture From Gallery
openGalleryForImage()
}
// Image Click
binding.iv.setOnClickListener(View.OnClickListener {
sendImage(it)
})
// touch image
if(uri != null){
binding.touchImage.setImageURI(uri)
}
return binding.root
}
// Pick Picture From Gallery
private fun openGalleryForImage() {
val intent = Intent(Intent.ACTION_PICK)
intent.type = "image/*"
startActivityForResult(intent, REQUEST_CODE)
}
// Pick Picture From Gallery
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == Activity.RESULT_OK && requestCode == REQUEST_CODE){
// Set Uri
uri = data?.data!!
// Set ImageView
touch_image.setImageURI(uri)
}
}
// Send Image Uri
private fun sendImage(view: View){
// Intent
val intent = Intent(requireContext(), $ActivityName::class.java).apply {
putExtra("ImageUri", uri.toString())
}
startActivity(intent)
}
}
3) Activity 수정
class $ActivityName : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = $ActivityNameBinding.inflate(layoutInflater)
setContentView(binding.root)
// Get Uri
val uri = intent.getStringExtra("ImageUri")
binding.touchImage.setImageURI(uri.toUri())
}
}
<21.07.08 추가>
※ 그런데 생각해보니까 액티비티를 새로 생성하는 것보다 fragment를 새로 만들어서 navigation을 통해 uri를 전달하도록 하는 것이 더 간단할 것이라는 생각이 들어 새로 구현을 해보았다.
1) fragment 추가
// $newFragmentName
class $newFragmentName : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
// binding
val binding: ${newFragmentName}Binding = DataBindingUtil.inflate(
inflater, R.layout.${newFragmentName}, container, false
)
// argument
val arg = ${newFragmentName}Args.fromBundle(requireArguments())
// 이미지 설정
binding.touchImage.setImageURI(arg.uri.toUri())
return binding.root
}
}
2) 추가한 fragment layout
// $newFragmentName.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<data>
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.ortiz.touchview.TouchImageView
android:id="@+id/touch_image"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
3) navigation 추가
<?xml version="1.0" encoding="utf-8"?>
<navigation
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:id="@+id/navigation"
app:startDestination="@id/$fragmentName">
<fragment
android:id="@+id/$fragmentName"
android:name="${package}.${fragmentName}"
android:label="${fragmentName}"
tools:layout="@layout/${layoutName}" >
<action
android:id="@+id/action_${fragmentName}_to_${newFragmentName}"
app:destination="@id/${newFragmentName}" />
</fragment>
<fragment
android:id="@+id/${newFragmentName}"
android:name="${package}.${newFragmentName}"
android:label="${newFragmentName}" >
<argument
android:name="uri"
app:argType="string" />
</fragment>
</navigation>
4) fragment viewModel Factory
// ${fragmentName}ViewModelFactory
class ${fragmentName}ViewModelFactory(): ViewModelProvider.Factory {
@Suppress("unchecked_cast")
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
if(modelClass.isAssignableFrom(${fragmentName}ViewModel::class.java)){
return ${fragmentName}ViewModel() as T
}
throw IllegalArgumentException("Unknown ViewModel Class")
}
}
5) fragment viewModel
// ${fragmentName}ViewModel
class ${fragmentName}ViewModel() : ViewModel() {
private val _navigateTo${newFragmentName} = MutableLiveData<Boolean>()
val navigateTo${newFragmentName}: LiveData<Boolean>
get() = _navigateTo${newFragmentName}
fun doneNavigating() {
_navigateTo${newFragmentName}.value = null
}
fun goTo${newFragmentName}(){
_navigateTo${newFragmentName}.value = true
}
}
6) fragment 수정
class $FragmentName : Fragment() {
// const
private val REQUEST_CODE = 100
// uri
private var uri: Uri? = null
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// binding
val binding: $FragmentNameBinding = DataBindingUtil.inflate(
inflater, R.layout.$fragment_name, container, false
)
val viewModelFactory = NewClientViewModelFactory(args.clientId, dao)
val viewModel = ViewModelProvider(this, viewModelFactory).get(${fragmentName}ViewModel::class.java)
binding.lifecycleOwner = this
viewModel.navigateTo${newFragmentName}.observe(viewLifecycleOwner, Observer {
if (it == true){
this.findNavController().navigate(${fragmentName}Directions.action${fragmentName}To${newFragmentName}(uri.toString()))
viewModel.doneNavigating()
}
})
// Get Image Button Click
binding.getImageButton.setOnClickListener {
// Pick Picture From Gallery
openGalleryForImage()
}
// Touch Image View Click
binding.touchImage.setOnClickListener(View.OnClickListener {
// set navigate flag true
viewModel.goTo${newFragmentName}()
})
// touch image
if(uri != null){
binding.touchImage.setImageURI(uri)
}
return binding.root
}
// Pick Picture From Gallery
private fun openGalleryForImage() {
val intent = Intent(Intent.ACTION_PICK)
intent.type = "image/*"
startActivityForResult(intent, REQUEST_CODE)
}
// Pick Picture From Gallery
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == Activity.RESULT_OK && requestCode == REQUEST_CODE){
// Gallery Request
// get uri
uri = data?.data!!
// Set ImageView
touch_image.setImageURI(uri)
}
}
}
※ fragment를 통해 이미지를 확대하는 것을 구현할 때, navigation과 viewModel에 대한 코드가 들어가서 길어진 감이 있지만 navigation과 viewModel은 앞으로도 계속 사용할 것이기에 익숙해지는 것을 추천한다.
'Android' 카테고리의 다른 글
Navigation Up Button (0) | 2021.07.08 |
---|---|
Back Button Click Listener (0) | 2021.07.08 |
카메라 촬영 후 이미지뷰로 나타내기 (0) | 2021.07.07 |
[Open Source] 이미지 줌 인/아웃 - TouchImageView (0) | 2021.07.06 |
[Open Source] 이미지 줌 인/아웃 - PhotoView (0) | 2021.07.05 |