十年網(wǎng)站開(kāi)發(fā)經(jīng)驗(yàn) + 多家企業(yè)客戶 + 靠譜的建站團(tuán)隊(duì)
量身定制 + 運(yùn)營(yíng)維護(hù)+專業(yè)推廣+無(wú)憂售后,網(wǎng)站問(wèn)題一站解決
在PC上我一直使用“小番茄”作為我的番茄鐘軟件,我把它打開(kāi)后放在副顯示器大化,這樣不僅可以讓它盡到本分,而且還可以告訴我的同事“我正在專心工作”??墒俏铱偸窍訔壦氖指胁粔蛴鋹?,總想自己寫(xiě)一個(gè)番茄鐘軟件,正好最近很久沒(méi)寫(xiě)UWP應(yīng)用了很手癢,于是就抽空寫(xiě)了個(gè)自用的番茄鐘并發(fā)布到微軟應(yīng)用商店。
結(jié)果手感也并不愉悅。
另外,本來(lái)本來(lái)我也打算用Storyboard實(shí)現(xiàn)動(dòng)畫(huà),但火火總是勸我不要搞Storyboard,要用Composition API做動(dòng)畫(huà)。Storyboard的能力是有極限的,我從短暫的UWP生涯當(dāng)中學(xué)到一件事,人越是玩弄?jiǎng)赢?huà),動(dòng)畫(huà)就越可能因?yàn)闆](méi)有料到的事態(tài)而失敗……除非超越Storyboard。所以我也不做Sotryboard啦。
微軟的應(yīng)用商店是一個(gè)還不錯(cuò)的平臺(tái),WPF程序員可以基于現(xiàn)有的知識(shí)輕易地創(chuàng)建一個(gè)UWP應(yīng)用并發(fā)布到應(yīng)用商店。尤其是現(xiàn)在微軟的審核比較寬松,只要是對(duì)得起自己良心的應(yīng)用一般都能通過(guò)審核。雖然因?yàn)樯痰瓿轱L(fēng)我自己都很難下載到自己的應(yīng)用。這篇文章將講解從創(chuàng)建UWP項(xiàng)目到發(fā)布到商店的整個(gè)流程。
我只想要一個(gè)可以倒計(jì)時(shí)的Timer,順便玩玩UWP的新API,所以原則上越簡(jiǎn)單越好,然后想到什么做什么。
很多番茄鐘軟件都會(huì)提供任務(wù)列表功能,還可以通過(guò)圖表展示番茄數(shù)量、完成任務(wù)數(shù)量的統(tǒng)計(jì)。不過(guò)我已經(jīng)有To-Do和Azure Devops,平時(shí)的工作還會(huì)記錄在OneNote上,我更放心把我的數(shù)據(jù)放到微軟那里而不是番茄鐘那里,而且我認(rèn)為衡量番茄工作法是否執(zhí)行得好的標(biāo)準(zhǔn)是我的工作,而不是圖表里展示給我的番茄數(shù)量,所以我對(duì)圖表、統(tǒng)計(jì)、任務(wù)列表這些功能不是太感興趣。
說(shuō)了這么多其實(shí)還是因?yàn)槲覒校綍r(shí)上班已經(jīng)處理這么多數(shù)據(jù)了,圖表我也玩膩了,自己玩玩的東西就不想做這些工作,而且存儲(chǔ)數(shù)據(jù)是要負(fù)責(zé)任的,我可不想負(fù)責(zé)任。
首先安裝Windows Template Studio,它可以幫助開(kāi)發(fā)者簡(jiǎn)單地創(chuàng)建UWP項(xiàng)目。
安裝后在創(chuàng)建新項(xiàng)目界面選擇Windows Template Studio(Universal Windows)
,然后在打開(kāi)的精靈控件窗口一步步創(chuàng)建一個(gè)已經(jīng)包含基礎(chǔ)功能的UWP應(yīng)用。
項(xiàng)目名稱是OnePomodoro
,項(xiàng)目類型選擇Blank
,Design pattern選擇了Prism,因?yàn)樵赪PF中用慣了Prsim。不過(guò)我不懂UWP中Prism怎么用,所以我也沒(méi)打算馬上就用,只是個(gè)小項(xiàng)目輕輕松松地CodeBehind一把梭。
頁(yè)面項(xiàng)選擇了Settings頁(yè)面。功能項(xiàng)添加了好像很有趣的Toast Notifications、Live Tile等一系列的通知功能。
稍等幾分鐘后,一個(gè)包含了基本功能的UWP項(xiàng)目就創(chuàng)建好了,項(xiàng)目中還貼心地提示了很多需要處理的Todo項(xiàng),運(yùn)行效果如下:
然后添加Microsoft.Toolkit.Uwp.UI和Microsoft.Toolkit.Uwp.UI.Animations引用,這兩個(gè)包是Windows Community Toolkit的一部分,提供了很多有用的Converter和動(dòng)畫(huà)。
第一次運(yùn)行應(yīng)用時(shí)會(huì)彈出一些示例通知,現(xiàn)在還不需要做到這么全面,找到App.xaml.cs里的LaunchApplicationAsync
把里面一些通知相關(guān)的代碼注釋掉,然后就可以開(kāi)始實(shí)現(xiàn)我們的功能了。
protected override async Task OnLaunchApplicationAsync(LaunchActivatedEventArgs args)
{
await LaunchApplicationAsync(PageTokens.MainPage, null);
}
private async Task LaunchApplicationAsync(string page, object launchParam)
{
await ThemeSelectorService.SetRequestedThemeAsync();
NavigationService.Navigate(page, launchParam);
SetupTitlebar();
Window.Current.Activate();
//await Container.Resolve().ShowIfAppropriateAsync();
//await Container.Resolve().ShowIfAppropriateAsync();
//Container.Resolve().SampleUpdate();
//Container.Resolve().ShowToastNotificationSample();
}
最終效果就是這樣,一個(gè)單頁(yè)面的應(yīng)用,點(diǎn)擊開(kāi)始啟動(dòng)工作的計(jì)時(shí)器,點(diǎn)擊停止(或者倒計(jì)時(shí)結(jié)束)轉(zhuǎn)到休息的計(jì)時(shí)器,如此往返幾次,一天的工資就到手了。
很多計(jì)時(shí)器是個(gè)由分針和秒針組成的表盤,但我已經(jīng)玩膩了這種做法,簡(jiǎn)單些反而有更多的快樂(lè)。
為了好看首先要移除應(yīng)用的標(biāo)題欄,將CoreApplicationViewTitleBar.ExtendViewIntoTitleBar 屬性設(shè)置為True:
private void ExtendAcrylicIntoTitleBar()
{
CoreApplication.GetCurrentView().TitleBar.ExtendViewIntoTitleBar = true;
ApplicationViewTitleBar titleBar = ApplicationView.GetForCurrentView().TitleBar;
titleBar.ButtonBackgroundColor = Colors.Transparent;
titleBar.ButtonInactiveBackgroundColor = Colors.Transparent;
}
因?yàn)楸尘笆呛谏?,需要將主題也改為黑色主題,在App.xaml中修改RequestedTheme為Dark:
RequestedTheme="Dark"
然后實(shí)現(xiàn)MainViewModel。使用到DispatcherTimer
進(jìn)行計(jì)時(shí),用DelegateCommand
實(shí)現(xiàn)命令,這些都只用到WPF的知識(shí):
public class MainViewModel: ViewModelBase
{
public bool IsInPomodoro { get; }
public bool IsTimerInProgress { get; }
public TimeSpan RemainingBreakTime { get; }
public TimeSpan RemainingPomodoroTime { get; }
public DelegateCommand StartTimerCommand { get; }
public DelegateCommand StopTimerCommand { get; }
}
整個(gè)UI上就只有4行字,以及停止和開(kāi)始兩個(gè)按鈕。(上面效果圖里還有一個(gè)按鈕,那是第二版做的)。整個(gè)番茄鐘由IsInPomodoro和IsTimerInProgress組合成準(zhǔn)備開(kāi)始工作,正在工作,準(zhǔn)備休息,正在休息四種狀態(tài),MainView上的元素就由IsInPomodoro和IsTimerInProgress這兩個(gè)屬性控制是否顯示。
為了用這兩個(gè)Bool屬性控制UI元素的顯示和隱藏需要用到Converter,Microsoft.Toolkit.Uwp.UI
提供了BoolToVisibilityConverter,我需要再實(shí)現(xiàn)一個(gè)反過(guò)來(lái)的NegationBoolToVisibilityConverter
:
public class NegationBoolToVisibilityConverter : BoolToObjectConverter
{
public NegationBoolToVisibilityConverter()
{
base.TrueValue = Visibility.Collapsed;
base.FalseValue = Visibility.Visible;
}
}
這兩個(gè)Converter配合IsInPomodoro和IsTimerInProgress兩個(gè)屬性用于控制是否顯示。然后再使用BoolToObjectConverter定義兩個(gè)Converter用于控制文字的水平和垂直對(duì)齊:
converters:BoolToObjectConverter TrueValue="Top"
FalseValue="Bottom"
x:Key="BoolToVerticalAlignmentConverter" />
converters:BoolToObjectConverter TrueValue="Left"
FalseValue="Right"
x:Key="BoolToVerticalHorizontalAlignment" />
整個(gè)布局大概這樣
到這時(shí)候,MainView和MainViewModel幾乎只用到WPF的知識(shí),雖然聽(tīng)說(shuō)DispatcherTimer比較傷性能,也沒(méi)有用x:Binding代替Binding,主要是想到項(xiàng)目剛開(kāi)始就盡量用WPF的知識(shí)實(shí)現(xiàn)所有功能,以后再試用UWP的API。不過(guò)動(dòng)畫(huà)我倒是沒(méi)用Storyboard,而是用Composition API做動(dòng)畫(huà)。
composition-animation有很多種,我選擇使用Windows Community Toolkit中的Implicit Animations,因?yàn)樗苓m合入門。
Implicit Animations(又稱為隱式動(dòng)畫(huà))是一種用于描述當(dāng)屬性(例如Opacity or Offset)改變時(shí)如何使用動(dòng)畫(huà)響應(yīng)的Composition Animations。而ShowAnimations和HideAnimations分別用于定義當(dāng)元素顯示/隱藏或從VisualTree上添加/移除時(shí)的動(dòng)畫(huà)效果。
MainView里當(dāng)狀態(tài)改變只會(huì)引起元素顯示/隱藏或者對(duì)齊的改變,所以很適合使用隱式動(dòng)畫(huà)。例如這段番茄鐘倒計(jì)時(shí)的動(dòng)畫(huà),即顯示時(shí)從下面200像素向上移動(dòng),并且淡入,耗時(shí)1.5秒;隱藏時(shí)用0.5秒淡出。
最終動(dòng)畫(huà)效果如下:
就這樣一個(gè)基本的番茄鐘就做好了,之后就是打包和發(fā)布。隨便畫(huà)個(gè)漸變的背景,再畫(huà)個(gè)圈,Logo就做好了。然后在Package.appxmanifest里處理一下信息,就打包了,就發(fā)布了。
官方文檔有很詳盡的發(fā)布指南,微軟合作伙伴中心的圖形界面也簡(jiǎn)單易用,稍微折騰一下就可以發(fā)布,過(guò)幾天就可以在Store里見(jiàn)到自己的應(yīng)用。
每次自己打包都很麻煩,可以將Github倉(cāng)庫(kù)(假設(shè)有的話)和AppCenter關(guān)聯(lián)起來(lái),每次提交到Github都由AppCenter打安裝包。AppCenter打包后即可把安裝包下載回來(lái),再發(fā)布(話說(shuō)沒(méi)有直接幫我發(fā)布的方法嗎?)
林德熙的這篇文章詳細(xì)介紹了如何操作。
還可以獲得一個(gè)徽標(biāo),顯示編譯結(jié)果。
Edi.Wang被UWP傷害后拋棄了UWP還像個(gè)怨念少女那樣每天對(duì)別人說(shuō)其實(shí)是要說(shuō)服自己“我才沒(méi)有喜歡UWP我最討厭UWP討厭討厭最討厭了”但這樣每天每天每天都說(shuō)UWP是個(gè)壞家伙是個(gè)壞家伙搞到我反而很想試一試這個(gè)壞家伙現(xiàn)在終于忍不了了晚上把switch扔在床上把自己關(guān)在書(shū)房里親自動(dòng)手調(diào)教UWP。
總的來(lái)說(shuō)這是個(gè)愉快的編程體驗(yàn):用慣的WPF知識(shí)和官方文檔,即可實(shí)現(xiàn)一個(gè)自己用的應(yīng)用并發(fā)布——除了商店偶爾抽風(fēng)導(dǎo)致自己都下載不了自己的應(yīng)用外。
順便一提OnePomodoro的中文名稱是一個(gè)番茄鐘(謝絕對(duì)命名品味的一切批評(píng)),已經(jīng)可以在Store下載。
最后提一下左下角的按鈕。因?yàn)?809的Button有了圓角的API,圓形的Reveal按鈕很容易實(shí)現(xiàn),只需要BasedOn ButtonRevealStyle
再把CornerRadius
有那么大就搞那么大:
這樣省去了很多修改ControlTemplate的麻煩,所以項(xiàng)目的最低版本即是1809,反正只是玩玩的東西不要顧慮太多。
可以打開(kāi)這個(gè)鏈接安裝 一個(gè)番茄鐘,也可以在Microsoft Store中搜索“OnePomodoro”或“一個(gè)番茄鐘”進(jìn)行安裝。
如果不能安裝?我相信,等緣分到了自然可以安裝。
通過(guò)《番茄工作法圖解》復(fù)習(xí)番茄工作法
Windows Template Studio quickly builds a UWP app, using a wizard-based UI to turn your needs into a foundation of Windows 10 patterns and best practices
Overview - Visual Studio App Center Microsoft Docs
合成動(dòng)畫(huà) - Windows UWP applications Microsoft Docs
Implicit Animations XAML Attached Properties - Windows Community Toolkit Microsoft Docs
OnePomodoro
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)cdcxhl.cn,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。