在Fragment中集成ZXingScannerView实现二维码扫描求助
Got it, let's get your QR scanner working in that Drawer Layout Fragment—this is a common pitfall when adapting Activity-based examples to Fragments, so let's break it down step by step.
1. Add ZXing Dependency First
First, make sure you have the right ZXing library in your app-level build.gradle (Module level):
implementation 'com.journeyapps:zxing-android-embedded:4.3.0' // If using AndroidX, include this compatibility dependency (newer versions may handle it automatically) implementation 'androidx.appcompat:appcompat:1.6.1'
Sync your project after adding these lines.
2. Create the Scanner Fragment Layout
Make a simple layout fragment_scanner.xml to hold the scanner view—this keeps your view hierarchy clean:
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/scanner_container" android:layout_width="match_parent" android:layout_height="match_parent"> </FrameLayout>
3. Implement the Scanner Fragment
Here's the full Fragment code, with lifecycle handling, camera permissions, and scan result processing—this fixes the main issues people run into when porting from Activity to Fragment:
import android.Manifest import android.content.pm.PackageManager import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat import androidx.fragment.app.Fragment import com.journeyapps.barcodescanner.BarcodeCallback import com.journeyapps.barcodescanner.BarcodeResult import com.journeyapps.barcodescanner.CompoundBarcodeView class ScannerFragment : Fragment() { private lateinit var barcodeScanner: CompoundBarcodeView private val CAMERA_PERMISSION_REQUEST_CODE = 1001 override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { return inflater.inflate(R.layout.fragment_scanner, container, false) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) // Initialize the scanner view and add it to the fragment's container barcodeScanner = CompoundBarcodeView(requireContext()) view.findViewById<ViewGroup>(R.id.scanner_container).addView(barcodeScanner) // Check camera permission before starting the scanner if (ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED ) { ActivityCompat.requestPermissions( requireActivity(), arrayOf(Manifest.permission.CAMERA), CAMERA_PERMISSION_REQUEST_CODE ) } else { startScanning() } } private fun startScanning() { // Set up callback for when a QR code is scanned barcodeScanner.decodeContinuous(object : BarcodeCallback { override fun barcodeResult(result: BarcodeResult) { // Handle the scanned content here (e.g., send to main activity) val scannedQrText = result.text (activity as MainActivity).handleScannedQrCode(scannedQrText) // Pause scanning after a successful read barcodeScanner.pause() } }) barcodeScanner.resume() // Optional: Lock the drawer so it doesn't interfere with scanning (activity as MainActivity).drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED) } // Handle camera permission request result override fun onRequestPermissionsResult( requestCode: Int, permissions: Array<out String>, grantResults: IntArray ) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) if (requestCode == CAMERA_PERMISSION_REQUEST_CODE) { if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) { startScanning() } else { // Show an error message or prompt the user to enable permission // Toast.makeText(requireContext(), "Camera permission is required to scan QR codes", Toast.LENGTH_SHORT).show() } } } // Bind scanner lifecycle to fragment lifecycle to avoid crashes/leaks override fun onResume() { super.onResume() if (::barcodeScanner.isInitialized) { barcodeScanner.resume() } } override fun onPause() { super.onPause() if (::barcodeScanner.isInitialized) { barcodeScanner.pause() // Unlock the drawer when leaving the scanner fragment (activity as MainActivity).drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED) } } override fun onDestroyView() { super.onDestroyView() if (::barcodeScanner.isInitialized) { barcodeScanner.pauseAndWait() } } }
4. Add the Fragment to Your Drawer Navigation
In your main Activity's drawer item click handler, add code to replace the current Fragment with ScannerFragment:
// Example in MainActivity's onNavigationItemSelected method when (menuItem.itemId) { R.id.nav_scanner -> { supportFragmentManager.beginTransaction() .replace(R.id.nav_host_fragment, ScannerFragment()) .commit() drawerLayout.closeDrawers() } // Handle other drawer items here... }
Common Mistakes to Avoid
- Missing Permission Handling: The scanner will crash immediately if camera permission isn't granted—always check and request permissions first.
- Unbound Lifecycle: Forgetting to call
resume()/pause()on the scanner with the Fragment's lifecycle leads to memory leaks or camera access errors. - Drawer Interference: Locking the drawer during scanning ensures the user doesn't accidentally open it mid-scan, breaking the camera view.
内容的提问来源于stack exchange,提问作者Miguel

