include.root.setOnClickListener

하나의 체크박스를 include로 영역을 잡은 후 클릭을 하면 모든 영역에서 클릭이벤트가 발생되어야 하지만 Button이나 ImageButton으로 지정된 View는 클릭이 안되는 문제가 생길 수 있다. 이런 경우에는 해당 Button을 ImageView로 만들어서 전체영역을 클릭할 수 있게 할 수 있다.

문제점

이미지 Metadata의 orientataion rotate값이 0이 아닌 90이나 180 270으로 저장되어 있기 때문에 아이폰에서 올린 사진이 안드로이드에서 90도회전이 된 상태로 보이는 문제가 발생하였다.

해결 방법

ExifInterface를 이용하여 이미지 자체의Metadata의 orientation값을 구한 후 해당 수치만큼 강제로 회전시켜 주었다.

ExifInterface를 이용하면 해당 이미지의 Metadata의 정보를 얻을 수 있다.

  • **EXIF(Exchangeable Image file Format) 메타정보란?사진을 보정한 날짜(Date time), EXIF버전(EXIF Version), 촬영한 날짜(Shoot Date time)촬영프로그램(Exposure Program), 렌즈초점 길이(Focal Length), 조리개수치(F-Number)즉 웹 상에 보이는 사진 파일의 기본 정보를 담고 있다.
  • 셔터스피드(Shutter Speed), 플래시 사용여부 등 세부적인 부가 정보를 기록할 수 있수 있습니다
  • ,웹에 올려진 사진의 실제크기(Image Size), 노출시간(Exposure Time),
  • 데이터와 함께 카메라 제조사(Marker), 카메라모델(Model), 에디터(Soft ware)
//이미지 metaData rotation값 -> 아이폰에서 올린 사진이 90도회전되서 보이는 문제 발생
**var exif : ExifInterface? = null
try{
    exif = ExifInterface(URL(photoList[idx].Url).openConnection().getInputStream())
}catch (e : IOException){
    e.printStackTrace()
}**

val manufacturer = exif?.getAttribute(ExifInterface.TAG_MAKE)
val cameraModel = exif?.getAttribute(ExifInterface.TAG_MODEL)

 **orientation = when (exif?.getAttributeInt(ExifInterface.TAG_ORIENTATION, 0)) {
    ExifInterface.ORIENTATION_ROTATE_90-> 90
    ExifInterface.ORIENTATION_ROTATE_180-> 180
    ExifInterface.ORIENTATION_ROTATE_270-> 270
    else -> 0
}**

val dateTime = exif?.getAttribute(ExifInterface.TAG_DATETIME)
val length = exif?.getAttribute(ExifInterface.TAG_IMAGE_LENGTH)//세로
val width = exif?.getAttribute(ExifInterface.TAG_IMAGE_WIDTH)//가로
 
Glide.with(photoView.context)
    .asBitmap()
    .format(DecodeFormat.PREFER_ARGB_8888)
    .placeholder(R.color.MainBg)
    .override(
        (arrBitmap[idx].width/ 0.1).roundToInt(),
        (arrBitmap[idx].height/ 0.1).roundToInt()
    )
    .load(arrBitmap[idx])
    .error(R.drawable.ic_baseline_image_not_supported_24)
    .transform(CenterInside(), RoundedCorners(4), Rotate(orientation))
    .into(photoView)

Patterns.EMAIL_ADDRESS.matcher(inputEmail).matches()

inputEmail에 입력된 이메일 값을 넣어주면 해당 텍스트가 이메일 형식인지 아닌지 판단해서 true, false값을 내려준다.

이메일 형식인 경우 → true

이메일 형식이 아닌 경우 → false

**Pattern.matches(”정규식”,검사할 텍스트) → 정규식 검사

if (!Patterns.EMAIL_ADDRESS.matcher(binding.shippingEmail.editEmail.text).matches()){
    Toast.makeText(activity, "이메일을 바르게 입력해 주세요.",Toast.LENGTH_SHORT).show()
    return@setOnClickListener
}

 

디지털 이미지를 저장하는 데 쓰이는 이미지 파일 포맷 또는 메모리 저장방식의 한 형태이다.

안드로이드에서 시스템 갤러리 어플리케이션의 사진은 기기의 화면밀도보다 해상도가 훨씬 높다.

메모리가 크지않은 환경에서 해당 이미지로 작업을 하게 되면 상당히 큰 메모리를 사용하기 때문에 효율적이지 않다. 이런 경우에는 해상도를 낮춰서 메모리에 로드하는것이 효율적이다.

(저해상도 버전은 UI구성요소의 크기와 일치해야 한다.)

그렇기 때문에 작게 서브 샘플링한 버전을 메모리에 로드하여 메모리 제한을 초과하지 않고 큰 비트맵을 디코딩하는것이 바람직하다.


비트맵 크기 및 유형값 구하기 (해당 비트맵을 메모리에 로드하지 않고 사이즈 구하는 방법)

val options = BitmapFactory.Options().apply {
    inJustDecodeBounds = true
}
BitmapFactory.decodeResource(resources, R.id.myimage, options)
val imageHeight: Int = options.outHeight
val imageWidth: Int = options.outWidth
val imageType: String = options.outMimeType

해당 이미지를Bitmap으로 만들기위해서는 decodeByteArray(), decodeFile(), decodeResource() 등

의 메서드를 사용하는데 해당 메소드들은 생성된 비트맵에 메모리를 할당하기 때문에 OutOfMemory예외가 발생할 수 있다. 메모리 할당을 방지하는 방법에는 BitmapFcatory.Options Class의 inJustDecodeBounds값을 true로 설정해주는 방법이 있다.


축소 버전을 메모리에 로드

이미지 크기를 알면 전체 이미지를 메모리에 로드할것인지 서브샘플링된 버전을 대신 로드할것인지 결정할 수 있다.

고려해야 하는 요소

  1. 전체 이미지를 메모리에 로드할 때 예상되는 메모리 사용량
  2. 어플리케이션의 다른 메모리 요구사항을 고려하여 해당 이미지를 로드하는데 사용할 수 있는 메모리 용량
  3. 이미지가 로드되는 ImageView또는 UI구성요소의 크기
  4. 현재 기기의 화면 크기 및 밀도

1024x768px의 이미지를 128x96px의 ImageView에 로드 한다면 1024x768px의 이미지를 메모리에 로드하는것은 바람직하지 않다.


inSampleSize

2048x1536px의 해상도를 줄여 더 낮은 px의 비트맵을 생성할 수 있다.

ex)inSampleSize = 4인 경우 2048x1536의 해상도를 512x384의 크기의 비트맵을 생성한다.

12MB의 이미지를 0.75MB의 크기로 줄일 수 있음.

+ Recent posts