Loading...
首页专栏正文

在鸿蒙上撸手机APP的引导页!

程序员小明 发布于 2021-08-30 16:26:20 浏览 2431 点赞 92 收藏 0

手机 APP 的引导页是一个常见的功能,今天和大家一起分享在鸿蒙系统的撸引导页代码的经验。

应用引导页的功能

①为什么要做应用的引导功能?

几乎所有的 App 都会有做一些界面引导,有的是页面交互的引导,有的是为了介绍新功能。

②通用的功能性引导大概分哪些呢?

主功能引导、新功能引导和功能转移或改名引导。

③通用的应用引导,需要注意哪些?

引导的内容文字不宜太长,适当加入一些图案可以方便用户理解。言归正传吧,开始咱们今天的主题,如何实现应用的引导功能吧!

实现应用的引导功能

具体步骤如下:

首先来看看讨论的引导功能的效果吧!点击引导页,向上滑动过程,第一个界面图案和文字渐变消失的过程。

而第二页界面的图片和文字渐渐清晰可见。底部 Next 图标会下滑隐藏再弹出的动画效果。

开发准备

搭建鸿蒙开发环境,这里就不做介绍了,如果没有环境没有搭建好的同学可以进入学习安装环境, 安装好环境以后接下来我们就可以进行开发工作了。

①设计思路

首先我们做的是公用的组件,我们需要使用组件化思想去搭建我们的项目框架,接下来根据组件的需求我们先去设计一下界面。

设计好之后我们需要对页面添加数据,添加完数据之后组件的大体界面已经展示给我们,下来就是在滑动 page 的时候添加底部 button 的回弹动画,并且在此时我们需要操作 page 的子 view。最后我们要去使用我们的组件。

②设计步骤

(1)设计界面

根据我们要实现的功能,我们可以使用 PageSlider 控件去实现界面布局文件,实现代码为: <PageSlider ohos:id="$+id:vertical_view_pager" ohos:width="match_parent" ohos:height="match_parent" >

添加数据、初始化数据:

public void setData() { super.setData(); pageColors = new ArrayList<>(); pageColors.add(getString(ResourceTable.Color_colorAccent)); pageColors.add(getString(ResourceTable.Color_color2)); pageColors.add(getString(ResourceTable.Color_colorPrimary)); pageColors.add(getString(ResourceTable.Color_color3)); pageMoudles = getData(); }

private List getData() { String textValue = "Lorem Ipsum is simply dummy text of the printing and typesetting industry."; PageMoudle pageMoudleOne = new PageMoudle(); pageMoudleOne.setRecoureId(ResourceTable.Graphic_intro_second_vector); pageMoudleOne.setBackGroudRgbColor(RgbColor.fromArgbInt(Color.getIntColor(pageColors.get(0)))); pageMoudleOne.setTitle("Lorem Ipsum Lorem Ipsum");

pageMoudleOne.setText(textValue + textValue + textValue);
pageMoudleOne.setTitleSize(17);
pageMoudleOne.setTextSize(14);
List<PageMoudle> datas = new ArrayList<>();
datas.add(pageMoudleOne);

PageMoudle pageMoudleTwo = new PageMoudle();
pageMoudleTwo.setRecoureId(ResourceTable.Graphic_four);
    pageMoudleTwo.setBackGroudRgbColor(RgbColor.fromArgbInt(Color.getIntColor(pageColors.get(1))));
pageMoudleTwo.setTitle("Lorem Ipsum Lorem Ipsum ");
pageMoudleTwo.setText(textValue + textValue);
datas.add(pageMoudleTwo);

PageMoudle pageMoudleThree = new PageMoudle();
pageMoudleThree.setRecoureId(ResourceTable.Graphic_ohos);
    pageMoudleThree.setBackGroudRgbColor(RgbColor.fromArgbInt(Color.getIntColor(pageColors.get(2))));
pageMoudleThree.setTitle("Lorem Ipsum");
pageMoudleThree.setText(textValue);
datas.add(pageMoudleThree);

PageMoudle pageMoudleFour = new PageMoudle();
pageMoudleFour.setRecoureId(ResourceTable.Media_new_intro);
    pageMoudleFour.setBackGroudRgbColor(RgbColor.fromArgbInt(Color.getIntColor(pageColors.get(3))));
pageMoudleFour.setTitle("Lorem Ipsum");
pageMoudleFour.setText(textValue + textValue + textValue);
datas.add(pageMoudleFour);
return datas;

}

设置 provider:

pageSlider = (PageSlider) findComponentById(ResourceTable.Id_vertical_view_pager);
pageSlider.setOrientation(Component.VERTICAL);
pageSlider.addPageChangedListener(this);
pageSlider.setTouchEventListener(this::onTouchEvent);
adapter = new VerticalIntroPagerAdapter(this, pageMoudles);
pageSlider.setProvider(adapter);

(2)添加动画

这里我们使用属性动画去完成底部 button 的上弹和下弹操作,上弹和下弹是和我们手指滑动的方向是有关系的。

所以这里我们必须实现手指的触摸事件,在触摸事件中获取我们手机滑动的距离,如果距离大于 0 则是下滑,如果小于 0 则是下滑。

获取是上滑还是下滑代码如下:

@Override public boolean onTouchEvent(Component component, TouchEvent touchEvent) { int action = touchEvent.getAction(); switch (action) { case TouchEvent.PRIMARY_POINT_DOWN: pageSlider.setSlidingPossible(true); startPointY = getTouchY(touchEvent, 0, component); return true; case TouchEvent.POINT_MOVE: movePointY = getTouchY(touchEvent, touchEvent.getIndex(), component) - startPointY; if (page != 0 && movePointY > 0) { WindowManager.getInstance().getTopWindow().get().setStatusBarColor(getColorByString(pageColors.get(page - 1))); } return true; case TouchEvent.PRIMARY_POINT_UP: return true; default: } return false; }

获取到上滑还是下滑后,接下来就去给底部 button 设置动画。动画用的是属性动画,属性动画大体实现是初始化动画,设置动画持续时间,实现动画属性值变化监听事件,最后启动动画。

大体代码如下:

private void startChangeButtonBg(int direction, int duration) { if (animatorValue == null) { animatorValue = new AnimatorValue(); } animatorValue.setCurveType(Animator.CurveType.LINEAR); animatorValue.setDuration(duration); animatorValue.setValueUpdateListener(new AnimatorValue.ValueUpdateListener() { @Override public void onUpdate(AnimatorValue animatorValue, float v) { if (direction <= 0) { double value = ((1 - (double)v) nextHeight) direction; next.setMarginBottom((int) value); } else { float value = -(v * nextHeight); next.setMarginBottom((int) value); if (v > 0.9) { if (page == 3) { skip.setVisibility(Component.INVISIBLE); next.setText("DONE"); next.setNormalColor(pageColors.get(1)); } else { skip.setVisibility(Component.VISIBLE); next.setText("NEXT"); next.setNormalColor(pageColors.get(page + 1)); } next.setMarginBottom(0); } } } }); setAnimStateChangeList(direction); animatorValue.start(); }

private void setAnimStateChangeList(int direction) { animatorValue.setStateChangedListener(new Animator.StateChangedListener() { @Override public void onStart(Animator animator) { if (direction <= 0) { if (page == 3) { skip.setVisibility(Component.INVISIBLE); next.setText("DONE"); next.setNormalColor(pageColors.get(1)); } else { skip.setVisibility(Component.VISIBLE); next.setText("NEXT"); next.setNormalColor(pageColors.get(page + 1)); } } } @Override public void onStop(Animator animator) { } @Override public void onCancel(Animator animator) { } @Override public void onEnd(Animator animator) { movePointY = 0; } @Override public void onPause(Animator animator) { } @Override public void onResume(Animator animator) { } }); }

(3)操作子 view

如何去操作子 view 呢?首先我们先去看看 PageSlider 是否有子 view 的操作监听接口,查看 api 后没有这样的接口获取方法,那就得我们自己去考虑怎么实现呢。

我这里的实现思路是在 PageSlider 设置 provider 的时候保存所有的子 view 对象,然后再使用的时候拿出子 view 再进行操作。

我们这里例子是改变子 view 的透明度。代码实现如下:

保存子 view:

public class VerticalIntroPagerAdapter extends PageSliderProvider { LinkedHashMap<Integer, Component> pageComonents; public VerticalIntroPagerAdapter(Context context, List datas) { this.context = context; this.datas = datas; pageComonent = new ArrayList<>(); // 初始化用来添加子view的集合,注意这里是一个有序集合 pageComonents = new LinkedHashMap<Integer, Component>(); } //添加子view @Override public Object createPageInContainer(ComponentContainer componentContainer, int i) { if (!pageComonents.containsValue(component)) { pageComonents.put(i, component); } } }

操作子 view:

private void setPageApale(int currentPage, int targetPage, float offset) { if (adapter.pageComonents != null && adapter.pageComonents.get(currentPage) != null && adapter.pageComonents.get(targetPage) != null) { float alpha = new BigDecimal(1.0f).subtract(new BigDecimal(offset).multiply(new BigDecimal(2))).floatValue(); if (offset >= 0.4 && offset <= 0.9) { offset = new BigDecimal(offset).subtract(new BigDecimal( 0.4f)).floatValue(); } else if (offset < 0.4) { offset = 0.0f; } else { offset = 1.0f; } setApale(currentPage, targetPage, alpha, offset); } }

到这里我们的竖直引导工具组件就已经封装好了。

(4)使用组件

如何去使用我们的组件呢?这里我们用的是组件化思想。所以我们呢只需要在我们的项目中引入我们的组件,然后在我们的 ablity 中集成我们封装好的 VerticalIntroSlice 对象就行。

最后我们再把封装一个添加数据的接口,把我们的数据变成动态添加的就行。

结语

到此我们的整个设计流程就完了,通过上面的操作,相信小伙伴们就可以实现应用引导功能了。

来源:鸿蒙技术社区

*本文仅代表作者观点,不代表易百纳技术社区立场。系作者授权易百纳技术社区发表,未经许可不得转载。

精彩评论

内容存在敏感词
打赏
打赏作者
程序员小明
您的支持将鼓励我继续创作!
金额:
¥1 ¥5 ¥10 ¥50 ¥100
支付方式:
微信支付
支付宝支付
微信支付
打赏成功!

感谢您的打赏,如若您也想被打赏,可前往 发表专栏 哦~

易百纳技术社区
确定要删除此文章、专栏、评论吗?
确定
取消
易百纳技术社区