zhao zhi 4 лет назад
Родитель
Сommit
6b5125b58c

+ 0 - 63
.gitattributes

@@ -1,63 +0,0 @@
-###############################################################################
-# Set default behavior to automatically normalize line endings.
-###############################################################################
-* text=auto
-
-###############################################################################
-# Set default behavior for command prompt diff.
-#
-# This is need for earlier builds of msysgit that does not have it on by
-# default for csharp files.
-# Note: This is only used by command line
-###############################################################################
-#*.cs     diff=csharp
-
-###############################################################################
-# Set the merge driver for project and solution files
-#
-# Merging from the command prompt will add diff markers to the files if there
-# are conflicts (Merging from VS is not affected by the settings below, in VS
-# the diff markers are never inserted). Diff markers may cause the following 
-# file extensions to fail to load in VS. An alternative would be to treat
-# these files as binary and thus will always conflict and require user
-# intervention with every merge. To do so, just uncomment the entries below
-###############################################################################
-#*.sln       merge=binary
-#*.csproj    merge=binary
-#*.vbproj    merge=binary
-#*.vcxproj   merge=binary
-#*.vcproj    merge=binary
-#*.dbproj    merge=binary
-#*.fsproj    merge=binary
-#*.lsproj    merge=binary
-#*.wixproj   merge=binary
-#*.modelproj merge=binary
-#*.sqlproj   merge=binary
-#*.wwaproj   merge=binary
-
-###############################################################################
-# behavior for image files
-#
-# image files are treated as binary by default.
-###############################################################################
-#*.jpg   binary
-#*.png   binary
-#*.gif   binary
-
-###############################################################################
-# diff behavior for common document formats
-# 
-# Convert binary document formats to text before diffing them. This feature
-# is only available from the command line. Turn it on by uncommenting the 
-# entries below.
-###############################################################################
-#*.doc   diff=astextplain
-#*.DOC   diff=astextplain
-#*.docx  diff=astextplain
-#*.DOCX  diff=astextplain
-#*.dot   diff=astextplain
-#*.DOT   diff=astextplain
-#*.pdf   diff=astextplain
-#*.PDF   diff=astextplain
-#*.rtf   diff=astextplain
-#*.RTF   diff=astextplain

+ 5 - 0
.gitignore

@@ -3,3 +3,8 @@
 ################################################################################
 
 /.vs
+/HiTA.Android/obj
+/HiTA.Android/bin/Debug
+/HiTA.iOS/obj
+/HiTA/bin/Debug/netstandard2.0
+/HiTA/obj

BIN
HiTA.Android/AarBinding.dll


+ 56 - 0
HiTA.Android/AsgI/ScanFragment.cs

@@ -0,0 +1,56 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Threading.Tasks;
+using Android;
+using Android.Content;
+using Android.Content.PM;
+using Android.Graphics;
+using Android.Hardware.Camera2;
+using Android.Hardware.Camera2.Params;
+using Android.OS;
+using Android.Runtime;
+using Android.Views;
+using AndroidX.Core.Content;
+using AndroidX.Fragment.App;
+using Java.Lang;
+using Java.Util.Concurrent;
+using Xamarin.Forms.Platform.Android;
+
+namespace HiTA.Droid.AsgI
+{
+    class ScanFragment: Fragment
+    { 
+        public ScanFragment()
+        {
+
+        }
+
+        public ScanFragment(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
+        {
+
+        }
+
+        public HiTA.Asg.ScanView Element { get; set; }
+
+        public override Android.Views.View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) => inflater.Inflate(Resource.Layout.asg_scan_fragment, null);
+
+        public override void OnViewCreated(Android.Views.View view, Bundle savedInstanceState)
+        {
+            
+            
+        }
+
+        public override void OnPause()
+        {
+            base.OnPause();
+        }
+
+        public override void OnResume()
+        {
+            base.OnResume();
+        }
+    }
+
+}

+ 20 - 0
HiTA.Android/AsgI/ScanNdk.cs

