UWP開發入門(十七)——判斷設備類型及響應VirtualKey


  蜀黍我做的工作跟IM軟件有關,UWP同時會跑在電腦和手機上。電腦和手機的使用習慣不盡一致,通常我傾向於根據窗口尺寸來進行布局的變化,但是特定的操作習慣是依賴於設備類型,而不是屏幕尺寸的,比如聊天窗口的發送消息。假設如下場景,desktop運行時要求回車鍵直接發送消息,而mobile版則要求回車鍵換行,僅能通過點擊按鈕發送消息。

  第一段的鋪墊是為了今天提到的兩個主題,判斷設備類型和處理Shift+Enter的組合。

  首先判斷設備類型我們使用的是Windows.System.Profile命名空間下的AnalyticsInfo類,通過AnalyticsInfo.VersionInfo.DeviceFamily這個屬性我們可以拿到當前的設備類型,小屏幕的設備類型是"Windows.Mobile",其他還是有Windows.Desktop,Windows.Xbox等。這里我們只希望單獨區分小屏幕設備,不關心其他設備類型。同時需要指出的是,隨之今后Windows設備類型的不斷擴充,該屬性可能出現的值會不斷變化,所以在使用時需要考慮到變化是否會產生bug

        public bool IsAcceptReturn
        {
            get
            {
                return AnalyticsInfo.VersionInfo.DeviceFamily == "Windows.Mobile";
            }
        }

  我們根據設備類型來定義了一個屬性IsAcceptReturn來標識是否接受回車鍵換行。

  接下來進行Shift+Enter組合鍵的響應了。UWP在這一點上果然又開了歷史倒車,沒記錯的話連WinForm也無需如此麻煩,竟然要額外地儲存一個標志位來標識VirtualKey.Shift是否被按下,在此基礎之上再進一步判斷是否有Enter鍵被觸發。實際的代碼中,我使用了KeyDown事件來記錄Shift鍵的按下,同時通過KeyU事件來進行Enter鍵觸發的判斷。

        private void KeyUp(KeyRoutedEventArgs e)
        {
            if (e.Key == VirtualKey.Enter)
            {
                if (_isShiftKeyPressed)
                {
                    int oldIndex = Index;
                    InputText = InputText.Replace(Environment.NewLine, "\n").Insert(Index, "\n");
                    Index = oldIndex + 1;
                }
                else if (IsAcceptReturn == false)
                {
                    SendMessage();
                }
            }
            _isShiftKeyPressed = false;
        }
        
        private void KeyDown(KeyRoutedEventArgs e)
        {
            if (e.Key == VirtualKey.Shift)
            {
                _isShiftKeyPressed = true;
            }
        }

  在KeyUp事件中如果涉及Enter鍵的觸發,將判斷_isShiftKeyPressed字段的值,同時根據IsAcceptReturn來判斷是否不處理換行,直接發送消息。這里值得一提的是Environment.NewLineWindows下對應的\r\n符號,計算字符串索引時僅作為1位處理,導致我很尷尬總是算不對Shift+Enter換行后的光標位置。無奈出下策將其替換成"\n",其中奧妙各位一試便知。程序對應的XAML如下:

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition Width="Auto"/>
        </Grid.ColumnDefinitions>
        <ListView Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" ItemsSource="{Binding Messages}"/>
        <TextBox Grid.Row="1" Grid.Column="0" Text="{Binding InputText, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" SelectionStart="{Binding Index, Mode=TwoWay}"
                 MaxHeight="100" AcceptsReturn="{Binding IsAcceptReturn}" TextWrapping="Wrap">

            <Interactivity:Interaction.Behaviors>
                <Core:EventTriggerBehavior EventName="KeyUp">
                    <Core:InvokeCommandAction Command="{Binding KeyUpCommand,Mode=OneTime}"/>
                </Core:EventTriggerBehavior>
                <Core:EventTriggerBehavior EventName="KeyDown">
                    <Core:InvokeCommandAction Command="{Binding KeyDownCommand,Mode=OneTime}"/>
                </Core:EventTriggerBehavior>
            </Interactivity:Interaction.Behaviors>

        </TextBox>
        <Button Grid.Row="1" Grid.Column="1" Width="80" Command="{Binding SendMessageCommand}" Content="Send"/>
    </Grid>

  ListView模擬聊天窗口,TextBoxText屬性Binding到了InpuText,同時SlectionStar屬性BindingIndex,用於Shift+Enter換行時,插入\n換行符號,及確定光標位置。AcceptsReturn屬性在Mobile設備上是true,而在其他設備上就會無視回車鍵來。TextWrapping屬性也很重要,如果不設置為Wrap,即使實際的字符串是包含\n等換行符號,但在TextBox中也不會顯示出來。

  求看到這里的各位評論一下嗨,讓俺知道還有人在看Windows UWP。

  Behaviors的使用我計划后續的篇章再介紹,同時本篇的代碼使用了Mvvmlight框架,我想是時候把Mvvmlight的介紹也拾起來了!最后是完整代碼在GitHub的地址,歡迎看了批評指正哈。

  https://github.com/manupstairs/UWPSamples/tree/master/UWPSamples/DeviceFamilyAndVirtualKey


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM