2021年1月5日 星期二

Xamarin.Forms 使用 Xamarin.Essentials 媒體選擇器

Xamarin.Forms 使用 Xamarin.Essentials 媒體選擇器

在這篇文章將會逐步說明,如何使用 Xamarin.Essentials 套件提供的 媒體選擇器 功能,幫 Xamarin.Forms 可以製作出可以使用照相機鏡頭的拍照功能。

建立專案

  • 開啟 Visual Studio 2019
  • 在 [Visual Studio 2019] 對話窗中,選擇 [建立新的專案]
  • 在 [建立新專案] 對話窗,選擇 [Prism Blank App (Xamarin.Forms)]
  • 點選 [下一步] 按鈕
  • 在 [設定新的專案] 對話窗, [專案名稱] 欄位輸入 xfMediaPicker
  • 點選 [建立] 按鈕
  • 在 [RPISM PROJECT WIZARD] 對話窗內,勾選 [ANDROID] & [iOS]
  • 點選 [CREATE PROJECT] 按鈕

加入與更新套件

  • 在 [方案總管] 視窗內,展開 Xamarin.Forms 專案節點,也就是 [xfMediaPicker]
  • 滑鼠右擊 [相依性節點],點選 [管理 NuGet 套件]
  • 當 [NuGet: xfMediaPicker] 視窗出現後,點選 [瀏覽] 標籤頁次
  • 在文字輸入盒內輸入 PropertyChanged.Fody ,搜尋出這個套件
  • 點選 [PropertyChanged.Fody] 這個套件,安裝到 Xamarin.Forms 專案內
  • 滑鼠右擊 [方案總管] 最上方的節點 [解決方案 xfMediaPicker]
  • 點選 [管理方案的 NuGet 套件]
  • 當 [NuGet: 解決方案] 視窗出現後,點選 [更新] 標籤頁次
  • 點選 [選取所有封裝] ,接著點選 [更新按鈕]
  • 將選取套件更新到最新版本

查看 Xamarin.Essentials 媒體選擇器 使用方式

打開 Xamarin.Essentials 媒體選擇器 文件,可以看到這個 Xamarin.Essentials 媒體選擇器 使用說明

Android 專案修正

  • 找到 Android 專案 [xfMediaPicker.Android]
  • 開啟 [Properties] 資料夾下的 AssemblyInfo.cs 檔案
  • 在最後面加入底下宣告
// Add some common permissions, these can be removed if not needed
[assembly: UsesPermission(Android.Manifest.Permission.Internet)]
[assembly: UsesPermission(Android.Manifest.Permission.WriteExternalStorage)]
// Needed for Picking photo/video
[assembly: UsesPermission(Android.Manifest.Permission.ReadExternalStorage)]

// Needed for Taking photo/video
[assembly: UsesPermission(Android.Manifest.Permission.WriteExternalStorage)]
[assembly: UsesPermission(Android.Manifest.Permission.Camera)]

// Add these properties if you would like to filter out devices that do not have cameras, or set to false to make them optional
[assembly: UsesFeature("android.hardware.camera", Required = true)]
[assembly: UsesFeature("android.hardware.camera.autofocus", Required = true)]

iOS 專案修正

  • 找到 Android 專案 [xfMediaPicker.iOS]
  • 滑鼠右擊 [Info.plist] 檔案,選擇 [開啟方式]
  • 在 [開啟方式 - Info.plist] 對話窗出現後,選擇 [XML (文字) 編輯器]
  • 將底下內容輸入到 </dict> 文字前面
<key>NSCameraUsageDescription</key>
<string>This app needs access to the camera to take photos.</string>
<key>NSMicrophoneUsageDescription</key>
<string>This app needs access to microphone for taking videos.</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>This app needs access to the photo gallery for picking photos and videos.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>This app needs access to photos gallery for picking photos and videos.</string>

修正首頁頁面

  • 打開 MainPage.xaml 檔案
  • 將這個檔案內容替換為底下內容
