问题描述
我有一个关于从活动到片段的结果/回调的问题。
到目前为止,我有一个片段,它调用相机活动来扫描QR码。因此,我以startActivityForResult
从片段开始活动。如果成功扫描QR码,我将收到Intent
中处理的回调onActivityResult
。
效果很好。
现在,我想处理多个扫描。详细而言,这意味着每次成功扫描都应调用onActivityResult
函数而不关闭活动。我现在遇到的问题是,只有在相机活动中调用onActivityResult
时才会调用finish()
。
所以我的问题是,如何在调用onActivityResult
或不调用finish()
的情况下多次调用class ScanFragment : Fragment() {
private val CHECKIN_CODE = 0
private val CHECKOUT_CODE = 1
companion object {
fun newInstance(): LeadScanFragment = LeadScanFragment()
}
override fun onCreateView(inflater: LayoutInflater,container: ViewGroup?,savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.fragment_lead_scan,container,false)
view.checkin.setOnClickListener {view ->
val intent = Intent(activity,CodeScannerActivity::class.java)
startActivityForResult(intent,CHECKIN_CODE)
}
view.checkout.setOnClickListener {view ->
val intent = Intent(activity,CHECKOUT_CODE)
}
return view
}
override fun onActivityResult(requestCode: Int,resultCode: Int,data: Intent?) {
super.onActivityResult(requestCode,resultCode,data)
if (requestCode == CHECKIN_CODE) {
if (resultCode == Activity.RESULT_OK) {
val returnString = data!!.getStringExtra("hash")
Log.d("scaned in",returnString)
}
}
if (requestCode == CHECKOUT_CODE) {
if (resultCode == Activity.RESULT_OK) {
val returnString = data!!.getStringExtra("hash")
Log.d("scaned out",returnString)
}
}
}
}
而又不关闭活动?还是有另一种方法来处理从活动到片段的回调?
这是我的片段代码:
class CodeScannerActivity : AppCompatActivity() {
private val requestCodeCameraPermission = 1001
private lateinit var cameraSource: CameraSource
private lateinit var detector: BarcodeDetector
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_code_scanner)
if (ContextCompat.checkSelfPermission(this@CodeScannerActivity,Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
askForCameraPermission()
} else {
setup()
}
}
private fun setup() {
detector = BarcodeDetector.Builder(this@CodeScannerActivity).build()
cameraSource = CameraSource.Builder(this@CodeScannerActivity,detector).setAutoFocusEnabled(true).build()
cameraSurfaceView.holder.addCallback(surfaceCallback)
detector.setProcessor(processor)
}
private fun askForCameraPermission() {
ActivityCompat.requestPermissions(this@CodeScannerActivity,arrayOf(Manifest.permission.CAMERA),requestCodeCameraPermission)
}
override fun onRequestPermissionsResult(
requestCode: Int,permissions: Array<out String>,grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode,permissions,grantResults)
if(requestCode == requestCodeCameraPermission && grantResults.isNotEmpty()) {
if(grantResults[0] == PackageManager.PERMISSION_GRANTED) {
setup()
} else {
Toast.makeText(applicationContext,"Permission denied!",Toast.LENGTH_SHORT).show()
}
}
}
private val surfaceCallback = object : SurfaceHolder.Callback {
override fun surfaceCreated(surfaceHolder: SurfaceHolder?) {
try {
cameraSource.start(surfaceHolder)
} catch (exception: Exception) {
Toast.makeText(applicationContext,"Something went wrong",Toast.LENGTH_SHORT).show()
}
}
override fun surfaceChanged(p0: SurfaceHolder?,p1: Int,p2: Int,p3: Int) {
}
override fun surfaceDestroyed(p0: SurfaceHolder?) {
cameraSource.stop()
}
}
private val processor = object : Detector.Processor<Barcode> {
override fun release() {
}
override fun receiveDetections(detections: Detector.Detections<Barcode>?) {
val intent = Intent()
if(detections != null && detections.detectedItems.isNotEmpty()) {
val qrCodes: SparseArray<Barcode> = detections.detectedItems
val code = qrCodes.valueAt(0)
intent.putExtra("hash",code.displayValue)
setResult(Activity.RESULT_OK,intent)
finish()
} else {
setResult(Activity.RESULT_CANCELED,intent)
finish()
}
}
}
}
这是相机活动代码:
receiveDetections
摄像机活动代码下部processor
内的 onActivityResult
是将回调Intent发送回import React from 'react';
import SetTimer from './components/SetTimer';
import './App.css';
class App extends React.Component {
state = {
breakCount: 5,sessionCount: 25,clockCount: 25 * 60,currentTimer: 'Session',isPlaying: false,};
constructor(props) {
super(props);
this.loop = undefined;
this.handlePlayPause = this.handlePlayPause.bind(this);
}
componentWillUnmount() {
clearInterval(this.loop);
}
handlePlayPause() {
const { isPlaying } = this.state;
console.log(isPlaying);
if (isPlaying) {
//if the time is playing and we press this button,then we need to puase or clear the playing intervals
clearInterval(this.loop);
this.setState({ isPlaying: false });
} else {
this.setState({ isPlaying: true });
this.loop = setInterval(() => {
const {
clockCount,breakCount,sessionCount,currentTimer,} = this.state;
if (clockCount === 0) {
this.setState({
currentTimer: currentTimer === 'Session' ? 'Break' : 'Session',clockCount:
currentTimer === 'Session' ? breakCount * 60 : sessionCount * 60,});
} else {
this.setState({ clockCount: clockCount - 1 });
}
},1000);
}
}
handleReset = () => {
this.setState({
breakCount: 5,});
clearInterval(this.loop);
};
convertTime = (count) => {
const minutes = Math.floor(count / 60);
let seconds = count % 60;
seconds = seconds < 10 ? `0${seconds}` : `${seconds}`;
return `${minutes}:${seconds}`;
};
handleBreakDecrease = () => {
const { breakCount } = this.state;
if (breakCount >= 2) {
this.setState({ breakCount: breakCount - 1 });
}
};
handleBreakIncrease = () => {
const { breakCount } = this.state;
this.setState({ breakCount: breakCount + 1 });
};
handleSessionDecrease = () => {
const { sessionCount } = this.state;
if (sessionCount >= 2) {
this.setState({
sessionCount: sessionCount - 1,clockCount: (sessionCount - 1) * 60,});
}
};
handleSessionIncrease = () => {
const { sessionCount } = this.state;
this.setState({
sessionCount: sessionCount + 1,});
};
render() {
const { breakCount,clockCount,currentTimer } = this.state;
const breakProps = {
title: 'Break Length',count: breakCount,handleDecrease: this.handleBreakDecrease,handleIncrease: this.handleBreakIncrease,};
const sessionProps = {
title: 'Session Length',count: sessionCount,handleDecrease: this.handleSessionDecrease,handleIncrease: this.handleSessionIncrease,};
return (
<div>
<div className='flex'>
<SetTimer {...breakProps} />
<SetTimer {...sessionProps} />
</div>
<div className='clock-container'>
<h1>{currentTimer}</h1>
<span>{this.convertTime(clockCount)}</span>
<div className='flex'>
<button onClick={this.handlePlayPause}>
{this.state.isPlaying ? (
<i className={`fas fa-pause`}></i>
) : (
<i className='fas fa-play'></i>
)}
</button>
<button onClick={this.handleReset}>
<i className='fas fa-sync-alt'></i>
</button>
</div>
</div>
</div>
);
}
}
export default App;
的地方。
解决方法
您可以让扫描器Activity
发送本地广播Intent
,以将“结果”转发给呼叫方Fragment
。 Fragment
(或其托管Activity
)应设置一个侦听器以侦听广播的“结果”。这样,您可以执行多次扫描并将每个结果发送回基础Activity
。