QR 코드 스캔시 아래 화면과 같이 커스텀
- 기본 UI에서 세로로 지정하기
세로로 지정하기에 대한 구글링 해보면 아래와 같이 나온다.
( 하지만 이렇게 하는건 비효율적이라고 생각함. 왜 굳이 쓸모없이 액티비티를 만드는건데? )
1. 새로운 액티비티를 만들고
class CustomCaptureActivity : CaptureActivity()
2. 해당 액티비티로 captureActivity를 지정하고
captureActivity = CustomCaptureActivity::class.java
3. 해당 액티비티의 screenOrientation 속성을 portrait 나 fullSensor로 명시
Q. 일단 왜 가로로 나오는가?
- 우리가 사용해야할 CaptureActivity가
<activity
android:name="com.journeyapps.barcodescanner.CaptureActivity"
android:clearTaskOnLaunch="true"
android:screenOrientation="sensorLandscape"
android:stateNotNeeded="true"
android:theme="@style/zxing_CaptureTheme"
android:windowSoftInputMode="stateAlwaysHidden" />
이렇게 되어있기 때문이다. (LandScape)
Q. 그러면 어떻게 해야해?
- 저 라이브러리의 Activity 속성을 변경한다.
<activity
android:name="com.journeyapps.barcodescanner.CaptureActivity"
android:exported="false"
android:screenOrientation="fullSensor"
tools:replace="android:screenOrientation" />
( 원래 기존 정의되어있는 액티비티의 속성을 추가할때는 tools:node="merge"를 사용하면 된다. )
하지만 그렇게 하면 에러가 발생함. 특정 속성이 이미 명시 되어있고 변경할때는 tools:replace를 이용해야 한다.
IntentIntegrator(requireActivity()).apply {
setDesiredBarcodeFormats(IntentIntegrator.QR_CODE)
setBeepEnabled(false)
captureActivity = CaptureActivity::class.java
setBarcodeImageEnabled(true)
initiateScan()
}
-> 그래서 빈 액티비티를 만들 필요가 없다
이제 UI 커스텀을 해보자.
커스텀 하기 위해 CaptureActivity를 상속하지 않고 CaptureActivity의 역할을 하는 Activity 를 생성한다.
( 해당 내용은 CaptureActivity 의 코드와 같다 )
class CustomScanActivity : AppCompatActivity(){
private val barcodeScannerView: DecoratedBarcodeView by lazy { findViewById(R.id.decoratedBarcodeView) }
private val capture: CaptureManager by lazy { CaptureManager(this, barcodeScannerView) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_custom_scanner)
capture.initializeFromIntent(intent, savedInstanceState)
capture.decode()
}
override fun onResume() {
super.onResume()
capture.onResume()
}
override fun onPause() {
super.onPause()
capture.onPause()
}
override fun onDestroy() {
super.onDestroy()
capture.onDestroy()
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
capture.onSaveInstanceState(outState)
}
}
activity_custom_scanner.xml
<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:layout_height="match_parent"
android:background="@color/blue_grey">
<com.journeyapps.barcodescanner.DecoratedBarcodeView
android:id="@+id/decoratedBarcodeView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:zxing_scanner_layout="@layout/merge_custom_barcode" />
// 사각형 점선 역할
<View
android:layout_width="263dp"
android:layout_height="263dp"
android:background="@drawable/bg_stroke_dash"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_qr_code"
style="@style/NotoBold"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:text="QR - CODE"
android:textColor="@color/white"
android:textSize="30sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/cb_flash" />
<TextView
android:id="@+id/tv_guide_scan"
style="@style/NotoBold"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:background="@color/zxing_transparent"
android:gravity="center_horizontal"
android:text="화면에 보이는 코드를 스캔해주세요."
android:textColor="@color/zxing_status_text"
android:textSize="15sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_qr_code" />
</androidx.constraintlayout.widget.ConstraintLayout>
merge_custom_barcode.xml
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
// 렌즈 역할
<com.journeyapps.barcodescanner.BarcodeView
android:id="@+id/zxing_barcode_surface"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:zxing_framing_rect_height="260dp"
app:zxing_framing_rect_width="260dp" />
<com.journeyapps.barcodescanner.ViewfinderView
android:id="@+id/zxing_viewfinder_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:zxing_possible_result_points="@color/zxing_custom_possible_result_points"
app:zxing_result_view="@color/zxing_custom_result_view"
app:zxing_viewfinder_laser="@color/white"
app:zxing_viewfinder_mask="@color/blue_grey" />
</merge>
IntentIntegrator(requireActivity()).apply {
setDesiredBarcodeFormats(IntentIntegrator.QR_CODE)
setBeepEnabled(false)
captureActivity = CustomScanActivity::class.java //CaptureActivity가 아닌 Custom
setBarcodeImageEnabled(true)
initiateScan()
}
디테일 추가 : 플래시 기능 넣기
위의 activity_custom_scanner.xml 에 플래시 아이콘을 추가한다.
<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:layout_height="match_parent"
android:background="@color/blue_grey">
...
<CheckBox
android:id="@+id/cb_flash"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="30dp"
android:button="@null"
android:drawableStart="@drawable/ic_flash_selector"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
...
</androidx.constraintlayout.widget.ConstraintLayout>
TorchListener 추가
class CustomScanActivity : AppCompatActivity(), DecoratedBarcodeView.TorchListener {
private val flash: CheckBox by lazy { findViewById(R.id.cb_flash) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_custom_scanner)
barcodeScannerView.setTorchListener(this)
capture.initializeFromIntent(intent, savedInstanceState)
capture.decode()
flash.setOnCheckedChangeListener { _, isChecked ->
if (isChecked) barcodeScannerView.setTorchOn()
else barcodeScannerView.setTorchOff()
}
}
override fun onTorchOn() {
flash.isChecked = true
}
override fun onTorchOff() {
flash.isChecked = false
}
}
'Android' 카테고리의 다른 글
영상URL에서 샘플 이미지 가져오기 ( 코일 ) (0) | 2023.02.21 |
---|---|
FlowBinding 사용하여 코드 간소화 (0) | 2023.01.11 |
[CI/CD] fastlane : App Distribution + Slack Message (0) | 2022.11.24 |
코루틴 좋아요 동기화 처리 (0) | 2022.11.07 |
build.gradle에 정의한 manifestPlaceholders 값 주입 받기 (0) | 2022.11.05 |