<?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="xfMediaPicker.Views.MainPage"
             Title="Xamarin.Essentials 媒體選擇器">

    <StackLayout HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand">
        <Label Text="Welcome to Xamarin Forms and Prism!" />
        <Button Text="Take Photo"
                Command="{Binding TakePhotoCommand}"/>
        <Label Text="{Binding FilePath}"/>
        <Image Source="{Binding Photo}"/>
    </StackLayout>

</ContentPage>

修正首頁 ViewModel

  • 打開 MainPageViewModel.cs 檔案
  • 將這個檔案內容替換為底下內容
using Prism.Commands;
using System;

namespace xfMediaPicker.ViewModels
{
    using System.ComponentModel;
    using System.IO;
    using System.Threading.Tasks;
    using Prism.Navigation;
    using Xamarin.Essentials;
    using Xamarin.Forms;

    public class MainPageViewModel : INotifyPropertyChanged, INavigationAware
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private readonly INavigationService navigationService;
        public string FilePath { get; set; }
        public ImageSource Photo { get; set; }
        public DelegateCommand TakePhotoCommand { get; set; }
        public MainPageViewModel(INavigationService navigationService)
        {
            this.navigationService = navigationService;
            TakePhotoCommand = new DelegateCommand(async () =>
            {
                try
                {
                    FileResult photo = await MediaPicker.CapturePhotoAsync();
                    await LoadPhotoAsync(photo);
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"CapturePhotoAsync THREW: {ex.Message}");
                }
            });
        }

        async Task LoadPhotoAsync(FileResult photo)
        {
            // canceled
            if (photo == null)
            {
                FilePath = "";
                return;
            }
            // save the file into local storage
            var newFile = Path.Combine(FileSystem.CacheDirectory, "MyPhoto.png");
            using (var stream = await photo.OpenReadAsync())
            using (var newStream = File.OpenWrite(newFile))
                await stream.CopyToAsync(newStream);

            File.Delete(photo.FullPath);
            FilePath = newFile;

            FileResult showFile = new FileResult(FilePath);
            Photo = ImageSource.FromStream( () =>
            {
                Stream stream = showFile.OpenReadAsync().Result;
                return stream;
            });
        }
        public void OnNavigatedFrom(INavigationParameters parameters)
        {
        }

        public void OnNavigatedTo(INavigationParameters parameters)
        {
        }

    }
}

開始執行這個專案

  • 選擇在 Android 模擬器下來執行這個專案
  • 當應用程式啟動之後,就會看到底下畫面

  • 點選 [TAKE PHOTO] 按鈕
  • 將會出現對話窗,詢問是否允許這個應用程式可以允許拍照或者錄影功能
  • 點選 [ALLOW] 按鈕

  • 現在將會出現底下對話窗,詢問這個應用程式是否可以允許存取圖片、媒體、檔案詢問這個應用程式是否可以允許存取圖片、媒體、檔案
  • 點選 [ALLOW] 按鈕

  • 現在,先回到 Visual Studio 內,打開 [MainPageViewModel.cs]
  • 找到 if (photo == null) 這行
  • 標示這行為中斷點

  • 現在將會看到模擬器出現了模擬的照相功能
  • 請點選最下方的 [照相機] 圖示,表示要拍照

  • 當出現下圖,點選底下的 [打勾] 按鈕

  • 現在程式停在剛剛設定中斷點上
  • 現在可以查看 LoadPhotoAsync 方法的參數 photo 的屬性值內容
  • 可以看到這次拍照的照片檔案存在在哪裡

  • 在我這台電腦上,所拍照的照片將會為這個檔案

/data/user/0/com.companyname.appname/cache/2203693cc04e0be7f4f024d5f9499e13/e5c347e3599d44ddb2f3c0ded01ab830/3fc6f9320d3a49018828d889843a03a7.jpg

  • 繼續執行這個專案,將會看到底下畫面

 




2021年1月4日 星期一

使用 Syncfusion 的按鈕元件或指定按鈕代表圖形,有 Bootstrap 4 與 Open Iconic 兩種用法

使用 Syncfusion 的按鈕元件或指定按鈕代表圖形,有 Bootstrap 4 與 Open Iconic 兩種用法