@@ -0,0 +1,20 @@
+using System;
+
+using Javax.Microedition.Khronos.Egl;
+using Javax.Microedition.Khronos.Opengles;
+
+using Android.App;
+using Android.Content;
+using Android.Opengl;
+using Android.OS;
+using Android.Views;
+using System.Runtime.InteropServices;
+using Android.Content.PM;
+
+namespace HiTA.Droid.AsgI
+{
+    public class ScanNdk
+    {
+        
+    }
+}

+ 218 - 0
HiTA.Android/AsgI/ScanViewRenderer.cs

@@ -0,0 +1,218 @@
+using System;
+using System.ComponentModel;
+using AndroidX.Fragment.App;
+using Android.Content;
+using Android.Views;
+using Android.Widget;
+using Xamarin.Forms;
+using Xamarin.Forms.Platform.Android;
+using Xamarin.Forms.Platform.Android.FastRenderers;
+
+[assembly: ExportRenderer(typeof(HiTA.Asg.ScanView), typeof(HiTA.Droid.AsgI.ScanViewRenderer))]
+namespace HiTA.Droid.AsgI
+{
+
+    /**答题卡扫描组件渲染器(android端)**/
+    public class ScanViewRenderer : FrameLayout, IVisualElementRenderer, IViewRenderer
+    {
+
+        int? defaultLabelFor;
+        bool disposed;
+        HiTA.Asg.ScanView element;
+        VisualElementTracker visualElementTracker;
+        VisualElementRenderer visualElementRenderer;
+        FragmentManager fragmentManager;
+        ScanFragment cameraFragment;
+
+        FragmentManager FragmentManager => fragmentManager ??= Context.GetFragmentManager();
+
+        public event EventHandler<VisualElementChangedEventArgs> ElementChanged;
+        public event EventHandler<PropertyChangedEventArgs> ElementPropertyChanged;
+
+        HiTA.Asg.ScanView Element
+        {
+            get => element;
+            set
+            {
+                if (element == value)
+                {
+                    return;
+                }
+
+                var oldElement = element;
+                element = value;
+                OnElementChanged(new ElementChangedEventArgs<HiTA.Asg.ScanView>(oldElement, element));
+            }
+        }
+
+        public ScanViewRenderer(Context context) : base(context)
+        {
+            visualElementRenderer = new VisualElementRenderer(this);
+        }
+
+        void OnElementChanged(ElementChangedEventArgs<HiTA.Asg.ScanView> e)
+        {
+            ScanFragment newFragment = null;
+
+            if (e.OldElement != null)
+            {
+                e.OldElement.PropertyChanged -= OnElementPropertyChanged;
+                cameraFragment.Dispose();
+            }
+            if (e.NewElement != null)
+            {
+                this.EnsureId();
+
+                e.NewElement.PropertyChanged += OnElementPropertyChanged;
+
+                ElevationHelper.SetElevation(this, e.NewElement);
+                newFragment = new ScanFragment { Element = element };
+            }
+
+            FragmentManager.BeginTransaction()
+                .Replace(Id, cameraFragment = newFragment, "camera")
+                .Commit();
+            ElementChanged?.Invoke(this, new VisualElementChangedEventArgs(e.OldElement, e.NewElement));
+        }
+
+        async void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+        {
+            ElementPropertyChanged?.Invoke(this, e);
+
+            switch (e.PropertyName)
+            {
+                case "Width":
+                    //await cameraFragment.RetrieveCameraDevice();
+                    break;
+            }
+        }
+
+        protected override void Dispose(bool disposing)
+        {
+            if (disposed)
+            {
+                return;
+            }
+
+            cameraFragment.Dispose();
+            disposed = true;
+
+            if (disposing)
+            {
+                SetOnClickListener(null);
+                SetOnTouchListener(null);
+
+                if (visualElementTracker != null)
+                {
+                    visualElementTracker.Dispose();
+                    visualElementTracker = null;
+                }
+
+                if (visualElementRenderer != null)
+                {
+                    visualElementRenderer.Dispose();
+                    visualElementRenderer = null;
+                }
+
+                if (Element != null)
+                {
+                    Element.PropertyChanged -= OnElementPropertyChanged;
+
+                    if (Platform.GetRenderer(Element) == this)
+                    {
+                        Platform.SetRenderer(Element, null);
+                    }
+                }
+            }
+
+            base.Dispose(disposing);
+        }
+
+        #region IViewRenderer
+
+        void IViewRenderer.MeasureExactly() => MeasureExactly(this, Element, Context);
+
+        static void MeasureExactly(Android.Views.View control, VisualElement element, Context context)
+        {
+            if (control == null || element == null)
+            {
+                return;
+            }
+
+            double width = element.Width;
+            double height = element.Height;
+
+            if (width <= 0 || height <= 0)
+            {
+                return;
+            }
+
+            int realWidth = (int)context.ToPixels(width);
+            int realHeight = (int)context.ToPixels(height);
+
+            int widthMeasureSpec = MeasureSpecFactory.MakeMeasureSpec(realWidth, MeasureSpecMode.Exactly);
+            int heightMeasureSpec = MeasureSpecFactory.MakeMeasureSpec(realHeight, MeasureSpecMode.Exactly);
+
+            control.Measure(widthMeasureSpec, heightMeasureSpec);
+        }
+
+        #endregion
+
+        #region IVisualElementRenderer
+
+        VisualElement IVisualElementRenderer.Element => Element;
+
+        VisualElementTracker IVisualElementRenderer.Tracker => visualElementTracker;
+
+        ViewGroup IVisualElementRenderer.ViewGroup => null;
+
+        Android.Views.View IVisualElementRenderer.View => this;
+
+        SizeRequest IVisualElementRenderer.GetDesiredSize(int widthConstraint, int heightConstraint)
+        {
+            Measure(widthConstraint, heightConstraint);
+            SizeRequest result = new SizeRequest(new Size(MeasuredWidth, MeasuredHeight), new Size(Context.ToPixels(20), Context.ToPixels(20)));
+            return result;
+        }
+
+        void IVisualElementRenderer.SetElement(VisualElement element)
+        {
+            if (!(element is HiTA.Asg.ScanView camera))
+            {
+                throw new ArgumentException($"{nameof(element)} must be of type {nameof(HiTA.Asg.ScanView)}");
+            }
+
+            if (visualElementTracker == null)
+            {
+                visualElementTracker = new VisualElementTracker(this);
+            }
+            Element = camera;
+        }
+
+        void IVisualElementRenderer.SetLabelFor(int? id)
+        {
+            if (defaultLabelFor == null)
+            {
+                defaultLabelFor = LabelFor;
+            }
+            LabelFor = (int)(id ?? defaultLabelFor);
+        }
+
+        void IVisualElementRenderer.UpdateLayout() => visualElementTracker?.UpdateLayout();
+
+        #endregion
+
+        static class MeasureSpecFactory
+        {
+            public static int GetSize(int measureSpec)
+            {
+                const int modeMask = 0x3 << 30;
+                return measureSpec & ~modeMask;
+            }
+
+            public static int MakeMeasureSpec(int size, MeasureSpecMode mode) => size + (int)mode;
+        }
+    
+
+}
+}

