鸿蒙推箱子小游戏UI界面美化
在上文笔者向大家分享了推箱子小游戏基础功能的实现,本文将继续向大家介绍如何做UI界面美化,以及如何利用轻量级偏好数据库做数据的存储和读取。
UI界面美化
MainAbilitySlice
我们可以看到,所有的界面都是采用无框全屏化设计,因此第一步是要修改config。json文件。
打开文件,将代码做出如下修改:。。。。。。launchType:standard}〕,metaData:{customizeData:〔{name:hwctheme,value:androidhwext:styleTheme。Emui。Light。NoTitleBar,extra:}〕}}}
然后设计按钮样式,首先新建一个graphic文件:
接着在里面添加美化代码:lt;?xmlversinotallow1。0encodingutf8?shapexmlns:ohoshttp:schemas。huawei。comresohosohos:shaperectanglecornersohos:radius120strokeohos:width3vpohos:colorfbc02dsolidohos:colorfff8e1shape
现在分析界面需求,其中带有Pokemon字样的是本地图片,因此我们需要的控件有四个按钮以及一张图片,布局采用DirectionalLayout即可。
代码如下:lt;?xmlversinotallow1。0encodingutf8?DirectionalLayoutxmlns:ohoshttp:schemas。huawei。comresohosohos:heightmatchparentohos:widthmatchparentohos:alignmentcenterohos:orientationverticalImageohos:layoutalignmenthorizontalcenterohos:width350vpohos:height100vpohos:imagesrcmedia:pokemonohos:scalemodezoomcenterohos:bottommargin20vpButtonohos:idid:startBtnohos:width250vpohos:height50vpohos:backgroundelementgraphic:backgroundabilitymainohos:textcolorffffffohos:textweight700ohos:textsize20vpohos:text开始游戏ohos:bottommargin20vpButtonohos:idid:recordBtnohos:width250vpohos:height50vpohos:backgroundelementgraphic:buttonohos:textcolorfbc02dohos:textweight700ohos:textsize20vpohos:text历史记录ohos:bottommargin20vpButtonohos:idid:aboutBtnohos:width250vpohos:height50vpohos:backgroundelementgraphic:buttonohos:textcolorfbc02dohos:textweight700ohos:textsize20vpohos:text关于游戏ohos:bottommargin20vpButtonohos:idid:exitBtnohos:width250vpohos:height50vpohos:textcolorfbc02dohos:backgroundelementgraphic:buttonohos:textweight700ohos:textsize20vpohos:text退出游戏ohos:bottommargin20vpDirectionalLayout
至此第一个界面就美化完成了。
SelectSlice
这个界面的布局跟第一个界面大同小异,只是少了一个按钮,还有就是按钮的样式有点不同,因此需要再写一个graphic文件,方法同上。
这里直接给出代码:lt;?xmlversinotallow1。0encodingutf8?shapexmlns:ohoshttp:schemas。huawei。comresohosohos:shaperectanglecornersohos:radius120strokeohos:width3vpohos:color7cc473solidohos:colore5f0e4shape
界面的代码如下:lt;?xmlversinotallow1。0encodingutf8?DirectionalLayoutxmlns:ohoshttp:schemas。huawei。comresohosohos:heightmatchparentohos:widthmatchparentohos:orientationverticalohos:alignmentcenterImageohos:width361vpohos:height70vpohos:scalemodezoomcenterohos:layoutalignmentcenterohos:bottommargin30vpohos:imagesrcmedia:selectButtonohos:layoutalignmentcenterohos:idid:firstBtnohos:width300vpohos:height60vpohos:backgroundelementgraphic:selectohos:textcolor7cc473ohos:textweight700ohos:textsize30fpohos:text第一关ohos:bottommargin30vpButtonohos:layoutalignmentcenterohos:idid:secondBtnohos:width300vpohos:height60vpohos:backgroundelementgraphic:selectohos:textcolor7cc473ohos:textweight700ohos:textsize30fpohos:text第二关ohos:bottommargin30vpButtonohos:layoutalignmentcenterohos:idid:thirdBtnohos:width300vpohos:height60vpohos:backgroundelementgraphic:selectohos:textcolor7cc473ohos:textweight700ohos:textsize30fpohos:text第三关ohos:bottommargin20vpDirectionalLayout
InitSlice
在加载界面中,只是用到了一个播放gif的第三方组件,以及一张图片(文字图片)一个进度条组件,布局也使用最常规的DirectionalLayout即可实现。lt;?xmlversinotallow1。0encodingutf8?DirectionalLayoutxmlns:ohoshttp:schemas。huawei。comresohosohos:heightmatchparentohos:widthmatchparentohos:orientationverticalcom。bumptech。glide。load。resource。gif。drawableability。DraweeViewohos:layoutalignmentcenterohos:topmargin100vpohos:idid:draweeViewohos:width360vpohos:height360vpImageohos:width291vpohos:height53vpohos:layoutalignmentcenterohos:bottommargin30vpohos:scalemodezoomcenterohos:imagesrcmedia:LoadingProgressBarohos:layoutalignmentcenterohos:height30vpohos:width330vpohos:idid:pbohos:max100ohos:min0ohos:progresswidth330vpohos:backgroundelementedf1bbohos:progresselementf2c867ohos:progress0DirectionalLayout
GameSlice
游戏界面的UI就稍微复杂一点,需要用到嵌套,之前说过,地图类继承自布局,所以实际上地图也是一个组件,理解了这一点之后,再来看代码会容易理解很多。
整体布局用了DirectionalLayout纵向布局,在里面有需要横向布局的,则添加DirectionalLayout的横向布局,做一个简单的嵌套。lt;?xmlversinotallow1。0encodingutf8?DirectionalLayoutxmlns:ohoshttp:schemas。huawei。comresohosohos:heightmatchparentohos:widthmatchparentohos:orientationverticalDirectionalLayoutohos:idid:dlohos:heightmatchcontentohos:widthmatchparentohos:orientationhorizontalohos:bottommargin20vpButtonohos:idid:backBtnohos:topmargin10vpohos:leftmargin10vpohos:rightmargin8vpohos:width40vpohos:height40vpohos:layoutalignmentleftohos:backgroundelementgraphic:backbuttonButtonohos:idid:setBtnohos:topmargin10vpohos:leftmargin8vpohos:rightmargin10vpohos:width40vpohos:height40vpohos:backgroundelementgraphic:setbuttonImageohos:layoutalignmentrightohos:topmargin10vpohos:leftmargin85vpohos:width40vpohos:height40vpohos:scalemodezoomcenterohos:imagesrcmedia:clockDirectionalLayoutImageohos:layoutalignmentcenterohos:width372vpohos:height35vpohos:scalemodezoomcenterohos:imagesrcmedia:goalohos:bottommargin20vpcom。example。pokemon。slice。GameMapohos:layoutalignmentcenterohos:idid:gameMap1ohos:widthmatchcontentohos:heightmatchcontentohos:bottommargin15vpDirectionalLayoutohos:height210vpohos:widthmatchparentohos:orientationhorizontalohos:topmargin20vpImageohos:layoutalignmentcenterohos:width158vpohos:height170vpohos:scalemodezoomcenterohos:imagesrcmedia:stackohos:bottommargin20vpButtonohos:idid:stackBtnohos:leftmargin15vpohos:bottommargin10vpohos:width150vpohos:height150vpohos:backgroundelementgraphic:buttonohos:text回退ohos:textsize50fpohos:textcolorfbc02dDirectionalLayoutDirectionalLayout
四个界面美化完毕!接下来做一些细节的调整。在按下历史记录按钮时,会显示每个关卡最近的一次历史记录,效果如下:
这实际上是一个自定义样式的CommonDialog,如何自定义?首先创建一个自定义的RecordDialog类和美化用的xml文件,然后在类里面添加自己的xml文件。
具体方法可以看代码:publicclassRecordDialog{staticCommonDialogcommonDialog;staticvoidshowDialog(Contextcontext,Strings1,Strings2,Strings3){DirectionalLayoutdl(DirectionalLayout)LayoutScatter。getInstance(context)。parse(ResourceTable。Layoutrecordlayout,null,false);commonDialognewCommonDialog(context);commonDialog。setAutoClosable(true);ButtonBtn(Button)dl。findComponentById(ResourceTable。IdBtn);Textfirst(Text)dl。findComponentById(ResourceTable。IdfirstText);first。setText(s1);Textsecond(Text)dl。findComponentById(ResourceTable。IdsecondText);second。setText(s2);Textthird(Text)dl。findComponentById(ResourceTable。IdthirdText);third。setText(s3);Btn。setClickedListener(newComponent。ClickedListener(){OverridepublicvoidonClick(Componentcomponent){commonDialog。destroy();}});commonDialog。setCornerRadius(15);commonDialog。setContentCustomComponent(dl)。show();}}
xml文件如下:lt;?xmlversinotallow1。0encodingutf8?DirectionalLayoutxmlns:ohoshttp:schemas。huawei。comresohosohos:heightmatchcontentohos:widthmatchcontentohos:orientationverticalTextohos:leftmargin5vpohos:rightmargin5vpohos:layoutalignmentleftohos:widthmatchcontentohos:heightmatchcontentohos:text最新通关记录:ohos:multiplelinestrueohos:topmargin20vpohos:textsize20fpTextohos:idid:firstTextohos:leftmargin120vpohos:rightmargin5vpohos:layoutalignmentleftohos:widthmatchcontentohos:heightmatchcontentohos:text第一关:无ohos:multiplelinestrueohos:topmargin10vpohos:textsize20fpTextohos:leftmargin120vpohos:rightmargin5vpohos:layoutalignmentleftohos:idid:secondTextohos:widthmatchcontentohos:heightmatchcontentohos:text第二关:无ohos:multiplelinestrueohos:topmargin10vpohos:textsize20fpTextohos:leftmargin120vpohos:rightmargin5vpohos:layoutalignmentleftohos:idid:thirdTextohos:widthmatchcontentohos:heightmatchcontentohos:text第三关:无ohos:multiplelinestrueohos:topmargin10vpohos:textsize20fpButtonohos:idid:okBtnohos:width250vpohos:height50vpohos:backgroundelementgraphic:backgroundabilitymainohos:textcolorffffffohos:textweight700ohos:textsize20vpohos:topmargin30vpohos:text确定ohos:bottommargin20vpohos:leftmargin40vpDirectionalLayout
关于这样的设计,这个小游戏中还有一处,点击关于游戏弹出的界面同样也是这么实现的:
代码如下:publicclassMyDialog{privatestaticTextversion;staticvoidshowDialog(Contextcontext){DirectionalLayoutdl(DirectionalLayout)LayoutScatter。getInstance(context)。parse(ResourceTable。Layoutmydialoglayout,null,false);CommonDialogcommonDialognewCommonDialog(context);commonDialog。setAutoClosable(true);ButtonknowBtn(Button)dl。findComponentById(ResourceTable。IdknowBtn);knowBtn。setClickedListener(newComponent。ClickedListener(){OverridepublicvoidonClick(Componentcomponent){commonDialog。destroy();}});commonDialog。setCornerRadius(15);commonDialog。setContentCustomComponent(dl)。show();}staticStringgetVersion(){returnversion。getText();}}lt;?xmlversinotallow1。0encodingutf8?DirectionalLayoutxmlns:ohoshttp:schemas。huawei。comresohosohos:heightmatchcontentohos:widthmatchcontentohos:orientationverticalohos:alignmentcenterTextohos:leftmargin5vpohos:rightmargin5vpohos:layoutalignmentleftohos:widthmatchcontentohos:heightmatchcontentohos:text游戏目标:收服在场的所有宝可梦!ohos:multiplelinestrueohos:topmargin20vpohos:textsize20fpTextohos:leftmargin5vpohos:rightmargin5vpohos:layoutalignmentleftohos:widthmatchcontentohos:heightmatchcontentohos:text游戏玩法:通过滑动屏幕控制人物,推动精灵球收服宝可梦,当收服完所有宝可梦时获得游戏胜利!ohos:multiplelinestrueohos:topmargin10vpohos:textsize20fpTextohos:leftmargin5vpohos:rightmargin5vpohos:layoutalignmentleftohos:idid:versionTextohos:widthmatchcontentohos:heightmatchcontentohos:text游戏版本号:V1。0。0ohos:multiplelinestrueohos:topmargin10vpohos:textsize20fpTextohos:leftmargin5vpohos:rightmargin5vpohos:layoutalignmentleftohos:idid:showTextohos:widthmatchcontentohos:heightmatchcontentohos:text开发人员:木棉花蓝锐鑫ohos:multiplelinestrueohos:topmargin10vpohos:textsize20fpButtonohos:idid:knowBtnohos:width250vpohos:height50vpohos:backgroundelementgraphic:backgroundabilitymainohos:textcolorffffffohos:textweight700ohos:textsize20vpohos:topmargin30vpohos:text已了解ohos:bottommargin20vpDirectionalLayout
游戏中最后一处UI设计,就是点击设置按钮时出现的一个滑动块组件,可以保存一些全局设置:
publicclassSetDialog{staticvoidshowDialog(Contextcontext){DirectionalLayoutdl(DirectionalLayout)LayoutScatter。getInstance(context)。parse(ResourceTable。Layoutsetlayout,null,false);CommonDialogcommonDialognewCommonDialog(context);commonDialog。setAutoClosable(true);ButtonsureBtn(Button)dl。findComponentById(ResourceTable。IdsureBtn);Switchchoose(Switch)dl。findComponentById(ResourceTable。Idchoose);StringvalueMyDB。getString(dl。getContext(),save);if(value!null){if(value。compareTo(开)0){choose。setChecked(true);}elseif(value。compareTo(关)0){choose。setChecked(false);}}choose。setCheckedStateChangedListener(newAbsButton。CheckedStateChangedListener(){OverridepublicvoidonCheckedChanged(AbsButtonabsButton,booleanb){Stringkeysave;if(b){MyDB。putString(dl。getContext(),key,开);}else{MyDB。putString(dl。getContext(),key,关);}}});sureBtn。setClickedListener(newComponent。ClickedListener(){OverridepublicvoidonClick(Componentcomponent){commonDialog。destroy();}});commonDialog。setCornerRadius(15);commonDialog。setContentCustomComponent(dl)。show();}}lt;?xmlversinotallow1。0encodingutf8?DirectionalLayoutxmlns:ohoshttp:schemas。huawei。comresohosohos:heightmatchcontentohos:widthmatchcontentohos:orientationverticalDirectionalLayoutohos:idid:dlohos:heightmatchcontentohos:widthmatchcontentohos:orientationhorizontalTextohos:leftmargin70vpohos:rightmargin25vpohos:layoutalignmentleftohos:idid:thirdTextohos:widthmatchcontentohos:heightmatchcontentohos:text自动保存ohos:multiplelinestrueohos:topmargin10vpohos:textsize30fpSwitchohos:idid:chooseohos:height40vpohos:width100vpohos:topmargin10vpohos:textstateon开ohos:textstateoff关ohos:textcolorffffffohos:textsize20fpohos:thumbelementeff1f8ohos:trackelementf9bf2dDirectionalLayoutButtonohos:idid:sureBtnohos:width250vpohos:height50vpohos:backgroundelementgraphic:backgroundabilitymainohos:textcolorffffffohos:textweight700ohos:textsize20vpohos:topmargin30vpohos:text确定ohos:bottommargin20vpohos:leftmargin40vpDirectionalLayout
至此,UI美化部分已经全部完成。
数据存储
这里用到轻量级偏好数据库,关于数据库怎么使用,可以看这篇文章,文章写得很详细!https:ost。51cto。composts7911
利用数据库存储每个关卡的信息,首先要新建一个数据库类MyDB:publicclassMyDB{privatestaticfinalStringPREFERENCEFILENAMEDB;privatestaticPreferencespreferences;privatestaticDatabaseHelperdatabaseHelper;privatestaticPreferences。PreferencesObservermPreferencesObserver;privatestaticvoidinitPreference(Contextcontext){if(databaseHelpernull){databaseHelpernewDatabaseHelper(context);}if(preferencesnull){preferencesdatabaseHelper。getPreferences(PREFERENCEFILENAME);}}publicstaticvoidputString(Contextcontext,Stringkey,Stringvalue){initPreference(context);preferences。putString(key,value);preferences。flush();}publicstaticStringgetString(Contextcontext,Stringkey){initPreference(context);returnpreferences。getString(key,null);}publicstaticbooleandeletePreferences(Contextcontext){initPreference(context);booleanisDeletedatabaseHelper。deletePreferences(PREFERENCEFILENAME);returnisDelete;}publicstaticvoidregisterObserver(Contextcontext,Preferences。PreferencesObserverpreferencesObserver){initPreference(context);mPreferencesObserverpreferencesObserver;preferences。registerObserver(mPreferencesObserver);}publicstaticvoidunregisterObserver(){if(mPreferencesObserver!null){向preferences实例注销观察者preferences。unregisterObserver(mPreferencesObserver);}}}
在结束游戏时,如果打开了自动保存按钮,则进行存储:if(gameMap。isWin()){tickTimer。stop();CommonDialogcommonDialognewCommonDialog(getContext());commonDialog。setSize(800,400);commonDialog。setTitleText(注意);commonDialog。setContentText(恭喜您完成游戏!!!);commonDialog。setButton(0,确定,newIDialog。ClickedListener(){OverridepublicvoidonClick(IDialogiDialog,inti){commonDialog。destroy();StringvalueMyDB。getString(getContext(),save);if(value!null){if(value。compareTo(开)0){MyDB。putString(getContext(),key,tickTimer。getText());}}present(newSelectSlice(),newIntent());terminate();}});commonDialog。show();}
在点击历史记录时,会进行数据读取:历史记录按钮recordBtn。setClickedListener(newComponent。ClickedListener(){OverridepublicvoidonClick(Componentcomponent){String〔〕s{第一关:无,第二关:无,第三关:无};StringfirstMyDB。getString(getContext(),first);StringsecondMyDB。getString(getContext(),second);StringthirdMyDB。getString(getContext(),third);if(firstnull){firsts〔0〕;}else{first第一关:first;}if(secondnull){seconds〔1〕;}else{second第二关:second;}if(thirdnull){thirds〔2〕;}else{third第三关:third;}RecordDialog。showDialog(getContext(),first,second,third);}});
开启自动保存,才会在游戏结束时存进数据库,实际上也是利用数据库中某个key中的value控制。
具体实现如下:choose。setCheckedStateChangedListener(newAbsButton。CheckedStateChangedListener(){OverridepublicvoidonCheckedChanged(AbsButtonabsButton,booleanb){Stringkeysave;if(b){MyDB。putString(dl。getContext(),key,开);}else{MyDB。putString(dl。getContext(),key,关);}}});
至此,项目已经全部分享完成,由于作品中涉及大量的图片资源均是网络资源(避免侵权),故仅作学习交流使用,实际上,绝大部分代码已经在文章中了,剩下的就是读者理解之后动手衔接起来!一定要动手!