由於工作上的需要以看到最新的網頁開發框架 Blazor ,便決定開始使用 Blazor Server Side 來進行網頁專案的開發,會選擇 Server Side 方式而不是採用 WASM 的方式,當初決定的理由相當的簡單,那就是要簡化整個網站開發的流程,透過 Blazor Server Side 開發架構,可以享受到許多的好處,例如可以線上直接設定中斷點來進行除錯、不需要設計 Web API 就可以存取後端的資料庫等等。

一旦決定了使用 Blazor 開發框架來進行專案開發,接下來要解決的問題就是如何設計各種ui介面,在網路上存在的許多免費的 Blazor UI 套件,每種使用方式以提供的功能都不盡相同,根據自身的需求來判斷,似乎沒有一套免費的ui套件可以滿足專案上的需要,因此就直接轉向了付費的 Blazor UI 套件來進行評估,當然,市面上也存在的許多付費的 Blazor 元件產品,在這裡選擇了 Syncfusion 這家的 Blazor 元件來進行開發。

那麼要如何使用 Syncfusion 元件來進行 Blazor 專案開發,就是這篇文章所要探討的內容,在這裡,將會說明如何在 Blazor 專案內顯示一個日期選舉萬年曆這樣的 UI 功能。

這個說明專案的原始碼位於 bzSyncfusionButton

建立 Blazor Server-Side 的專案

  • 打開 Visual Studio 2019

  • 點選右下方的 [建立新的專案] 按鈕

  • [建立新專案] 對話窗將會顯示在螢幕上

  • 從[建立新專案] 對話窗的中間區域,找到 [Blazor 應用程式] 這個專案樣板選項,並且選擇這個項目

  • 點選右下角的 [下一步] 按鈕

  • 現在 [設定新的專案] 對話窗將會出現

  • 請在這個對話窗內,輸入適當的 [專案名稱] 、 [位置] 、 [解決方案名稱]

    在這裡請輸入 [專案名稱] 為 bzSyncfusion

  • 完成後,請點選 [建立] 按鈕

  • 當出現 [建立新的 Blazor 應用程式] 對話窗的時候

  • 請選擇最新版本的 .NET Core 與 [Blazor 伺服器應用程式]

  • 完成後,請點選 [建立] 按鈕

稍微等會一段時間,Blazor 專案將會建立起來

進行 Syncfusion 元件的安裝

  • 滑鼠右擊 Blazor 專案的 [相依性] 節點
  • 選擇 [管理 NuGet 套件]
  • 切換到 [瀏覽] 標籤頁次
  • 搜尋 Syncfusion.Blazor 這個元件名稱
  • 選擇搜尋到的 [Syncfusion.Blazor] 元件,並且安裝起來

進行 Syncfusion 元件的設定

  • 打開專案根目錄下的 [Startup.cs] 這個檔案
  • 找到 [ConfigureServices] 這個方法
  • 在這個方法的最後面,加入底下程式碼,已完成 Blazor 元件會用到的服務註冊
#region Syncfusion 元件的服務註冊
services.AddSyncfusionBlazor();
#endregion
  • 在同一個檔案內,找到 [Configure] 這個方法
  • 在這個方法的最前面,加入底下程式碼,宣告合法授權的金鑰 (License Key)
#region 宣告所使用 Syncfusion for Blazor 元件的使用授權碼
Syncfusion.Licensing.SyncfusionLicenseProvider.RegisterLicense("YOUR LICENSE KEY");
#endregion
  • 打開 [Pages] 資料夾內的 [_Host.cshtml] 檔案

  • 在 <head> 標籤內,加入需要的 CSS 宣告,如底下內容

    若沒有加入底下的宣告,將無法正常看到 Syncfusion 的元件樣貌

<link href="_content/Syncfusion.Blazor/styles/bootstrap4.css" rel="stylesheet" />

修改 Index.razor

  • 在專案的 [Pages] 資料夾
  • 打開 [Index.razor] 檔案
  • 使用底下程式碼替換到 [Index.razor] 檔案內容
@page "/"
@using Syncfusion.Blazor
@using Syncfusion.Blazor.Buttons

<h1>Hello, SfButton!</h1>

<p>各種按鈕樣式</p>
<SfButton @ref="ThisBtn" CssClass="e-primary" @onclick="OnClick" Content="@Content"></SfButton>
<SfButton CssClass="e-success">Success</SfButton>
<SfButton CssClass="e-info">Info</SfButton>
<SfButton CssClass="e-warning">Warning</SfButton>
<SfButton CssClass="e-danger">Danger</SfButton>
<SfButton CssClass="e-link">Link</SfButton>
<p>各種按鈕類型</p>
<SfButton CssClass="e-flat">Flat</SfButton>
<SfButton CssClass="e-outline">Outline</SfButton>
<SfButton CssClass="e-round" IconCss="oi oi-plus" IsPrimary="true"></SfButton>
<p>按鈕+圖形</p>
<SfButton IconCss="e-icons e-play-icon" IconPosition="IconPosition.Right">PLAY</SfButton>
<SfButton IconCss="e-icons e-pause-icon">PAUSE</SfButton>

<p>各種 Bootstrap 4 的圖形 https://blazor.syncfusion.com/documentation/appearance/icons/#bootstrap-4 </p>
<p>各種 Open Iconic 的圖形 https://useiconic.com/open</p>

<style>

    .e-play-icon:before {
        content: '\e70b';
    }

    .e-pause-icon:before {
        content: '\e757';
    }
</style>

@code{
    SfButton ThisBtn;
    public string Content = "Primary";
    private void OnClick(Microsoft.AspNetCore.Components.Web.MouseEventArgs args)
    {
        Content = "已經按下此按鈕";
    }
}

使用 Syncfusion 的 SfButton 元件, 可以產生出更多的視覺效果,然而這與一般HTML的按鈕元件用法差異不大,對於當使用者點選這個按鈕之後,可以使用 @onclick 來宣告說綁定的觸發事件委派方法,也就是說按鈕被按下去之後,指定的委派方法就會執行;而 Content 屬性則是用來設定該按鈕要顯示的文字,另外可以使用 CssClass 屬性搭配 Syncfusion 提供的css類別來指定按鈕的各種不同樣式。

在第一個 SfButton 按鈕中,原先蓋按鈕將會顯示 @Content 這一個變數的字串值,預設為 Primary, 當使用者按下這個按鈕之後,就會觸發 private void OnClick(Microsoft.AspNetCore.Components.Web.MouseEventArgs args) 這個事件委派方法,在委派方法那會透過這個敘述 Content = "已經按下此按鈕" , 變更 Content 這個變數數值,也就是這個按鈕將會顯示出 Content = "已經按下此按鈕" 這個文字。在底下的螢幕截圖可以看到這樣的操作結果。

若想要指定這個按鈕上面所要顯示的圖案,可以使用任何網站開發會用到的字體圖示檔案,在建立 Blazor 專案的時候,預設將會安裝 Open Iconic 字體圖示檔案,所以可以在 SfButton 標籤內使用 IconCss 這個屬性指定要顯示圖示的類別名稱; 例如這樣的用法 <SfButton CssClass="e-round" IconCss="oi oi-plus" IsPrimary="true"></SfButton>

現在可以直接執行這支程式,就會看到如下圖的執行結果。

 




2021年1月3日 星期日

如何使用 Syncfusion 元件庫 在 Blazor 專案上

如何使用 Syncfusion 元件庫 在 Blazor 專案上

由於工作上的需要以看到最新的網頁開發框架 Blazor ,便決定開始使用 Blazor Server Side 來進行網頁專案的開發,會選擇 Server Side 方式而不是採用 WASM 的方式,當初決定的理由相當的簡單,那就是要簡化整個網站開發的流程,透過 Blazor Server Side 開發架構,可以享受到許多的好處,例如可以線上直接設定中斷點來進行除錯、不需要設計 Web API 就可以存取後端的資料庫等等。