+ 21 - 0
HiTA.Android/HiTA.Android.csproj

@@ -37,6 +37,10 @@
     <EnableLLVM>false</EnableLLVM>
     <AndroidEnableProfiledAot>false</AndroidEnableProfiledAot>
     <BundleAssemblies>false</BundleAssemblies>
+    <Debugger>Xamarin</Debugger>
+    <AndroidUseAapt2>true</AndroidUseAapt2>
+    <EmbedAssembliesIntoApk>false</EmbedAssembliesIntoApk>
+    <AndroidSupportedAbis />
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
     <DebugSymbols>true</DebugSymbols>
@@ -47,6 +51,10 @@
     <WarningLevel>4</WarningLevel>
     <AndroidManagedSymbols>true</AndroidManagedSymbols>
     <AndroidUseSharedRuntime>false</AndroidUseSharedRuntime>
+    <AotAssemblies>false</AotAssemblies>
+    <EnableLLVM>false</EnableLLVM>
+    <AndroidEnableProfiledAot>false</AndroidEnableProfiledAot>
+    <BundleAssemblies>false</BundleAssemblies>
   </PropertyGroup>
   <ItemGroup>
     <Reference Include="Mono.Android" />
@@ -62,6 +70,9 @@
     <PackageReference Include="Xamarin.Essentials" Version="1.6.1" />
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="AsgI\ScanFragment.cs" />
+    <Compile Include="AsgI\ScanNdk.cs" />
+    <Compile Include="AsgI\ScanViewRenderer.cs" />
     <Compile Include="MainActivity.cs" />
     <Compile Include="Resources\Resource.designer.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
@@ -96,5 +107,15 @@
       <Name>HiTA</Name>
     </ProjectReference>
   </ItemGroup>
+  <ItemGroup>
+    <AndroidResource Include="Resources\layout\asg_scan_fragment.xml">
+      <SubType>Designer</SubType>
+    </AndroidResource>
+  </ItemGroup>
   <Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
+  <ProjectExtensions>
+    <VisualStudio>
+      <UserProperties XamarinHotReloadDebuggerTimeoutExceptionHiTAAndroidHideInfoBar="True" />
+    </VisualStudio>
+  </ProjectExtensions>
 </Project>

+ 9 - 0
HiTA.Android/HiTA.Android.csproj.user

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <SelectedDevice>Halove HL2001</SelectedDevice>
+    <ActiveDebugProfile>Halove HL2001</ActiveDebugProfile>
+    <AndroidDesignerPreferredTheme>MainTheme</AndroidDesignerPreferredTheme>
+    <AndroidDesignerPreferredDevice>Nexus 4</AndroidDesignerPreferredDevice>
+  </PropertyGroup>
+</Project>

Разница между файлами не показана из-за своего большого размера
+ 19447 - 48
HiTA.Android/Resources/Resource.designer.cs


+ 7 - 0
HiTA.Android/Resources/layout/asg_scan_fragment.xml

@@ -0,0 +1,7 @@
+<?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"
+    android:background="#000000">
+
+</FrameLayout>

+ 1 - 0
HiTA.iOS/HiTA.iOS.csproj

@@ -70,6 +70,7 @@
     <Compile Include="AppDelegate.cs" />
     <None Include="Entitlements.plist" />
     <None Include="Info.plist" />
+    <Compile Include="MainActivity.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
   </ItemGroup>
   <ItemGroup>

+ 28 - 0
HiTA.iOS/MainActivity.cs

