提交 2988f5b0 authored 作者: houziyu's avatar houziyu

Initial commit

上级
.DS_Store
.dart_tool/
.packages
.pub/
build/
# Default ignored files
/shelf/
/workspace.xml
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.dart_tool" />
<excludeFolder url="file://$MODULE_DIR$/.pub" />
<excludeFolder url="file://$MODULE_DIR$/build" />
<excludeFolder url="file://$MODULE_DIR$/example/.dart_tool" />
<excludeFolder url="file://$MODULE_DIR$/example/.pub" />
<excludeFolder url="file://$MODULE_DIR$/example/build" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Dart SDK" level="project" />
<orderEntry type="library" name="Flutter Plugins" level="project" />
</component>
</module>
\ No newline at end of file
<component name="libraryTable">
<library name="Dart SDK">
<CLASSES>
<root url="file://$USER_HOME$/development/flutter/bin/cache/dart-sdk/lib/async" />
<root url="file://$USER_HOME$/development/flutter/bin/cache/dart-sdk/lib/cli" />
<root url="file://$USER_HOME$/development/flutter/bin/cache/dart-sdk/lib/collection" />
<root url="file://$USER_HOME$/development/flutter/bin/cache/dart-sdk/lib/convert" />
<root url="file://$USER_HOME$/development/flutter/bin/cache/dart-sdk/lib/core" />
<root url="file://$USER_HOME$/development/flutter/bin/cache/dart-sdk/lib/developer" />
<root url="file://$USER_HOME$/development/flutter/bin/cache/dart-sdk/lib/ffi" />
<root url="file://$USER_HOME$/development/flutter/bin/cache/dart-sdk/lib/html" />
<root url="file://$USER_HOME$/development/flutter/bin/cache/dart-sdk/lib/indexed_db" />
<root url="file://$USER_HOME$/development/flutter/bin/cache/dart-sdk/lib/io" />
<root url="file://$USER_HOME$/development/flutter/bin/cache/dart-sdk/lib/isolate" />
<root url="file://$USER_HOME$/development/flutter/bin/cache/dart-sdk/lib/js" />
<root url="file://$USER_HOME$/development/flutter/bin/cache/dart-sdk/lib/js_util" />
<root url="file://$USER_HOME$/development/flutter/bin/cache/dart-sdk/lib/math" />
<root url="file://$USER_HOME$/development/flutter/bin/cache/dart-sdk/lib/mirrors" />
<root url="file://$USER_HOME$/development/flutter/bin/cache/dart-sdk/lib/svg" />
<root url="file://$USER_HOME$/development/flutter/bin/cache/dart-sdk/lib/typed_data" />
<root url="file://$USER_HOME$/development/flutter/bin/cache/dart-sdk/lib/web_audio" />
<root url="file://$USER_HOME$/development/flutter/bin/cache/dart-sdk/lib/web_gl" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>
\ No newline at end of file
<component name="libraryTable">
<library name="Flutter Plugins" type="FlutterPluginsLibraryType">
<CLASSES>
<root url="file://$PROJECT_DIR$" />
<root url="file://$USER_HOME$/development/flutter/.pub-cache/hosted/pub.flutter-io.cn/scan-1.6.0" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="FrameworkDetectionExcludesConfiguration">
<type id="android" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/flutter_dong_scan.iml" filepath="$PROJECT_DIR$/.idea/flutter_dong_scan.iml" />
</modules>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>
\ No newline at end of file
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
version:
revision: 0b8abb4724aa590dd0f429683339b1e045a1594d
channel: stable
project_type: plugin
## 0.0.1
* TODO: Describe initial release.
TODO: Add your license here.
# SDScan
#### 前言
***
flutter_dong_scan是一个可以定做UI的二维码扫描库.
参考库如下所示。安卓部分是基于 zxing-android-embedded 这个库,iOS是参考 ZFScan 改造的。
[Android部分:zxing-android-embedded](https://github.com/journeyapps/zxing-android-embedded)
[iOS部分:ZFScan](https://github.com/Zirkfied/ZFScan)
<br>
#### 简单上手
***
首先我们在 **pubspec.yaml** 文件中导入下面内容。然后再执行 **flutter pub get** 命令。
```
dependencies:
flutter_dong_scan: ^最新版本
```
同时,我们需要把项目中build.gradle的minSdkVersion设置为19.
```
android {
...
defaultConfig {
minSdkVersion 19
...
}
}
```
对于iOS部分,由于插件本身有图片资源,所以我们需要改动下我们的 **build System**
具体操作是 打开Xcode,从菜单栏中找到 **File → Workspace Settings** ,然后打开.
然后我们需要把 **build System****Legacy Build System**
然后我们需要在Android的 **AndroidManifest.xml** 和 iOS 的 **info.plist** 添加权限请求, 具体如下所示。
这里要说明一下iOS部分添加权限需要注意的问题,如果你的App想要上线AppStore,我建议你把 “该Demo想使用您的相机” 这句话改为更加详细的阐述,不然挨拒那是必然的。**UIViewControllerBasedStatusBarAppearance** 这个属性为什么要设置,这里我需要说明下,我为UI的统一把状态栏前景色改为白色,所以需要设置这个属性,可以不设置跟随整体主色走。
###### Android 部分
```
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.FLASHLIGHT" />
<uses-permission android:name="android.permission.CAMERA" />
<application>
.....
</application>
</manifest>
```
###### iOS部分
```
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSCameraUsageDescription</key>
<string>该Demo想使用您的相机</string>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
......
</dict>
</plist>
```
上面配置完成之后,我们导入SDScan,如下所示。
```
import 'package:flutter_dong_scan/scan.dart';
```
然后我们就可以如下进行调用了。
```
ScanConfig scanConfig = ScanConfig();
SDScan scan = SDScan().setScanEventListener((dynamic codeString){
print("扫描结果:" + codeString);
});
scan.startScan(config: scanConfig);
```
具体可看博客[SDScan详解博客](https://www.jianshu.com/p/4ec149ad560a)
\ No newline at end of file
*.iml
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures
group 'com.dong.scan'
version '1.0'
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.0'
}
}
rootProject.allprojects {
repositories {
jcenter()
google()
}
}
apply plugin: 'com.android.library'
android {
compileSdkVersion 31
defaultConfig {
minSdkVersion 19
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
lintOptions {
disable 'InvalidPackage'
}
}
dependencies {
implementation 'com.journeyapps:zxing-android-embedded:3.6.0'
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'// 这个版本最小要23
implementation 'androidx.lifecycle:lifecycle-common-java8:2.4.0'
}
org.gradle.jvmargs=-Xmx1536M
android.enableR8=true
android.useAndroidX=true
android.enableJetifier=true
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
rootProject.name = 'scan'
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.dong.scan">
<application>
<activity android:name=".SDScanAvtivity"
android:theme="@style/AppTheme.FullScreen"
></activity>
</application>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.FLASHLIGHT" />
<uses-permission android:name="android.permission.CAMERA" />
</manifest>
\ No newline at end of file
package com.dong.scan;
import android.app.Activity;
import android.util.Log;
import com.journeyapps.barcodescanner.BarcodeResult;
import com.journeyapps.barcodescanner.CaptureManager;
import com.journeyapps.barcodescanner.DecoratedBarcodeView;
public class SDCaptureManager extends CaptureManager {
private Activity activity;
public SDCaptureManager(Activity activity, DecoratedBarcodeView barcodeView) {
super(activity, barcodeView);
this.activity = activity;
}
@Override
protected void returnResult(BarcodeResult rawResult) {
ResultDataManager.getInstance().setBarcodeResult(rawResult);
activity.finish();
}
}
package com.dong.scan;
import android.app.Activity;
import android.content.Intent;
import com.google.zxing.client.android.Intents;
import com.google.zxing.integration.android.IntentIntegrator;
public class SDIntentIntegrator extends IntentIntegrator {
private ScanConfig config;
public SDIntentIntegrator(Activity activity) {
super(activity);
}
@Override
public Intent createScanIntent() {
Intent intent = super.createScanIntent();
if (config != null) {
intent.putExtra("ScanConfig", config);
}
return intent;
}
public IntentIntegrator setScanConfig(ScanConfig config) {
this.config = config;
return this;
}
public ScanConfig getConfig() {
return config;
}
public void setConfig(ScanConfig config) {
this.config = config;
}
}
package com.dong.scan;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.widget.ImageButton;
import android.widget.TextView;
import com.journeyapps.barcodescanner.BarcodeResult;
import com.journeyapps.barcodescanner.CaptureManager;
import com.journeyapps.barcodescanner.DecoratedBarcodeView;
public class SDScanAvtivity extends AppCompatActivity {
private SDCaptureManager captureManager;
private DecoratedBarcodeView barcodeView;
private SDScanFinderView scanFinderView;
private TextView titleView;
private ImageButton exitButton;
private ScanConfig config;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = getIntent();
config = (ScanConfig)intent.getSerializableExtra("ScanConfig");
Log.e("打印",config.title);
setContentView(R.layout.activity_sd_scan_avtivity);
barcodeView = (DecoratedBarcodeView)findViewById(R.id.dbv_custom);
titleView = (TextView)findViewById(R.id.scan_view_title);
titleView.setText(config.title);
scanFinderView = (SDScanFinderView)barcodeView.getViewFinder();
scanFinderView.setConfig(config);
exitButton = (ImageButton)findViewById(R.id.scan_exit_button);
if (config.returnStyle == 0) {
exitButton.setImageResource(R.drawable.sd_scan_exit_icon);
} else {
exitButton.setImageResource(R.drawable.sd_scan_cancle_icon);
}
exitButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
});
captureManager = new SDCaptureManager(this,barcodeView);
captureManager.initializeFromIntent(getIntent(),savedInstanceState);
captureManager.decode();
}
@Override
protected void onResume() {
super.onResume();
captureManager.onResume();
}
@Override
protected void onPause() {
super.onPause();
captureManager.onPause();
}
@Override
protected void onDestroy() {
super.onDestroy();
captureManager.onDestroy();
}
@Override
public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
super.onSaveInstanceState(outState, outPersistentState);
captureManager.onSaveInstanceState(outState);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
captureManager.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
return barcodeView.onKeyDown(keyCode, event) || super.onKeyDown(keyCode, event);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
}
}
package com.dong.scan;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.google.zxing.ResultPoint;
import com.journeyapps.barcodescanner.ViewfinderView;
import java.util.ArrayList;
import java.util.List;
/**
* A simple {@link Fragment} subclass.
* Use the {@link SDScanFinderView} factory method to
* create an instance of this fragment.
*/
public class SDScanFinderView extends ViewfinderView {
/**
* 外部传入的配置项
*/
public ScanConfig config;
/**
* 重绘时间间隔
*/
public static final long CUSTOME_ANIMATION_DELAY = 16;
/* ****************************************** 边角线相关属性 ************************************************/
/**
* "边角线长度/扫描边框长度"的占比 (比例越大,线越长)
*/
public float mLineRate = 10F;
/**
* 边角线厚度 (建议使用dp)
*/
public float mLineDepth = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 4, getResources().getDisplayMetrics());
/**
* 边角线颜色
*/
public int mLineColor = Color.parseColor("#ff4bde2b");
/* ******************************************* 扫描线相关属性 ************************************************/
/**
* 扫描线起始位置
*/
public int mScanLinePosition = 0;
/**
* 扫描线厚度
*/
public float mScanLineDepth = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 4, getResources().getDisplayMetrics());
/**
* 扫描线每次重绘的移动距离
*/
public float mScanLineDy = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 3, getResources().getDisplayMetrics());
/**
* 线性梯度
*/
public LinearGradient mLinearGradient;
/**
* 线性梯度位置
*/
public float[] mPositions = new float[]{0f, 0.5f, 1f};
/**
* 线性梯度各个位置对应的颜色值
*/
public int[] mScanLineColor = new int[]{0x004bde2b, Color.parseColor("#ff4bde2b"), 0x004bde2b};
public SDScanFinderView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setConfig(ScanConfig config) {
this.config = config;
mLineColor = Color.parseColor(config.titeColor);
mScanLineColor = new int[]{Color.parseColor("#00" + config.titeColor.substring(1)), Color.parseColor("#ff" + config.titeColor.substring(1)), Color.parseColor("#00" + config.titeColor.substring(1))};
}
@Override
public void onDraw(Canvas canvas) {
refreshSizes();
if (framingRect == null || cameraPreview.getPreviewFramingRect() == null) {
return;
}
Rect frame = framingRect;
Rect previewFrame = cameraPreview.getPreviewFramingRect();
int width = canvas.getWidth();
int height = canvas.getHeight();
//绘制4个角
paint.setColor(mLineColor); // 定义画笔的颜色
// canvas.drawRect(frame.left, frame.top, frame.left + frame.width() * mLineRate, frame.top + mLineDepth, paint);
// canvas.drawRect(frame.left, frame.top, frame.left + mLineDepth, frame.top + frame.height() * mLineRate, paint);
//
// canvas.drawRect(frame.right - frame.width() * mLineRate, frame.top, frame.right, frame.top + mLineDepth, paint);
// canvas.drawRect(frame.right - mLineDepth, frame.top, frame.right, frame.top + frame.height() * mLineRate, paint);
//
// canvas.drawRect(frame.left, frame.bottom - mLineDepth, frame.left + frame.width() * mLineRate, frame.bottom, paint);
// canvas.drawRect(frame.left, frame.bottom - frame.height() * mLineRate, frame.left + mLineDepth, frame.bottom, paint);
//
// canvas.drawRect(frame.right - frame.width() * mLineRate, frame.bottom - mLineDepth, frame.right, frame.bottom, paint);
// canvas.drawRect(frame.right - mLineDepth, frame.bottom - frame.height() * mLineRate, frame.right, frame.bottom, paint);
//
// // Draw the exterior (i.e. outside the framing rect) darkened
// paint.setColor(resultBitmap != null ? resultColor : maskColor);
// canvas.drawRect(0, 0, width , frame.top , paint);
// canvas.drawRect(0, frame.top, frame.left, frame.bottom + 1, paint);
// canvas.drawRect(frame.right + 1, frame.top, width, frame.bottom + 1, paint);
// canvas.drawRect(0, frame.bottom + 1, width, height, paint);
if (resultBitmap != null) {
// Draw the opaque result bitmap over the scanning rectangle
paint.setAlpha(CURRENT_POINT_OPACITY);
canvas.drawBitmap(resultBitmap, null, frame, paint);
} else {
// 绘制扫描线
mScanLinePosition += mScanLineDy;
if (mScanLinePosition > frame.height()) {
mScanLinePosition = 0;
}
mLinearGradient = new LinearGradient(frame.left, frame.top + mScanLinePosition, frame.right, frame.top + mScanLinePosition, mScanLineColor, mPositions, Shader.TileMode.CLAMP);
paint.setShader(mLinearGradient);
canvas.drawRect(frame.left - 100, frame.top + mScanLinePosition, frame.right, frame.top + mScanLinePosition + mScanLineDepth, paint);
paint.setShader(null);
float scaleX = frame.width() / (float) previewFrame.width();
float scaleY = frame.height() / (float) previewFrame.height();
List<ResultPoint> currentPossible = possibleResultPoints;
List<ResultPoint> currentLast = lastPossibleResultPoints;
int frameLeft = frame.left;
int frameTop = frame.top;
if (currentPossible.isEmpty()) {
lastPossibleResultPoints = null;
} else {
possibleResultPoints = new ArrayList<>(5);
lastPossibleResultPoints = currentPossible;
paint.setAlpha(CURRENT_POINT_OPACITY);
paint.setColor(resultPointColor);
for (ResultPoint point : currentPossible) {
canvas.drawCircle(frameLeft + (int) (point.getX() * scaleX),
frameTop + (int) (point.getY() * scaleY),
POINT_SIZE, paint);
}
}
if (currentLast != null) {
paint.setAlpha(CURRENT_POINT_OPACITY / 2);
paint.setColor(resultPointColor);
float radius = POINT_SIZE / 2.0f;
for (ResultPoint point : currentLast) {
canvas.drawCircle(frameLeft + (int) (point.getX() * scaleX),
frameTop + (int) (point.getY() * scaleY),
radius, paint);
}
}
}
// Request another update at the animation interval, but only repaint the laser line,
// not the entire viewfinder mask.
postInvalidateDelayed(CUSTOME_ANIMATION_DELAY,
frame.left,
frame.top,
frame.right,
frame.bottom);
}
}
\ No newline at end of file
package com.dong.scan;
import java.io.Serializable;
public class ScanConfig implements Serializable {
/*格式为#ARGB,默认为 '#4c000000'*/
String maskColor;
/*遮罩框相对比例.默认为宽度的0.68 */
double maskRatio;
/*返回按钮的样式,ReturnStyleExit(值为0) ReturnStyleCancle(值为1)*/
int returnStyle;
/*四个角的主色,默认为'#4bde2b'*/
String titeColor;
/*标题文字,默认为扫一扫*/
String title;
/*底部提示文字,默认为将二维码放入框内,即可自动扫描*/
String hintString;
public String getMaskColor() {
return maskColor;
}
public void setMaskColor(String maskColor) {
this.maskColor = maskColor;
}
public double getMaskRatio() {
return maskRatio;
}
public void setMaskRatio(double maskRatio) {
this.maskRatio = maskRatio;
}
public int getReturnStyle() {
return returnStyle;
}
public void setReturnStyle(int returnStyle) {
this.returnStyle = returnStyle;
}
public String getTiteColor() {
return titeColor;
}
public void setTiteColor(String titeColor) {
this.titeColor = titeColor;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getHintString() {
return hintString;
}
public void setHintString(String hintString) {
this.hintString = hintString;
}
}
package com.dong.scan;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import androidx.annotation.NonNull;
import io.flutter.Log;
import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
import io.flutter.plugin.common.EventChannel;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugin.common.PluginRegistry.Registrar;
import android.app.Activity;
import android.content.IntentFilter;
import com.google.zxing.integration.android.IntentIntegrator;
import com.journeyapps.barcodescanner.BarcodeResult;
import com.journeyapps.barcodescanner.CaptureActivity;
import java.util.HashMap;
import java.util.Map;
/**
* ScanPlugin
*/
public class ScanPlugin implements FlutterPlugin, MethodCallHandler, ActivityAware, SDResultCallBack {
// private static PluginRegistry.Registrar registrar;
private static FlutterPluginBinding flutterPluginBinding;
private static Activity activity;
private static final int REQUEST_CODE_SCAN = 0x0000;
private EventChannel.EventSink eventSink = null;
private EventChannel.StreamHandler streamHandler = new EventChannel.StreamHandler() {
@Override
public void onListen(Object arguments, EventChannel.EventSink events) {
eventSink = events;
}
@Override
public void onCancel(Object arguments) {
eventSink = null;
}
};
@Override
public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
final MethodChannel channel = new MethodChannel(flutterPluginBinding.getFlutterEngine().getDartExecutor(), "scan");
channel.setMethodCallHandler(this);//修改此处为this
if (flutterPluginBinding.getApplicationContext() != null) {
ScanPlugin.flutterPluginBinding = flutterPluginBinding;
}
EventChannel eventChannel = new EventChannel(flutterPluginBinding.getBinaryMessenger(),"scan_event");
eventChannel.setStreamHandler(streamHandler);
}
@Override
public void onAttachedToActivity(ActivityPluginBinding binding) {
this.activity = binding.getActivity();
}
@Override
public void onDetachedFromActivityForConfigChanges() {
}
@Override
public void onReattachedToActivityForConfigChanges(ActivityPluginBinding binding) {
}
@Override
public void onDetachedFromActivity() {
}
public static void registerWith(Registrar registrar) {
final MethodChannel channel = new MethodChannel(registrar.messenger(), "scan");
channel.setMethodCallHandler(new ScanPlugin());
}
public static final String action = "dong.scan.result.action";
@Override
public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
if (call.method.equals("startScan")) {
ScanConfig config = new ScanConfig();
config.maskColor = call.argument("maskColor");
config.maskRatio = call.argument("maskRatio");
config.returnStyle = call.argument("returnStyle");
config.titeColor = call.argument("titeColor");
config.title = call.argument("title");
config.hintString = call.argument("hintString");
ResultDataManager.getInstance().callBack = this;
new SDIntentIntegrator(ScanPlugin.activity)
.setScanConfig(config)
.setCaptureActivity(SDScanAvtivity.class)
.setPrompt(config.hintString)// 设置提示语
.setCameraId(0)// 选择摄像头,可使用前置或者后置
.setBeepEnabled(false)// 是否开启声音,扫完码之后会"哔"的一声
.setBarcodeImageEnabled(false)// 扫完码之后生成二维码的图片
.initiateScan();// 开始扫描
result.success("Android " + android.os.Build.VERSION.RELEASE);
} else {
result.notImplemented();
}
}
@Override
public void returnResultCallBackAction(BarcodeResult rawResult) {
if (eventSink != null) {
eventSink.success(rawResult.toString());
}
}
@Override
public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
}
}
class ResultDataManager {
private static ResultDataManager instance;//恶汉模式,直接先实例化
public BarcodeResult barcodeResult;
public SDResultCallBack callBack;
private ResultDataManager() {
}
public void setBarcodeResult(BarcodeResult barcodeResult) {
this.barcodeResult = barcodeResult;
if (callBack != null) {
callBack.returnResultCallBackAction(barcodeResult);
}
}
public static synchronized ResultDataManager getInstance(){//同步控制,避免多线程的状况多创建了实例对象
if (instance == null){
instance = new ResultDataManager();//在需要的时候在创建
}
return instance;
}
}
interface SDResultCallBack {
public void returnResultCallBackAction(BarcodeResult rawResult);
}
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/btn_back_press" android:state_pressed="true"></item>
<item android:drawable="@drawable/btn_back_normal"></item>
</selector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 选中状态下 -->
<item android:state_pressed="true"><shape android:shape="rectangle">
<corners android:radius="2dp" />
<size android:height="40dp" android:width="120dp" />
<gradient android:angle="90" android:centerColor="#ff000000" android:centerX="50%" android:centerY="50%" android:endColor="#fff0f0f0" android:startColor="#fff0f0f0" />
<stroke android:width="1dp" android:color="#ffffffff" />
</shape></item>
<!-- 正常状态下 -->
<item><shape android:shape="rectangle">
<corners android:radius="2dp" />
<size android:height="40dp" android:width="120dp" />
<gradient android:angle="90" android:centerColor="#ffc5c5c5" android:centerX="50%" android:centerY="50%" android:endColor="#fff0f0f0" android:startColor="#fff0f0f0" />
<stroke android:width="1dp" android:color="#ff646464" />
</shape></item>
</selector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<corners android:radius="2dp" />
<size
android:height="40dp"
android:width="120dp" />
<gradient
android:angle="90"
android:centerColor="#ffc5c5c5"
android:centerX="50%"
android:centerY="50%"
android:endColor="#fff0f0f0"
android:startColor="#fff0f0f0" />
<stroke
android:width="1dp"
android:color="#ff646464" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<corners android:radius="2dp"/>
<stroke android:color="#ff646464"
android:width="1dp"/>
<padding android:left="10dp"
android:right="10dp"
android:top="8dp"
android:bottom="8dp"/>
</shape>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<corners android:radius="2dp"/>
<stroke android:width="1dp"
android:color="#ffc5c5c5"
android:dashWidth="5dp"
android:dashGap="5dp"/>
</shape>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<stroke android:width="1dp"
android:color="#ff646464"
android:dashWidth="5dp"
android:dashGap="5dp"/>
</shape>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical"
tools:context=".SDScanAvtivity">
<com.journeyapps.barcodescanner.DecoratedBarcodeView
android:id="@+id/dbv_custom"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:zxing_scanner_layout="@layout/custom_barcode_scanner"
app:zxing_framing_rect_width="400dp"
app:zxing_framing_rect_height="800dp"
app:zxing_preview_scaling_strategy="fitXY"
tools:ignore="MissingConstraints" />
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.journeyapps.barcodescanner.BarcodeView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/zxing_barcode_surface"
/>
<com.dong.scan.SDScanFinderView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/zxing_viewfinder_view"
/>
<TextView
android:id="@+id/zxing_status_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="240dp"
android:background="@color/zxing_transparent"
android:text="@string/zxing_msg_default_status"
android:textColor="@color/zxing_status_text"
/>
<TextView
android:id="@+id/scan_view_title"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_gravity="top|center_horizontal"
android:layout_marginTop="10dp"
android:background="@color/zxing_transparent"
android:gravity="center"
android:text="扫一扫"
android:textSize="18sp"
android:textColor="@color/zxing_status_text"
/>
<ImageButton
android:id="@+id/scan_exit_button"
android:background="@color/zxing_transparent"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginTop="10dp"
android:layout_marginLeft="10dp"
android:scaleX="0.6"
android:scaleY="0.6"
android:scaleType="fitXY"
android:src="@drawable/sd_scan_exit_icon"
/>
</FrameLayout>
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".SDScanFinderView">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/hello_blank_fragment" />
</FrameLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#6200EE</color>
<color name="colorPrimaryDark">#3700B3</color>
<color name="colorAccent">#03DAC5</color>
<color name="viewfinder_frame">#ff000000</color>
<color name="viewfinder_laser">#ffff0000</color>
<color name="viewfinder_mask">#60000000</color>
<color name="result_view">#b0000000</color>
<color name="corner_color">#ff4bde2b</color>
<color name="possible_result_points">#00000000</color>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- zxing -->
<item type="id" name="auto_focus"/>
<item type="id" name="decode"/>
<item type="id" name="decode_failed"/>
<item type="id" name="decode_succeeded"/>
<item type="id" name="encode_failed"/>
<item type="id" name="encode_succeeded"/>
<item type="id" name="launch_product_query"/>
<item type="id" name="quit"/>
<item type="id" name="restart_preview"/>
<item type="id" name="return_scan_result"/>
<item type="id" name="search_book_contents_failed"/>
<item type="id" name="search_book_contents_succeeded"/>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!--qrcode-->
<string name="str_scan_title">扫一扫</string>
<string name="str_open_light">开启闪光灯</string>
<string name="str_close_light">关闭闪光灯</string>
<string name="str_scan_hint">取景框对准二维码, 即可自动扫描</string>
<!-- TODO: Remove or change this placeholder text -->
<string name="hello_blank_fragment">Hello blank fragment</string>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
<style name="AppTheme.FullScreen" parent="Theme.AppCompat.Light.NoActionBar">
<item name="windowNoTitle">true</item>
<item name="android:windowFullscreen">true</item>
</style>
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
</resources>
\ No newline at end of file
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
# IntelliJ related
*.iml
*.ipr
*.iws
.idea/
# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/
# Flutter/Dart/Pub related
**/doc/api/
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.packages
.pub-cache/
.pub/
/build/
# Web related
lib/generated_plugin_registrant.dart
# Exceptions to above rules.
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
version:
revision: 0b8abb4724aa590dd0f429683339b1e045a1594d
channel: stable
project_type: app
# scan_example
Demonstrates how to use the scan plugin.
## Getting Started
This project is a starting point for a Flutter application.
A few resources to get you started if this is your first Flutter project:
- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab)
- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook)
For help getting started with Flutter, view our
[online documentation](https://flutter.dev/docs), which offers tutorials,
samples, guidance on mobile development, and a full API reference.
gradle-wrapper.jar
/.gradle
/captures/
/gradlew
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
}
def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
apply plugin: 'com.android.application'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
compileSdkVersion 28
lintOptions {
disable 'InvalidPackage'
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.dong.scan_example"
minSdkVersion 19
targetSdkVersion 31
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig signingConfigs.debug
}
}
}
flutter {
source '../..'
}
dependencies {
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
}
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.dong.scan_example">
<!-- Flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.dong.scan_example">
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
calls FlutterMain.startInitialization(this); in its onCreate method.
In most cases you can leave this as-is, but you if you want to provide
additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here. -->
<application
android:name="${applicationName}"
android:label="scan_example"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
</manifest>
package com.dong.scan_example;
import io.flutter.embedding.android.FlutterActivity;
public class MainActivity extends FlutterActivity {
}
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
Flutter draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
</resources>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.dong.scan_example">
<!-- Flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.0'
}
}
allprojects {
repositories {
google()
jcenter()
}
}
rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(':app')
}
task clean(type: Delete) {
delete rootProject.buildDir
}
org.gradle.jvmargs=-Xmx1536M
android.enableR8=true
android.useAndroidX=true
android.enableJetifier=true
#Fri Jun 23 08:50:38 CEST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip
include ':app'
def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
def plugins = new Properties()
def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
if (pluginsFile.exists()) {
pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
}
plugins.each { name, path ->
def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
include ":$name"
project(":$name").projectDir = pluginDirectory
}
*.mode1v3
*.mode2v3
*.moved-aside
*.pbxuser
*.perspectivev3
**/*sync/
.sconsign.dblite
.tags*
**/.vagrant/
**/DerivedData/
Icon?
**/Pods/
**/.symlinks/
profile
xcuserdata
**/.generated/
Flutter/App.framework
Flutter/Flutter.framework
Flutter/Flutter.podspec
Flutter/Generated.xcconfig
Flutter/app.flx
Flutter/app.zip
Flutter/flutter_assets/
Flutter/flutter_export_environment.sh
ServiceDefinitions.json
Runner/GeneratedPluginRegistrant.*
# Exceptions to above rules.
!default.mode1v3
!default.mode2v3
!default.pbxuser
!default.perspectivev3
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>App</string>
<key>CFBundleIdentifier</key>
<string>io.flutter.flutter.app</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>App</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>8.0</string>
</dict>
</plist>
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "Generated.xcconfig"
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Generated.xcconfig"
# Uncomment this line to define a global platform for your project
platform :ios, '8.0'
use_frameworks!
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
project 'Runner', {
'Debug' => :debug,
'Profile' => :release,
'Release' => :release,
}
def parse_KV_file(file, separator='=')
file_abs_path = File.expand_path(file)
if !File.exists? file_abs_path
return [];
end
generated_key_values = {}
skip_line_start_symbols = ["#", "/"]
File.foreach(file_abs_path) do |line|
next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ }
plugin = line.split(pattern=separator)
if plugin.length == 2
podname = plugin[0].strip()
path = plugin[1].strip()
podpath = File.expand_path("#{path}", file_abs_path)
generated_key_values[podname] = podpath
else
puts "Invalid plugin specification: #{line}"
end
end
generated_key_values
end
target 'Runner' do
# Flutter Pod
copied_flutter_dir = File.join(__dir__, 'Flutter')
copied_framework_path = File.join(copied_flutter_dir, 'Flutter.framework')
copied_podspec_path = File.join(copied_flutter_dir, 'Flutter.podspec')
unless File.exist?(copied_framework_path) && File.exist?(copied_podspec_path)
# Copy Flutter.framework and Flutter.podspec to Flutter/ to have something to link against if the xcode backend script has not run yet.
# That script will copy the correct debug/profile/release version of the framework based on the currently selected Xcode configuration.
# CocoaPods will not embed the framework on pod install (before any build phases can generate) if the dylib does not exist.
generated_xcode_build_settings_path = File.join(copied_flutter_dir, 'Generated.xcconfig')
unless File.exist?(generated_xcode_build_settings_path)
raise "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter pub get is executed first"
end
generated_xcode_build_settings = parse_KV_file(generated_xcode_build_settings_path)
cached_framework_dir = generated_xcode_build_settings['FLUTTER_FRAMEWORK_DIR'];
unless File.exist?(copied_framework_path)
FileUtils.cp_r(File.join(cached_framework_dir, 'Flutter.framework'), copied_flutter_dir)
end
unless File.exist?(copied_podspec_path)
FileUtils.cp(File.join(cached_framework_dir, 'Flutter.podspec'), copied_flutter_dir)
end
end
# Keep pod path relative so it can be checked into Podfile.lock.
pod 'Flutter', :path => 'Flutter'
# Plugin Pods
# Prepare symlinks folder. We use symlinks to avoid having Podfile.lock
# referring to absolute paths on developers' machines.
system('rm -rf .symlinks')
system('mkdir -p .symlinks/plugins')
plugin_pods = parse_KV_file('../.flutter-plugins')
plugin_pods.each do |name, path|
symlink = File.join('.symlinks', 'plugins', name)
File.symlink(path, symlink)
pod name, :path => File.join(symlink, 'ios')
end
end
# Prevent Cocoapods from embedding a second Flutter framework and causing an error with the new Xcode build system.
install! 'cocoapods', :disable_input_output_paths => true
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['ENABLE_BITCODE'] = 'NO'
end
end
end
PODS:
- Flutter (1.0.0)
- flutter_dong_scan (0.0.4):
- Flutter
DEPENDENCIES:
- Flutter (from `Flutter`)
- flutter_dong_scan (from `.symlinks/plugins/flutter_dong_scan/ios`)
EXTERNAL SOURCES:
Flutter:
:path: Flutter
flutter_dong_scan:
:path: ".symlinks/plugins/flutter_dong_scan/ios"
SPEC CHECKSUMS:
Flutter: 0e3d915762c693b495b44d77113d4970485de6ec
flutter_dong_scan: 7827f389ef824f9a8390b6e087cc94bf655852fe
PODFILE CHECKSUM: d32a3c6d518bc462b70211f68a03ef2f9ff3416d
COCOAPODS: 1.9.2
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; };
3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; };
9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; };
97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
A9602928445961E144111569 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84EE4E38FBF59E4DD8F9A0E0 /* Pods_Runner.framework */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */,
9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = "<group>"; };
4BFB90C517C1F796F703A7D9 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
6BA5B53365383A0FAB973C61 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
7ADD00FCEFDA222E6B26FDCB /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
84EE4E38FBF59E4DD8F9A0E0 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = "<group>"; };
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
97C146EB1CF9000F007C117D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */,
3B80C3941E831B6300D905FE /* App.framework in Frameworks */,
A9602928445961E144111569 /* Pods_Runner.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
49CE461545D032C6E72CEBE0 /* Frameworks */ = {
isa = PBXGroup;
children = (
84EE4E38FBF59E4DD8F9A0E0 /* Pods_Runner.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup;
children = (
3B80C3931E831B6300D905FE /* App.framework */,
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
9740EEBA1CF902C7004384FC /* Flutter.framework */,
9740EEB21CF90195004384FC /* Debug.xcconfig */,
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
9740EEB31CF90195004384FC /* Generated.xcconfig */,
);
name = Flutter;
sourceTree = "<group>";
};
97C146E51CF9000F007C117D = {
isa = PBXGroup;
children = (
9740EEB11CF90186004384FC /* Flutter */,
97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */,
C80C04F0A8FEED1DC8BC9E11 /* Pods */,
49CE461545D032C6E72CEBE0 /* Frameworks */,
);
sourceTree = "<group>";
};
97C146EF1CF9000F007C117D /* Products */ = {
isa = PBXGroup;
children = (
97C146EE1CF9000F007C117D /* Runner.app */,
);
name = Products;
sourceTree = "<group>";
};
97C146F01CF9000F007C117D /* Runner */ = {
isa = PBXGroup;
children = (
7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */,
7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */,
97C146FA1CF9000F007C117D /* Main.storyboard */,
97C146FD1CF9000F007C117D /* Assets.xcassets */,
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
97C147021CF9000F007C117D /* Info.plist */,
97C146F11CF9000F007C117D /* Supporting Files */,
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
);
path = Runner;
sourceTree = "<group>";
};
97C146F11CF9000F007C117D /* Supporting Files */ = {
isa = PBXGroup;
children = (
97C146F21CF9000F007C117D /* main.m */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
C80C04F0A8FEED1DC8BC9E11 /* Pods */ = {
isa = PBXGroup;
children = (
6BA5B53365383A0FAB973C61 /* Pods-Runner.debug.xcconfig */,
7ADD00FCEFDA222E6B26FDCB /* Pods-Runner.release.xcconfig */,
4BFB90C517C1F796F703A7D9 /* Pods-Runner.profile.xcconfig */,
);
path = Pods;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
97C146ED1CF9000F007C117D /* Runner */ = {
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
0EC2160446975E404085A685 /* [CP] Check Pods Manifest.lock */,
9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
2AEB26D160D65427BDC9C66E /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
dependencies = (
);
name = Runner;
productName = Runner;
productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1020;
ORGANIZATIONNAME = "The Chromium Authors";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
CreatedOnToolsVersion = 7.3.1;
DevelopmentTeam = 76HE6TP5SH;
};
};
};
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 97C146E51CF9000F007C117D;
productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
97C146ED1CF9000F007C117D /* Runner */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
97C146EC1CF9000F007C117D /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
0EC2160446975E404085A685 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
2AEB26D160D65427BDC9C66E /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "[CP] Embed Pods Frameworks";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Thin Binary";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin";
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Run Script";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
97C146EA1CF9000F007C117D /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */,
97C146F31CF9000F007C117D /* main.m in Sources */,
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
97C146FA1CF9000F007C117D /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
97C146FB1CF9000F007C117D /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
97C147001CF9000F007C117D /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
249021D3217E4FDB00AE95B9 /* Profile */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Profile;
};
249021D4217E4FDB00AE95B9 /* Profile */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = 76HE6TP5SH;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
PRODUCT_BUNDLE_IDENTIFIER = com.dong.scanExample;
PRODUCT_NAME = "$(TARGET_NAME)";
VERSIONING_SYSTEM = "apple-generic";
};
name = Profile;
};
97C147031CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
97C147041CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
97C147061CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = 76HE6TP5SH;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
PRODUCT_BUNDLE_IDENTIFIER = com.dong.scanExample;
PRODUCT_NAME = "$(TARGET_NAME)";
VERSIONING_SYSTEM = "apple-generic";
};
name = Debug;
};
97C147071CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = 76HE6TP5SH;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
PRODUCT_BUNDLE_IDENTIFIER = com.dong.scanExample;
PRODUCT_NAME = "$(TARGET_NAME)";
VERSIONING_SYSTEM = "apple-generic";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
97C147031CF9000F007C117D /* Debug */,
97C147041CF9000F007C117D /* Release */,
249021D3217E4FDB00AE95B9 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
97C147061CF9000F007C117D /* Debug */,
97C147071CF9000F007C117D /* Release */,
249021D4217E4FDB00AE95B9 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 97C146E61CF9000F007C117D /* Project object */;
}
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:Runner.xcodeproj">
</FileRef>
</Workspace>
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1020"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Profile"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:Runner.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>
#import <Flutter/Flutter.h>
#import <UIKit/UIKit.h>
@interface AppDelegate : FlutterAppDelegate
@end
#import "AppDelegate.h"
#import "GeneratedPluginRegistrant.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[GeneratedPluginRegistrant registerWithRegistry:self];
// Override point for customization after application launch.
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
@end
{
"images" : [
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@3x.png",
"scale" : "3x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@3x.png",
"scale" : "3x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@3x.png",
"scale" : "3x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@2x.png",
"scale" : "2x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@3x.png",
"scale" : "3x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@1x.png",
"scale" : "1x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@1x.png",
"scale" : "1x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@1x.png",
"scale" : "1x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@2x.png",
"scale" : "2x"
},
{
"size" : "83.5x83.5",
"idiom" : "ipad",
"filename" : "Icon-App-83.5x83.5@2x.png",
"scale" : "2x"
},
{
"size" : "1024x1024",
"idiom" : "ios-marketing",
"filename" : "Icon-App-1024x1024@1x.png",
"scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
{
"images" : [
{
"idiom" : "universal",
"filename" : "LaunchImage.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "LaunchImage@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "LaunchImage@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
# Launch Screen Assets
You can customize the launch screen with your own desired assets by replacing the image files in this directory.
You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Ydg-fD-yQy"/>
<viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4">
</imageView>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/>
</constraints>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
<resources>
<image name="LaunchImage" width="168" height="185"/>
</resources>
</document>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
</dependencies>
<scenes>
<!--Flutter View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
</document>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSCameraUsageDescription</key>
<string>Demo想使用您的相机</string>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>scan_example</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>$(FLUTTER_BUILD_NAME)</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
</dict>
</plist>
#import <Flutter/Flutter.h>
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char* argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
import 'package:flutter/material.dart';
import 'package:flutter_dong_scan/scan.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String _platformVersion = 'Unknown';
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Plugin example app'),
),
body: Center(
child: RaisedButton(
onPressed: () {
ScanConfig scanConfig = ScanConfig();
SDScan scan = SDScan().setScanEventListener((dynamic codeString){
print("扫描结果:" + codeString);
});
scan.startScan(config: scanConfig);
},
child: Text("点击跳转"),
),
),
),
);
}
}
name: scan_example
description: Demonstrates how to use the scan plugin.
publish_to: 'none'
environment:
sdk: ">=2.12.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.0
dev_dependencies:
flutter_test:
sdk: flutter
flutter_dong_scan:
path: ../
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
# The following section is specific to Flutter.
flutter:
# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in
# the material Icons class.
uses-material-design: true
# To add assets to your application, add an assets section, like this:
# assets:
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.dev/assets-and-images/#resolution-aware.
# For details regarding adding assets from package dependencies, see
# https://flutter.dev/assets-and-images/#from-packages
# To add custom fonts to your application, add a fonts section here,
# in this "flutter" section. Each entry in this list should have a
# "family" key with the font family name, and a "fonts" key with a
# list giving the asset and other descriptors for the font. For
# example:
# fonts:
# - family: Schyler
# fonts:
# - asset: fonts/Schyler-Regular.ttf
# - asset: fonts/Schyler-Italic.ttf
# style: italic
# - family: Trajan Pro
# fonts:
# - asset: fonts/TrajanPro.ttf
# - asset: fonts/TrajanPro_Bold.ttf
# weight: 700
#
# For details regarding fonts from package dependencies,
# see https://flutter.dev/custom-fonts/#from-packages
.idea/
.vagrant/
.sconsign.dblite
.svn/
.DS_Store
*.swp
profile
DerivedData/
build/
GeneratedPluginRegistrant.h
GeneratedPluginRegistrant.m
.generated/
*.pbxuser
*.mode1v3
*.mode2v3
*.perspectivev3
!default.pbxuser
!default.mode1v3
!default.mode2v3
!default.perspectivev3
xcuserdata
*.moved-aside
*.pyc
*sync/
Icon?
.tags*
/Flutter/Generated.xcconfig
/Flutter/flutter_export_environment.sh
\ No newline at end of file
#import <Flutter/Flutter.h>
@interface MyScanPlugin : NSObject<FlutterPlugin,FlutterStreamHandler>
@end
#import "MyScanPlugin.h"
#import "SDScanViewController.h"
#import <objc/runtime.h>
@interface MyScanPlugin ()
@property(nonatomic,copy)FlutterEventSink eventSink;
@property(nonatomic,strong)FlutterEventChannel *eventChannel;
@end
@implementation MyScanPlugin
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
FlutterMethodChannel* channel = [FlutterMethodChannel
methodChannelWithName:@"scan"
binaryMessenger:[registrar messenger]];
MyScanPlugin* instance = [[MyScanPlugin alloc] init];
[registrar addMethodCallDelegate:instance channel:channel];
instance.eventChannel = [FlutterEventChannel eventChannelWithName:@"scan_event" binaryMessenger:[registrar messenger]];
[instance.eventChannel setStreamHandler:instance];
}
- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
if ([@"startScan" isEqualToString:call.method]) {
NSDictionary *argsDictionary = call.arguments;
SDScanConfig *config = [[SDScanConfig alloc] init];
config.resultBlock = ^(NSString *barCodeString) {
if (self.eventSink != nil) {
self.eventSink(barCodeString);
}
};
[config setValuesForKeysWithDictionary:argsDictionary];
SDScanViewController *scanViewController = [[SDScanViewController alloc] initWithConfig:config];
scanViewController.modalPresentationStyle = UIModalPresentationFullScreen;
[[UIApplication sharedApplication].delegate.window.rootViewController presentViewController:scanViewController animated:YES completion:nil];
UIViewController *controller = [UIViewController new];
controller.view.backgroundColor = [UIColor whiteColor];
result(@"请求成功");
} else {
result(FlutterMethodNotImplemented);
}
}
#pragma mark - 数据流交换层面
- (FlutterError* _Nullable)onListenWithArguments:(id _Nullable)arguments
eventSink:(FlutterEventSink)events {
self.eventSink = events;
return nil;
}
- (FlutterError* _Nullable)onCancelWithArguments:(id _Nullable)arguments {
self.eventSink = nil;
return nil;
}
@end
//
// SDScanConfig.h
// SDScanDemo
//
// Created by 王巍栋 on 2020/7/1.
// Copyright © 2020 骚栋. All rights reserved.
//
#import <UIKit/UIKit.h>
typedef enum : NSUInteger {
ReturnImageTypeExit,
ReturnImageTypeCancle,
} ReturnImageType;
typedef void(^ScanResultBlock)(NSString *barCodeString);
@interface SDScanConfig : NSObject
// SDScanConfig 是扫描配置项
/// 扫描完成的回调
@property(nonatomic,copy)ScanResultBlock resultBlock;
/// 半透明遮罩颜色 默认为0.3透明度#000000
@property(nonatomic,strong)UIColor *maskColor;
/// 遮罩框相对比例.默认为0.68
@property(nonatomic,assign)CGFloat maskRatio;
/// 返回按钮的类型,默认为ReturnImageTypeExit
@property(nonatomic,assign)ReturnImageType returnImageType;
/// 整体主色,会影响四个边角的颜色
@property(nonatomic,copy)NSString *titeColor;
/// 标题文字,默认为扫一扫
@property(nonatomic,strong)NSString *titleString;
/// 底部提示文字,默认为将二维码放入框内,即可自动扫描
@property(nonatomic,strong)NSString *hintString;
@end
//
// SDScanConfig.m
// SDScanDemo
//
// Created by 王巍栋 on 2020/7/1.
// Copyright © 2020 骚栋. All rights reserved.
//
#import "SDScanConfig.h"
#import "UIColor+HexStringColor.h"
@implementation SDScanConfig
- (instancetype)init {
if (self = [super init]) {
_maskRatio = 0.68;
_maskColor = [UIColor hexStringToColor:@"000000" alpha:0.3];
_returnImageType = ReturnImageTypeExit;
_titeColor = nil;
_titleString = @"扫一扫";
_hintString = @"将二维码放入框内,即可自动扫描";
}
return self;
}
- (void)setValue:(id)value forUndefinedKey:(NSString *)key {
}
@end
//
// SDScanHeader.h
// SDScanDemo
//
// Created by 王巍栋 on 2020/6/30.
// Copyright © 2020 骚栋. All rights reserved.
//
#ifndef SDScanHeader_h
#define SDScanHeader_h
#define KNoSafeHeight [UIScreen mainScreen].bounds.size.height
#define KmainWidth [UIScreen mainScreen].bounds.size.width
#define StatusHeight ((KNoSafeHeight == 812 || KNoSafeHeight == 896) ? 44.0f : 20.0f)
#define NavigationBarHeight (44.0f)
#define TabBarHeight (49.0f)
#endif /* SDScanHeader_h */
//
// SDScanMaskView.h
// SDScanDemo
//
// Created by 王巍栋 on 2020/6/29.
// Copyright © 2020 骚栋. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "SDScanConfig.h"
typedef void(^UserClickExitBlock)(void);
@interface SDScanMaskView : UIView
// SDScanMaskView 是扫描遮罩层的视图
- (instancetype)initWithFrame:(CGRect)frame config:(SDScanConfig *)config;
/// 用户点击返回按钮的Block
@property(nonatomic,copy)UserClickExitBlock exitBlock;
@end
//
// SDScanMaskView.m
// SDScanDemo
//
// Created by 王巍栋 on 2020/6/29.
// Copyright © 2020 骚栋. All rights reserved.
//
#import "SDScanMaskView.h"
#import "SDScanHeader.h"
#import "UIView+Extension.h"
#import "UIColor+HexStringColor.h"
@interface SDScanMaskView ()
@property(nonatomic,strong)SDScanConfig *config;
@property(nonatomic,strong)UIView *maskView;
@property(nonatomic,strong)UIButton *exitButton;
@property(nonatomic,strong)UILabel *titleLabel;
@property(nonatomic,strong)UIImageView *scanLineImageView;
@property(nonatomic,strong)UIImageView *topLeftImageView;
@property(nonatomic,strong)UIImageView *topRightImageView;
@property(nonatomic,strong)UIImageView *bottomLeftImageView;
@property(nonatomic,strong)UIImageView *bottomRightImageView;
@property(nonatomic,strong)UILabel *hintLabel;
@property(nonatomic,strong)UIBezierPath *bezier;
@property(nonatomic,strong)CAShapeLayer *shapeLayer;
@end
@implementation SDScanMaskView
- (instancetype)initWithFrame:(CGRect)frame config:(SDScanConfig *)config {
if (self = [super initWithFrame:frame]) {
self.config = config;
[self addSubview:self.maskView];
[self addSubview:self.exitButton];
[self addSubview:self.titleLabel];
[self addSubview:self.topLeftImageView];
[self addSubview:self.topRightImageView];
[self addSubview:self.bottomLeftImageView];
[self addSubview:self.bottomRightImageView];
[self addSubview:self.scanLineImageView];
[self addSubview:self.hintLabel];
[self startScanLineAnimationAction];
}
return self;
}
#pragma mark - 懒加载
- (UIView *)maskView {
if (_maskView == nil) {
_maskView = [[UIView alloc] initWithFrame:self.bounds];
_maskView.backgroundColor = _config.maskColor;
_maskView.layer.mask = self.shapeLayer;
}
return _maskView;
}
- (UIBezierPath *)bezier {
if (_bezier == nil) {
_bezier = [UIBezierPath bezierPathWithRect:self.bounds];
[_bezier appendPath:[[UIBezierPath bezierPathWithRect:CGRectMake(self.centerX - _config.maskRatio * self.width/2.0, self.centerY - _config.maskRatio * self.width/2.0, _config.maskRatio * self.width, _config.maskRatio * self.width)] bezierPathByReversingPath]];
}
return _bezier;
}
- (CAShapeLayer *)shapeLayer {
if (_shapeLayer == nil) {
_shapeLayer = [[CAShapeLayer alloc] init];
_shapeLayer.path = self.bezier.CGPath;
}
return _shapeLayer;
}
- (UIButton *)exitButton {
if (_exitButton == nil) {
_exitButton = [[UIButton alloc] initWithFrame:CGRectMake(0, StatusHeight, NavigationBarHeight, NavigationBarHeight)];
[_exitButton addTarget:self action:@selector(exitButtonAction) forControlEvents:UIControlEventTouchUpInside];
if (_config.returnImageType == ReturnImageTypeExit) {
[_exitButton setImage:[SDScanMaskView getBundleImageName:@"sd_scan_exit_icon@2x"] forState:UIControlStateNormal];
} else {
[_exitButton setImage:[SDScanMaskView getBundleImageName:@"sd_scan_cancle_icon@2x"] forState:UIControlStateNormal];
}
}
return _exitButton;
}
- (UILabel *)titleLabel {
if (_titleLabel == nil) {
_titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(self.exitButton.right, self.exitButton.top, KmainWidth - self.exitButton.width * 2, NavigationBarHeight)];
_titleLabel.textAlignment = NSTextAlignmentCenter;
_titleLabel.font = [UIFont systemFontOfSize:18];
_titleLabel.textColor = [UIColor whiteColor];
_titleLabel.text = _config.titleString;
}
return _titleLabel;
}
- (UIImageView *)scanLineImageView {
if (_scanLineImageView == nil) {
UIImage *scanLineImage = [[SDScanMaskView getBundleImageName:@"sd_scan_line_icon@2x"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
_scanLineImageView = [[UIImageView alloc] initWithImage:scanLineImage];
_scanLineImageView.frame = CGRectMake(self.centerX - _config.maskRatio * scanLineImage.size.width/2.0, self.centerY - _config.maskRatio * self.width/2.0, scanLineImage.size.width, scanLineImage.size.height);
_scanLineImageView.tintColor = [UIColor hexStringToColor:_config.titeColor];
}
return _scanLineImageView;
}
- (UIImageView *)topLeftImageView {
if (_topLeftImageView == nil) {
UIImage *topLeftImage = [[SDScanMaskView getBundleImageName:@"sd_scan_top_left_icon@2x"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
_topLeftImageView = [[UIImageView alloc] initWithImage:topLeftImage];
_topLeftImageView.frame = CGRectMake(self.centerX - _config.maskRatio * self.width/2.0, self.centerY - _config.maskRatio * self.width/2.0, topLeftImage.size.width, topLeftImage.size.height);
_topLeftImageView.tintColor = [UIColor hexStringToColor:_config.titeColor];
}
return _topLeftImageView;
}
- (UIImageView *)topRightImageView {
if (_topRightImageView == nil) {
UIImage *topRightImage = [[SDScanMaskView getBundleImageName:@"sd_scan_top_right_icon@2x"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
_topRightImageView = [[UIImageView alloc] initWithImage:topRightImage];
_topRightImageView.frame = CGRectMake(self.centerX + _config.maskRatio * self.width/2.0 - topRightImage.size.width, self.centerY - _config.maskRatio * self.width/2.0, topRightImage.size.width, topRightImage.size.height);
_topRightImageView.tintColor = [UIColor hexStringToColor:_config.titeColor];
}
return _topRightImageView;
}
- (UIImageView *)bottomLeftImageView {
if (_bottomLeftImageView == nil) {
UIImage *bottomLeftImage = [[SDScanMaskView getBundleImageName:@"sd_scan_bottom_left_icon@2x"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
_bottomLeftImageView = [[UIImageView alloc] initWithImage:bottomLeftImage];
_bottomLeftImageView.frame = CGRectMake(self.centerX - _config.maskRatio * self.width/2.0, self.centerY + _config.maskRatio * self.width/2.0 - bottomLeftImage.size.height, bottomLeftImage.size.width, bottomLeftImage.size.height);
_bottomLeftImageView.tintColor = [UIColor hexStringToColor:_config.titeColor];
}
return _bottomLeftImageView;
}
- (UIImageView *)bottomRightImageView {
if (_bottomRightImageView == nil) {
UIImage *bottomRightImage = [[SDScanMaskView getBundleImageName:@"sd_scan_bottom_right_icon@2x"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
_bottomRightImageView = [[UIImageView alloc] initWithImage:bottomRightImage];
_bottomRightImageView.frame = CGRectMake(self.centerX + _config.maskRatio * self.width/2.0 - bottomRightImage.size.width, self.centerY + _config.maskRatio * self.width/2.0 - bottomRightImage.size.height, bottomRightImage.size.width, bottomRightImage.size.height);
_bottomRightImageView.tintColor = [UIColor hexStringToColor:_config.titeColor];
}
return _bottomRightImageView;
}
- (UILabel *)hintLabel {
if (_hintLabel == nil) {
_hintLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, self.bottomLeftImageView.bottom + 15.0, KmainWidth, NavigationBarHeight)];
_hintLabel.textAlignment = NSTextAlignmentCenter;
_hintLabel.font = [UIFont systemFontOfSize:12];
_hintLabel.textColor = [UIColor whiteColor];
_hintLabel.text = _config.hintString;
CGSize hintSize = [_hintLabel sizeThatFits:CGSizeMake(KmainWidth * _config.maskRatio, 0)];
_hintLabel.frame = CGRectMake((KmainWidth - hintSize.width)/2.0, self.bottomLeftImageView.bottom + 15.0, hintSize.width, hintSize.height);
}
return _hintLabel;
}
#pragma mark - 相关事件
- (void)setConfig:(SDScanConfig *)config {
_config = config;
self.titleLabel.text = config.titleString;
self.hintLabel.text = config.hintString;
}
- (void)exitButtonAction {
if (self.exitBlock != nil) {
self.exitBlock();
}
}
- (void)startScanLineAnimationAction {
CABasicAnimation * animation = [CABasicAnimation animationWithKeyPath:@"position"];
animation.duration = 3;
animation.fillMode = kCAFillModeForwards;
animation.removedOnCompletion = NO;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
animation.repeatCount = MAXFLOAT;
animation.fromValue = [NSValue valueWithCGPoint:CGPointMake(self.centerX, self.centerY - _config.maskRatio * self.width/2.0)];
animation.toValue = [NSValue valueWithCGPoint:CGPointMake(self.centerX, self.centerY + _config.maskRatio * self.width/2.0)];
[self.scanLineImageView.layer addAnimation:animation forKey:nil];
}
+ (UIImage *)getBundleImageName:(NSString *)imageName {
NSBundle *bundle = [NSBundle bundleForClass:[SDScanMaskView class]];
NSURL *url = [bundle URLForResource:@"SDScanResource" withExtension:@"bundle"];
NSBundle *imageBundle = [NSBundle bundleWithURL:url];
if (imageBundle == nil) {
NSLog(@"获取包失败");
}
if ([UIImage imageWithContentsOfFile:[imageBundle pathForResource:imageName ofType:@"png"]] == nil) {
NSLog(@"获取资源失败");
}
return [UIImage imageWithContentsOfFile:[imageBundle pathForResource:imageName ofType:@"png"]];
}
@end
//
// SDScanViewController.h
// SDScanDemo
//
// Created by 王巍栋 on 2020/6/29.
// Copyright © 2020 骚栋. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "SDScanConfig.h"
@interface SDScanViewController : UIViewController
// SDScanViewController 是扫描的主控制器,返回扫描二维码
- (instancetype)initWithConfig:(SDScanConfig *)scanConfig;
@end
//
// SDScanViewController.m
// SDScanDemo
//
// Created by 王巍栋 on 2020/6/29.
// Copyright © 2020 骚栋. All rights reserved.
//
#import "SDScanViewController.h"
#import <AVFoundation/AVFoundation.h>
#import "SDScanMaskView.h"
#import "SDScanHeader.h"
@interface SDScanViewController ()<AVCaptureMetadataOutputObjectsDelegate>
@property(nonatomic,strong)SDScanConfig *config;
@property(nonatomic,strong)AVCaptureDevice *device;
@property(nonatomic,strong)AVCaptureSession *session;
@property(nonatomic,strong)AVCaptureVideoPreviewLayer *previewLayer;
@property(nonatomic,strong)SDScanMaskView *maskView;
@property(nonatomic,strong)NSMutableArray *metadataObjectTypeArray;
@end
@implementation SDScanViewController
- (instancetype)initWithConfig:(SDScanConfig *)scanConfig {
if (self = [super init]) {
self.config = scanConfig;
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
[self startRunCameraScanAction];
[self.view addSubview:self.maskView];
}
- (UIStatusBarStyle)preferredStatusBarStyle {
return UIStatusBarStyleLightContent;
}
#pragma mark - 懒加载
- (SDScanMaskView *)maskView {
if (_maskView == nil) {
_maskView = [[SDScanMaskView alloc] initWithFrame:self.view.bounds config:self.config];
__weak typeof(self) weakSelf = self;
_maskView.exitBlock = ^{
[weakSelf dismissViewControllerAnimated:YES completion:nil];
};
}
return _maskView;
}
- (NSMutableArray *)metadataObjectTypeArray {
if (_metadataObjectTypeArray == nil) {
_metadataObjectTypeArray = [NSMutableArray arrayWithArray:@[AVMetadataObjectTypeAztecCode,
AVMetadataObjectTypeCode128Code,
AVMetadataObjectTypeCode39Code,
AVMetadataObjectTypeCode39Mod43Code,
AVMetadataObjectTypeCode93Code,
AVMetadataObjectTypeEAN13Code,
AVMetadataObjectTypeEAN8Code,
AVMetadataObjectTypePDF417Code,
AVMetadataObjectTypeQRCode,
AVMetadataObjectTypeUPCECode,
AVMetadataObjectTypeInterleaved2of5Code,
AVMetadataObjectTypeITF14Code,
AVMetadataObjectTypeDataMatrixCode]];
}
return _metadataObjectTypeArray;
}
#pragma mark - 扫描相关
// 开始扫描
- (void)startRunCameraScanAction {
self.device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
AVCaptureDeviceInput * input = [AVCaptureDeviceInput deviceInputWithDevice:self.device error:nil];
AVCaptureMetadataOutput * metadataOutput = [[AVCaptureMetadataOutput alloc] init];
[metadataOutput setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
self.session = [[AVCaptureSession alloc] init];
self.session.sessionPreset = AVCaptureSessionPresetHigh;
[self.session addInput:input];
[self.session addOutput:metadataOutput];
self.previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.session];
self.previewLayer.frame = self.view.bounds;
self.previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
self.previewLayer.backgroundColor = [UIColor yellowColor].CGColor;
[self.view.layer addSublayer:self.previewLayer];
metadataOutput.metadataObjectTypes = [NSArray arrayWithArray:self.metadataObjectTypeArray];
[self.session startRunning];
}
// 扫描结果
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection {
if (metadataObjects.count > 0) {
[self.session stopRunning];
AVMetadataMachineReadableCodeObject * metadataObject = metadataObjects.firstObject;
if (self.config.resultBlock != nil) {
self.config.resultBlock(metadataObject.stringValue);
}
[self dismissViewControllerAnimated:YES completion:nil];
}
}
@end
//
// UIColor+HexStringColor.h
// ChildMusicTeacher
//
// Created by bnqc on 2018/12/7.
// Copyright © 2018年 Dong. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface UIColor (HexStringColor)
// HexStringColor 是16进制颜色
+ (UIColor *)hexStringToColor:(NSString *)stringToConvert;
+ (UIColor *)hexStringToColor:(NSString *)stringToConvert alpha:(CGFloat)alpha;
@end
//
// UIColor+HexStringColor.m
// ChildMusicTeacher
//
// Created by bnqc on 2018/12/7.
// Copyright © 2018年 Dong. All rights reserved.
//
#import "UIColor+HexStringColor.h"
@implementation UIColor (HexStringColor)
+ (UIColor *)hexAlphaStringToColor:(NSString *)stringToConvert alpha:(CGFloat)alpha {
NSString *cString = [[stringToConvert
stringByTrimmingCharactersInSet:
[NSCharacterSet whitespaceAndNewlineCharacterSet]] uppercaseString];
// String should be 6 or 8 characters
if ([cString length] < 6)
return [UIColor blackColor];
// strip 0X if it appears
if ([cString hasPrefix:@"0X"])
cString = [cString substringFromIndex:2];
if ([cString hasPrefix:@"#"])
cString = [cString substringFromIndex:1];
if ([cString length] != 6)
return [UIColor blackColor];
// Separate into r, g, b substrings
NSRange range;
range.location = 0;
range.length = 2;
NSString *rString = [cString substringWithRange:range];
range.location = 2;
NSString *gString = [cString substringWithRange:range];
range.location = 4;
NSString *bString = [cString substringWithRange:range];
// Scan values
unsigned int r, g, b;
[[NSScanner scannerWithString:rString] scanHexInt:&r];
[[NSScanner scannerWithString:gString] scanHexInt:&g];
[[NSScanner scannerWithString:bString] scanHexInt:&b];
return [UIColor colorWithRed:((float)r / 255.0f)
green:((float)g / 255.0f)
blue:((float)b / 255.0f)
alpha:alpha];
}
+ (UIColor *)hexStringToColor:(NSString *)stringToConvert {
return [UIColor hexAlphaStringToColor:stringToConvert alpha:1.0f];
}
+ (UIColor *)hexStringToColor:(NSString *)stringToConvert alpha:(CGFloat)alpha {
return [UIColor hexAlphaStringToColor:stringToConvert alpha:alpha];
}
@end
//
// UIView+Extension.h
// SmartLock
//
// Created by 江欣华 on 2016/10/25.
// Copyright © 2016年 工程锁. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface UIView (Extension)
/** 起点x坐标 */
@property (nonatomic,assign)CGFloat x;
/** 起点y坐标 */
@property (nonatomic,assign)CGFloat y;
/** 中心点x坐标 */
@property (nonatomic,assign)CGFloat centerX;
/** 中心点y坐标 */
@property (nonatomic,assign)CGFloat centerY;
/** 宽度 */
@property (nonatomic,assign)CGFloat width;
/** 高度 */
@property (nonatomic,assign)CGFloat height;
/** 顶部 */
@property (nonatomic,assign)CGFloat top;
/** 底部 */
@property (nonatomic,assign)CGFloat bottom;
/** 左边 */
@property (nonatomic,assign)CGFloat left;
/** 右边 */
@property (nonatomic,assign)CGFloat right;
/** size */
@property (nonatomic,assign)CGSize size;
/** origin */
@property (nonatomic,assign)CGPoint origin;
/** 设置圆角 */
- (void)rounded:(CGFloat)cornerRadius;
/** 设置圆角和边框 */
- (void)rounded:(CGFloat)cornerRadius width:(CGFloat)borderWidth color:(UIColor *)borderColor;
/** 设置边框 */
- (void)border:(CGFloat)borderWidth color:(UIColor *)borderColor;
/** 给哪几个角设置圆角 */
- (void)round:(CGFloat)cornerRadius RectCorners:(UIRectCorner)rectCorner;
/** 设置阴影 */
- (void)shadow:(UIColor *)shadowColor opacity:(CGFloat)opacity radius:(CGFloat)radius offset:(CGSize)offset;
- (UIViewController *)viewController;
+ (CGFloat)getLabelHeightByWidth:(CGFloat)width Title:(NSString *)title font:(UIFont *)font;
@end
//
// UIView+Extension.m
// SmartLock
//
// Created by 江欣华 on 2016/10/25.
// Copyright © 2016年 工程锁. All rights reserved.
//
#import "UIView+Extension.h"
@implementation UIView (Extension)
#pragma mark - frame
- (void)setX:(CGFloat)x {
CGRect frame = self.frame;
frame.origin.x = x;
self.frame = frame;
}
- (void)setY:(CGFloat)y {
CGRect frame = self.frame;
frame.origin.y = y;
self.frame = frame;
}
- (CGFloat)x {
return self.frame.origin.x;
}
- (CGFloat)y {
return self.frame.origin.y;
}
- (void)setCenterX:(CGFloat)centerX {
CGPoint center = self.center;
center.x = centerX;
self.center = center;
}
- (CGFloat)centerX {
return self.center.x;
}
- (void)setCenterY:(CGFloat)centerY{
CGPoint center = self.center;
center.y = centerY;
self.center = center;
}
- (CGFloat)centerY {
return self.center.y;
}
- (void)setWidth:(CGFloat)width {
CGRect frame = self.frame;
frame.size.width = width;
self.frame = frame;
}
- (void)setHeight:(CGFloat)height {
CGRect frame = self.frame;
frame.size.height = height;
self.frame = frame;
}
- (CGFloat)height {
return self.frame.size.height;
}
- (CGFloat)width {
return self.frame.size.width;
}
- (void)setSize:(CGSize)size {
CGRect frame = self.frame;
frame.size = size;
self.frame = frame;
}
- (CGSize)size {
return self.frame.size;
}
- (void)setOrigin:(CGPoint)origin {
CGRect frame = self.frame;
frame.origin = origin;
self.frame = frame;
}
- (CGPoint)origin {
return self.frame.origin;
}
- (CGFloat)top {
return self.frame.origin.y;
}
- (void)setTop:(CGFloat)top {
CGRect frame = self.frame;
frame.origin.y = top;
self.frame = frame;
}
- (CGFloat)left {
return self.frame.origin.x;
}
- (void)setLeft:(CGFloat)left {
CGRect frame = self.frame;
frame.origin.x = left;
self.frame = frame;
}
- (CGFloat)bottom {
return self.frame.size.height + self.frame.origin.y;
}
- (void)setBottom:(CGFloat)bottom {
CGRect frame = self.frame;
frame.origin.y = bottom - frame.size.height;
self.frame = frame;
}
- (CGFloat)right {
return self.frame.size.width + self.frame.origin.x;
}
- (void)setRight:(CGFloat)right {
CGRect frame = self.frame;
frame.origin.x = right - frame.size.width;
self.frame = frame;
}
#pragma mark - layer
- (void)rounded:(CGFloat)cornerRadius {
[self rounded:cornerRadius width:0 color:nil];
}
- (void)border:(CGFloat)borderWidth color:(UIColor *)borderColor {
[self rounded:0 width:borderWidth color:borderColor];
}
- (void)rounded:(CGFloat)cornerRadius width:(CGFloat)borderWidth color:(UIColor *)borderColor {
self.layer.cornerRadius = cornerRadius;
self.layer.borderWidth = borderWidth;
self.layer.borderColor = [borderColor CGColor];
self.layer.masksToBounds = YES;
}
- (void)round:(CGFloat)cornerRadius RectCorners:(UIRectCorner)rectCorner {
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:rectCorner cornerRadii:CGSizeMake(cornerRadius, cornerRadius)];
CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
maskLayer.frame = self.bounds;
maskLayer.path = maskPath.CGPath;
self.layer.mask = maskLayer;
}
- (void)shadow:(UIColor *)shadowColor opacity:(CGFloat)opacity radius:(CGFloat)radius offset:(CGSize)offset {
//给Cell设置阴影效果
self.layer.masksToBounds = NO;
self.layer.shadowColor = shadowColor.CGColor;
self.layer.shadowOpacity = opacity;
self.layer.shadowRadius = radius;
self.layer.shadowOffset = offset;
}
#pragma mark - base
- (UIViewController *)viewController {
id nextResponder = [self nextResponder];
while (nextResponder != nil) {
if ([nextResponder isKindOfClass:[UIViewController class]]) {
UIViewController *vc = (UIViewController *)nextResponder;
return vc;
}
nextResponder = [nextResponder nextResponder];
}
return nil;
}
+ (CGFloat)getLabelHeightByWidth:(CGFloat)width Title:(NSString *)title font:(UIFont *)font {
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, width, 0)];
label.text = title;
label.font = font;
label.numberOfLines = 0;
[label sizeToFit];
CGFloat height = label.frame.size.height;
return height;
}
@end
#
# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html.
# Run `pod lib lint scan.podspec' to validate before publishing.
#
Pod::Spec.new do |s|
s.name = 'flutter_dong_scan'
s.version = '0.0.4'
s.summary = 'A new Flutter plugin.'
s.description = <<-DESC
A new Flutter plugin.
DESC
s.homepage = 'http://example.com'
s.license = { :file => '../LICENSE' }
s.author = { 'Your Company' => 'email@example.com' }
s.source = { :path => '.' }
s.source_files = 'Classes/**/*'
s.public_header_files = 'Classes/**/*.h'
s.dependency 'Flutter'
s.platform = :ios, '8.0'
s.resource = 'Resources/SDScanResource.bundle'
# Flutter.framework does not contain a i386 slice. Only x86_64 simulators are supported.
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'VALID_ARCHS[sdk=iphonesimulator*]' => 'x86_64' }
s.swift_version = '5.0'
end
import 'dart:async';
import 'package:flutter/services.dart';
typedef ScanEventListener = dynamic Function(dynamic codeString);
class SDScan {
StreamSubscription<dynamic>? _eventSubscription;
static const MethodChannel _channel = const MethodChannel('scan');
ScanEventListener? scanEventListener;
SDScan() {
initEvent();
}
SDScan setScanEventListener(ScanEventListener scanEventListener) {
this.scanEventListener = scanEventListener;
initEvent();
return this;
}
void initEvent() {
_eventSubscription = _eventChannelFor().receiveBroadcastStream().listen(scanEventListener,onError: scanErrorListener);
}
EventChannel _eventChannelFor() {
return EventChannel('scan_event');
}
void scanErrorListener(Object object) {}
Future<String> startScan({ScanConfig? config}) async {
late ScanConfig scanConfig;
if (config != null) {
scanConfig = config;
}
final String codeString = await _channel.invokeMethod('startScan', <String, dynamic>{
"maskColorAlpha": scanConfig.maskColorAlpha,
"maskRatio": scanConfig.maskRatio,
"returnStyle": scanConfig.returnStyle,
"titeColor": scanConfig.titeColor,
"title": scanConfig.title,
"hintString": scanConfig.hintString,
});
return codeString;
}
}
class ScanConfig {
/*遮罩的透明度,默认为0.3'*/
late double maskColorAlpha;
/*遮罩框相对比例.默认为宽度的0.68 */
late double maskRatio;
/*返回按钮的样式,ReturnStyleExit(值为0) ReturnStyleCancle(值为1)*/
late int returnStyle;
/*四个角的主色,默认为'#4bde2b'*/
late String? titeColor;
/*标题文字,默认为扫一扫*/
late String title;
/*底部提示文字,默认为将二维码放入框内,即可自动扫描*/
late String hintString;
ScanConfig({
this.maskColorAlpha = 0.3,
this.maskRatio = 0.68,
this.returnStyle = 0,
this.titeColor = '#4bde2b',
this.title = '扫一扫',
this.hintString = '扫二维码',
});
}
name: flutter_dong_scan
description: 一个可简单定制UI的二维码扫描插件
version: 1.1.4
homepage: https://github.com/wang82426107/flutter_dong_scan.git
environment:
sdk: ">=2.12.0 <3.0.0"
flutter: ">=1.20.0"
dependencies:
flutter:
sdk: flutter
scan: ^1.6.0
dev_dependencies:
flutter_test:
sdk: flutter
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
# The following section is specific to Flutter.
flutter:
# This section identifies this Flutter project as a plugin project.
# The androidPackage and pluginClass identifiers should not ordinarily
# be modified. They are used by the tooling to maintain consistency when
# adding or updating assets for this project.
plugin:
platforms:
android:
package: com.dong.scan
pluginClass: ScanPlugin
ios:
pluginClass: MyScanPlugin
# To add assets to your plugin package, add an assets section, like this:
# assets:
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
#
# For details regarding assets in packages, see
# https://flutter.dev/assets-and-images/#from-packages
#
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.dev/assets-and-images/#resolution-aware.
# To add custom fonts to your plugin package, add a fonts section here,
# in this "flutter" section. Each entry in this list should have a
# "family" key with the font family name, and a "fonts" key with a
# list giving the asset and other descriptors for the font. For
# example:
# fonts:
# - family: Schyler
# fonts:
# - asset: fonts/Schyler-Regular.ttf
# - asset: fonts/Schyler-Italic.ttf
# style: italic
# - family: Trajan Pro
# fonts:
# - asset: fonts/TrajanPro.ttf
# - asset: fonts/TrajanPro_Bold.ttf
# weight: 700
#
# For details regarding fonts in packages, see
# https://flutter.dev/custom-fonts/#from-packages
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论