一旦決定了使用 Blazor 開發框架來進行專案開發,接下來要解決的問題就是如何設計各種ui介面,在網路上存在的許多免費的 Blazor UI 套件,每種使用方式以提供的功能都不盡相同,根據自身的需求來判斷,似乎沒有一套免費的ui套件可以滿足專案上的需要,因此就直接轉向了付費的 Blazor UI 套件來進行評估,當然,市面上也存在的許多付費的 Blazor 元件產品,在這裡選擇了 Syncfusion 這家的 Blazor 元件來進行開發。

那麼要如何使用 Syncfusion 元件來進行 Blazor 專案開發,就是這篇文章所要探討的內容,在這裡,將會說明如何在 Blazor 專案內顯示一個日期選舉萬年曆這樣的 UI 功能。

這個說明專案的原始碼位於 bzSidebar

建立 Blazor Server-Side 的專案

  • 打開 Visual Studio 2019

  • 點選右下方的 [建立新的專案] 按鈕

  • [建立新專案] 對話窗將會顯示在螢幕上

  • 從[建立新專案] 對話窗的中間區域,找到 [Blazor 應用程式] 這個專案樣板選項,並且選擇這個項目

  • 點選右下角的 [下一步] 按鈕

  • 現在 [設定新的專案] 對話窗將會出現

  • 請在這個對話窗內,輸入適當的 [專案名稱] 、 [位置] 、 [解決方案名稱]

    在這裡請輸入 [專案名稱] 為 bzSyncfusion

  • 完成後,請點選 [建立] 按鈕

  • 當出現 [建立新的 Blazor 應用程式] 對話窗的時候

  • 請選擇最新版本的 .NET Core 與 [Blazor 伺服器應用程式]

  • 完成後,請點選 [建立] 按鈕

稍微等會一段時間,Blazor 專案將會建立起來

進行 Syncfusion 元件的安裝

  • 滑鼠右擊 Blazor 專案的 [相依性] 節點
  • 選擇 [管理 NuGet 套件]
  • 切換到 [瀏覽] 標籤頁次
  • 搜尋 Syncfusion.Blazor 這個元件名稱
  • 選擇搜尋到的 [Syncfusion.Blazor] 元件,並且安裝起來

進行 Syncfusion 元件的設定

  • 打開專案根目錄下的 [Startup.cs] 這個檔案
  • 找到 [ConfigureServices] 這個方法
  • 在這個方法的最後面,加入底下程式碼,已完成 Blazor 元件會用到的服務註冊
#region Syncfusion 元件的服務註冊
services.AddSyncfusionBlazor();
#endregion
  • 在同一個檔案內,找到 [Configure] 這個方法
  • 在這個方法的最前面,加入底下程式碼,宣告合法授權的金鑰 (License Key)
#region 宣告所使用 Syncfusion for Blazor 元件的使用授權碼
Syncfusion.Licensing.SyncfusionLicenseProvider.RegisterLicense("YOUR LICENSE KEY");
#endregion
  • 打開 [Pages] 資料夾內的 [_Host.cshtml] 檔案

  • 在 <head> 標籤內,加入需要的 CSS 宣告,如底下內容

    若沒有加入底下的宣告,將無法正常看到 Syncfusion 的元件樣貌

<link href="_content/Syncfusion.Blazor/styles/bootstrap4.css" rel="stylesheet" />

使用 SfCalendar 元件

  • 在專案的 [Pages] 資料夾
  • 打開 [Index.razor] 檔案
  • 使用底下程式碼替換到 [Index.razor] 檔案內容
@page "/"
@using Syncfusion.Blazor
@using Syncfusion.Blazor.Calendars

<h1>Hello, world!</h1>

Welcome to your new app.

<SfCalendar TValue="DateTime" Value="workDate"></SfCalendar>

@code
{
    DateTime workDate = DateTime.Now;
}

從這裡看到使用 Syncfusion 元件相當的容易,只需要加入該元件所使用的命名空間在 Razor 元元件前面,接著就加入該元件的HTML標籤,例如在這裡使用的是

現在可以直接執行這支程式,就會看到如下圖的執行結果。