@@ -0,0 +1,28 @@
+using System;
+
+using Android.App;
+using Android.Content.PM;
+using Android.Runtime;
+using Android.OS;
+
+namespace HiTA.Droid
+{
+    [Activity(Label = "HiTA", Icon = "@mipmap/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize )]
+    public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
+    {
+        protected override void OnCreate(Bundle savedInstanceState)
+        {
+            base.OnCreate(savedInstanceState);
+
+            Xamarin.Essentials.Platform.Init(this, savedInstanceState);
+            global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
+            LoadApplication(new App());
+        }
+        public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
+        {
+            Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
+
+            base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
+        }
+    }
+}

+ 56 - 0
HiTA.sln

@@ -12,67 +12,123 @@ EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
+		Debug|ARM = Debug|ARM
+		Debug|ARM64 = Debug|ARM64
 		Debug|iPhone = Debug|iPhone
 		Debug|iPhoneSimulator = Debug|iPhoneSimulator
+		Debug|x64 = Debug|x64
+		Debug|x86 = Debug|x86
 		Release|Any CPU = Release|Any CPU
+		Release|ARM = Release|ARM
+		Release|ARM64 = Release|ARM64
 		Release|iPhone = Release|iPhone
 		Release|iPhoneSimulator = Release|iPhoneSimulator
+		Release|x64 = Release|x64
+		Release|x86 = Release|x86
 	EndGlobalSection
 	GlobalSection(ProjectConfigurationPlatforms) = postSolution
 		{35B3EBB9-6BBF-4478-8245-DA7189B55386}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{35B3EBB9-6BBF-4478-8245-DA7189B55386}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{35B3EBB9-6BBF-4478-8245-DA7189B55386}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
+		{35B3EBB9-6BBF-4478-8245-DA7189B55386}.Debug|ARM.ActiveCfg = Debug|Any CPU
+		{35B3EBB9-6BBF-4478-8245-DA7189B55386}.Debug|ARM.Build.0 = Debug|Any CPU
+		{35B3EBB9-6BBF-4478-8245-DA7189B55386}.Debug|ARM.Deploy.0 = Debug|Any CPU
+		{35B3EBB9-6BBF-4478-8245-DA7189B55386}.Debug|ARM64.ActiveCfg = Debug|Any CPU
+		{35B3EBB9-6BBF-4478-8245-DA7189B55386}.Debug|ARM64.Build.0 = Debug|Any CPU
+		{35B3EBB9-6BBF-4478-8245-DA7189B55386}.Debug|ARM64.Deploy.0 = Debug|Any CPU
 		{35B3EBB9-6BBF-4478-8245-DA7189B55386}.Debug|iPhone.ActiveCfg = Debug|Any CPU
 		{35B3EBB9-6BBF-4478-8245-DA7189B55386}.Debug|iPhone.Build.0 = Debug|Any CPU
 		{35B3EBB9-6BBF-4478-8245-DA7189B55386}.Debug|iPhone.Deploy.0 = Debug|Any CPU
 		{35B3EBB9-6BBF-4478-8245-DA7189B55386}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
 		{35B3EBB9-6BBF-4478-8245-DA7189B55386}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
 		{35B3EBB9-6BBF-4478-8245-DA7189B55386}.Debug|iPhoneSimulator.Deploy.0 = Debug|Any CPU
+		{35B3EBB9-6BBF-4478-8245-DA7189B55386}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{35B3EBB9-6BBF-4478-8245-DA7189B55386}.Debug|x64.Build.0 = Debug|Any CPU
+		{35B3EBB9-6BBF-4478-8245-DA7189B55386}.Debug|x64.Deploy.0 = Debug|Any CPU
+		{35B3EBB9-6BBF-4478-8245-DA7189B55386}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{35B3EBB9-6BBF-4478-8245-DA7189B55386}.Debug|x86.Build.0 = Debug|Any CPU
+		{35B3EBB9-6BBF-4478-8245-DA7189B55386}.Debug|x86.Deploy.0 = Debug|Any CPU
 		{35B3EBB9-6BBF-4478-8245-DA7189B55386}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{35B3EBB9-6BBF-4478-8245-DA7189B55386}.Release|Any CPU.Build.0 = Release|Any CPU
 		{35B3EBB9-6BBF-4478-8245-DA7189B55386}.Release|Any CPU.Deploy.0 = Release|Any CPU
+		{35B3EBB9-6BBF-4478-8245-DA7189B55386}.Release|ARM.ActiveCfg = Release|Any CPU
+		{35B3EBB9-6BBF-4478-8245-DA7189B55386}.Release|ARM.Build.0 = Release|Any CPU
+		{35B3EBB9-6BBF-4478-8245-DA7189B55386}.Release|ARM.Deploy.0 = Release|Any CPU
+		{35B3EBB9-6BBF-4478-8245-DA7189B55386}.Release|ARM64.ActiveCfg = Release|Any CPU
+		{35B3EBB9-6BBF-4478-8245-DA7189B55386}.Release|ARM64.Build.0 = Release|Any CPU
+		{35B3EBB9-6BBF-4478-8245-DA7189B55386}.Release|ARM64.Deploy.0 = Release|Any CPU
 		{35B3EBB9-6BBF-4478-8245-DA7189B55386}.Release|iPhone.ActiveCfg = Release|Any CPU
 		{35B3EBB9-6BBF-4478-8245-DA7189B55386}.Release|iPhone.Build.0 = Release|Any CPU
 		{35B3EBB9-6BBF-4478-8245-DA7189B55386}.Release|iPhone.Deploy.0 = Release|Any CPU
 		{35B3EBB9-6BBF-4478-8245-DA7189B55386}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
 		{35B3EBB9-6BBF-4478-8245-DA7189B55386}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
 		{35B3EBB9-6BBF-4478-8245-DA7189B55386}.Release|iPhoneSimulator.Deploy.0 = Release|Any CPU
+		{35B3EBB9-6BBF-4478-8245-DA7189B55386}.Release|x64.ActiveCfg = Release|Any CPU
+		{35B3EBB9-6BBF-4478-8245-DA7189B55386}.Release|x64.Build.0 = Release|Any CPU
+		{35B3EBB9-6BBF-4478-8245-DA7189B55386}.Release|x64.Deploy.0 = Release|Any CPU
+		{35B3EBB9-6BBF-4478-8245-DA7189B55386}.Release|x86.ActiveCfg = Release|Any CPU
+		{35B3EBB9-6BBF-4478-8245-DA7189B55386}.Release|x86.Build.0 = Release|Any CPU
+		{35B3EBB9-6BBF-4478-8245-DA7189B55386}.Release|x86.Deploy.0 = Release|Any CPU
 		{DD420EB8-7E35-426D-8247-FDBC6025FA68}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator
 		{DD420EB8-7E35-426D-8247-FDBC6025FA68}.Debug|Any CPU.Build.0 = Debug|iPhoneSimulator
 		{DD420EB8-7E35-426D-8247-FDBC6025FA68}.Debug|Any CPU.Deploy.0 = Debug|iPhoneSimulator
+		{DD420EB8-7E35-426D-8247-FDBC6025FA68}.Debug|ARM.ActiveCfg = Debug|iPhone
+		{DD420EB8-7E35-426D-8247-FDBC6025FA68}.Debug|ARM64.ActiveCfg = Debug|iPhone
 		{DD420EB8-7E35-426D-8247-FDBC6025FA68}.Debug|iPhone.ActiveCfg = Debug|iPhone
 		{DD420EB8-7E35-426D-8247-FDBC6025FA68}.Debug|iPhone.Build.0 = Debug|iPhone
 		{DD420EB8-7E35-426D-8247-FDBC6025FA68}.Debug|iPhone.Deploy.0 = Debug|iPhone
 		{DD420EB8-7E35-426D-8247-FDBC6025FA68}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
 		{DD420EB8-7E35-426D-8247-FDBC6025FA68}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
 		{DD420EB8-7E35-426D-8247-FDBC6025FA68}.Debug|iPhoneSimulator.Deploy.0 = Debug|iPhoneSimulator
+		{DD420EB8-7E35-426D-8247-FDBC6025FA68}.Debug|x64.ActiveCfg = Debug|iPhone
+		{DD420EB8-7E35-426D-8247-FDBC6025FA68}.Debug|x86.ActiveCfg = Debug|iPhone
 		{DD420EB8-7E35-426D-8247-FDBC6025FA68}.Release|Any CPU.ActiveCfg = Release|iPhoneSimulator
 		{DD420EB8-7E35-426D-8247-FDBC6025FA68}.Release|Any CPU.Build.0 = Release|iPhoneSimulator
 		{DD420EB8-7E35-426D-8247-FDBC6025FA68}.Release|Any CPU.Deploy.0 = Release|iPhoneSimulator
+		{DD420EB8-7E35-426D-8247-FDBC6025FA68}.Release|ARM.ActiveCfg = Release|iPhone
+		{DD420EB8-7E35-426D-8247-FDBC6025FA68}.Release|ARM64.ActiveCfg = Release|iPhone
 		{DD420EB8-7E35-426D-8247-FDBC6025FA68}.Release|iPhone.ActiveCfg = Release|iPhone
 		{DD420EB8-7E35-426D-8247-FDBC6025FA68}.Release|iPhone.Build.0 = Release|iPhone
 		{DD420EB8-7E35-426D-8247-FDBC6025FA68}.Release|iPhone.Deploy.0 = Release|iPhone
 		{DD420EB8-7E35-426D-8247-FDBC6025FA68}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
 		{DD420EB8-7E35-426D-8247-FDBC6025FA68}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
 		{DD420EB8-7E35-426D-8247-FDBC6025FA68}.Release|iPhoneSimulator.Deploy.0 = Release|iPhoneSimulator
+		{DD420EB8-7E35-426D-8247-FDBC6025FA68}.Release|x64.ActiveCfg = Release|iPhone
+		{DD420EB8-7E35-426D-8247-FDBC6025FA68}.Release|x86.ActiveCfg = Release|iPhone
 		{80E56974-9E79-4225-B45F-CE8FBE1822C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{80E56974-9E79-4225-B45F-CE8FBE1822C1}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{80E56974-9E79-4225-B45F-CE8FBE1822C1}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
+		{80E56974-9E79-4225-B45F-CE8FBE1822C1}.Debug|ARM.ActiveCfg = Debug|Any CPU
+		{80E56974-9E79-4225-B45F-CE8FBE1822C1}.Debug|ARM.Build.0 = Debug|Any CPU
+		{80E56974-9E79-4225-B45F-CE8FBE1822C1}.Debug|ARM64.ActiveCfg = Debug|Any CPU
+		{80E56974-9E79-4225-B45F-CE8FBE1822C1}.Debug|ARM64.Build.0 = Debug|Any CPU
 		{80E56974-9E79-4225-B45F-CE8FBE1822C1}.Debug|iPhone.ActiveCfg = Debug|Any CPU
 		{80E56974-9E79-4225-B45F-CE8FBE1822C1}.Debug|iPhone.Build.0 = Debug|Any CPU
 		{80E56974-9E79-4225-B45F-CE8FBE1822C1}.Debug|iPhone.Deploy.0 = Debug|Any CPU
 		{80E56974-9E79-4225-B45F-CE8FBE1822C1}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
 		{80E56974-9E79-4225-B45F-CE8FBE1822C1}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
 		{80E56974-9E79-4225-B45F-CE8FBE1822C1}.Debug|iPhoneSimulator.Deploy.0 = Debug|Any CPU
+		{80E56974-9E79-4225-B45F-CE8FBE1822C1}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{80E56974-9E79-4225-B45F-CE8FBE1822C1}.Debug|x64.Build.0 = Debug|Any CPU
+		{80E56974-9E79-4225-B45F-CE8FBE1822C1}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{80E56974-9E79-4225-B45F-CE8FBE1822C1}.Debug|x86.Build.0 = Debug|Any CPU
 		{80E56974-9E79-4225-B45F-CE8FBE1822C1}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{80E56974-9E79-4225-B45F-CE8FBE1822C1}.Release|Any CPU.Build.0 = Release|Any CPU
 		{80E56974-9E79-4225-B45F-CE8FBE1822C1}.Release|Any CPU.Deploy.0 = Release|Any CPU
+		{80E56974-9E79-4225-B45F-CE8FBE1822C1}.Release|ARM.ActiveCfg = Release|Any CPU
+		{80E56974-9E79-4225-B45F-CE8FBE1822C1}.Release|ARM.Build.0 = Release|Any CPU
+		{80E56974-9E79-4225-B45F-CE8FBE1822C1}.Release|ARM64.ActiveCfg = Release|Any CPU
+		{80E56974-9E79-4225-B45F-CE8FBE1822C1}.Release|ARM64.Build.0 = Release|Any CPU
 		{80E56974-9E79-4225-B45F-CE8FBE1822C1}.Release|iPhone.ActiveCfg = Release|Any CPU
 		{80E56974-9E79-4225-B45F-CE8FBE1822C1}.Release|iPhone.Build.0 = Release|Any CPU
 		{80E56974-9E79-4225-B45F-CE8FBE1822C1}.Release|iPhone.Deploy.0 = Release|Any CPU
 		{80E56974-9E79-4225-B45F-CE8FBE1822C1}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
 		{80E56974-9E79-4225-B45F-CE8FBE1822C1}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
 		{80E56974-9E79-4225-B45F-CE8FBE1822C1}.Release|iPhoneSimulator.Deploy.0 = Release|Any CPU
+		{80E56974-9E79-4225-B45F-CE8FBE1822C1}.Release|x64.ActiveCfg = Release|Any CPU
+		{80E56974-9E79-4225-B45F-CE8FBE1822C1}.Release|x64.Build.0 = Release|Any CPU
+		{80E56974-9E79-4225-B45F-CE8FBE1822C1}.Release|x86.ActiveCfg = Release|Any CPU
+		{80E56974-9E79-4225-B45F-CE8FBE1822C1}.Release|x86.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE

+ 4 - 0
HiTA/AppShell.xaml

@@ -42,5 +42,9 @@
         <ShellContent Route="LoginPage" ContentTemplate="{DataTemplate local:LoginPage}" />
     </TabBar>
 
+    <FlyoutItem>
+        <ShellContent Route="ScanPage" ContentTemplate="{DataTemplate local:ScanPage}" /> 
+    </FlyoutItem>
+
 
 </Shell>

+ 14 - 0
HiTA/Asg/ScanView.cs

@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Xamarin.Forms;
+
+namespace HiTA.Asg
+{
+
+    /**答题卡扫描组件**/
+    public class ScanView : View
+    {
+    }
+
+}

+ 6 - 0
HiTA/HiTA.csproj

@@ -9,4 +9,10 @@
     <PackageReference Include="Xamarin.Forms" Version="5.0.0.2012" />  
     <PackageReference Include="Xamarin.Essentials" Version="1.6.1" />
   </ItemGroup>
+
+  <ItemGroup>
+    <EmbeddedResource Update="Views\ScanPage.xaml">
+      <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+    </EmbeddedResource>
+  </ItemGroup>
 </Project>

+ 16 - 2
HiTA/ViewModels/AboutViewModel.cs

@@ -1,4 +1,5 @@
-using System;
+using HiTA.Views;
+using System;
 using System.Windows.Input;
 using Xamarin.Essentials;
 using Xamarin.Forms;
@@ -7,12 +8,25 @@ namespace HiTA.ViewModels
 {
     public class AboutViewModel : BaseViewModel
     {
+
+        /**扫描答题卡命令**/
+        public Command ScanAsgCommand { get; }
+
+        public ICommand OpenWebCommand { get; }
+
         public AboutViewModel()
         {
             Title = "About";
             OpenWebCommand = new Command(async () => await Browser.OpenAsync("https://aka.ms/xamarin-quickstart"));
+
+            ScanAsgCommand = new Command(OnScanAsgClick);
+        }
+
+        /**扫描答题卡事件**/
+        private async void OnScanAsgClick(object obj)
+        {
+            await Shell.Current.GoToAsync($"//{nameof(ScanPage)}");
         }
 
-        public ICommand OpenWebCommand { get; }
     }
 }

+ 5 - 0
HiTA/Views/AboutPage.xaml

@@ -45,6 +45,11 @@
                         Command="{Binding OpenWebCommand}"
                         BackgroundColor="{StaticResource Primary}"
                         TextColor="White" />
+
+                <Button Margin="0,10,0,0" Text="扫描成绩卡"
+                        Command="{Binding ScanAsgCommand}"
+                        BackgroundColor="{StaticResource Primary}"
+                        TextColor="White" />
             </StackLayout>
         </ScrollView>
     </Grid>

+ 1 - 0
HiTA/Views/AboutPage.xaml.cs

@@ -11,5 +11,6 @@ namespace HiTA.Views
         {
             InitializeComponent();
         }
+
     }
 }

+ 11 - 0
HiTA/Views/ScanPage.xaml

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+             x:Class="HiTA.Views.ScanPage"
+             xmlns:local="clr-namespace:HiTA.Asg">
+    <ContentPage.Content>
+        <StackLayout>
+            <local:ScanView Margin="20, 20, 20, 20" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"></local:ScanView>
+        </StackLayout>
+    </ContentPage.Content>
+</ContentPage>

+ 20 - 0
HiTA/Views/ScanPage.xaml.cs

@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using Xamarin.Forms;
+using Xamarin.Forms.Xaml;
+
+namespace HiTA.Views
+{
+
+    public partial class ScanPage : ContentPage
+    {
+        public ScanPage()
+        {
+            InitializeComponent();
+        }
+    }
+}