项目作者: cherishyan

项目描述 :
实现的一些功能合集,包括React-Native,MVP,FullPage Guide WebView,NavigationBar,RX系列,5.0MD相关
高级语言: Java
项目地址: git://github.com/cherishyan/Widgets.git
创建时间: 2016-12-12T07:16:22Z
项目社区:https://github.com/cherishyan/Widgets

开源协议:

关键词:
android-mvp react-native rx

下载


小控件,方法合集


Python脚本替换Android资源(包名,图片,文件内容)


Android引导页动画(RxJava)

最近在考虑用新的形式构建APP的欢迎页和引导页,发现一个不错的过渡动画,主要是图片的灰度和放大效果,进入后延迟一秒开始动画。
使用RxJava的Timer操作符实现延迟。


H5引导页

前端的fullpage展示已经在非常多的站点上使用了,这里尝试将Android的引导页换成fullpage的网页动画,这里是示例图片,添加更多动画元素以后效果应该非常不错。

  • 首先我替换了原生的webview控件,改成了腾讯x5的webviewSDK,低配的手机上加强了性能体验(虽然感觉冷启动过程好像长了点…)

  • 在asserts文件夹中建立一个web项目文件夹,如web_page,然后用前端开发工具(我是用的sublime text3)实现fullpage引导页。

  • Tencent webview调用本地HTML资源:

  1. mWeb.loadUrl("file:///android_asset/web_page/page.html");

Android MVP 实践

RecyclerView刷新控件及CoordinatorLayout合用实现

效果:

IRecyclerView

Material 登录注册界面效果

效果:

materialLogin

BottomNavigationBar 底部导航栏

在MainActivity中添加了Material design风格的底部导航栏:BottomNavigation
但是在引入过程中发现,单个tab点击的时候都有放大效果,这不符合我的设计风格,作者并没有添加控制点击动画的API,于是自己动手,下载源码开始修改。

  • 首先我们在BottomNavigationBar类中发现初始化过程:
  1. public void initialise() {
  2. mSelectedPosition = DEFAULT_SELECTED_POSITION;
  3. mBottomNavigationTabs.clear();
  4. if (!mBottomNavigationItems.isEmpty()) {
  5. mTabContainer.removeAllViews();
  6. if (mMode == MODE_DEFAULT) {
  7. if (mBottomNavigationItems.size() <= MIN_SIZE) {
  8. mMode = MODE_FIXED;
  9. } else {
  10. mMode = MODE_SHIFTING;
  11. }
  12. }
  13. if (mBackgroundStyle == BACKGROUND_STYLE_DEFAULT) {
  14. if (mMode == MODE_FIXED) {
  15. mBackgroundStyle = BACKGROUND_STYLE_STATIC;
  16. } else {
  17. mBackgroundStyle = BACKGROUND_STYLE_RIPPLE;
  18. }
  19. }
  20. if (mBackgroundStyle == BACKGROUND_STYLE_STATIC) {
  21. mBackgroundOverlay.setVisibility(View.GONE);
  22. mContainer.setBackgroundColor(mBackgroundColor);
  23. }
  24. int screenWidth = Utils.getScreenWidth(getContext());
  25. if (mMode == MODE_FIXED) {
  26. int[] widths = BottomNavigationHelper.getMeasurementsForFixedMode(getContext(), screenWidth, mBottomNavigationItems.size(), mScrollable);
  27. int itemWidth = widths[0];
  28. for (BottomNavigationItem currentItem : mBottomNavigationItems) {
  29. FixedBottomNavigationTab bottomNavigationTab = new FixedBottomNavigationTab(getContext());
  30. setUpTab(bottomNavigationTab, currentItem, itemWidth, itemWidth);
  31. }
  32. } else if (mMode == MODE_SHIFTING) {
  33. int[] widths = BottomNavigationHelper.getMeasurementsForShiftingMode(getContext(), screenWidth, mBottomNavigationItems.size(), mScrollable);
  34. int itemWidth = widths[0];
  35. int itemActiveWidth = widths[1];
  36. for (BottomNavigationItem currentItem : mBottomNavigationItems) {
  37. ShiftingBottomNavigationTab bottomNavigationTab = new ShiftingBottomNavigationTab(getContext());
  38. setUpTab(bottomNavigationTab, currentItem, itemWidth, itemActiveWidth);
  39. }
  40. }
  41. if (mBottomNavigationTabs.size() > mFirstSelectedPosition) {
  42. selectTabInternal(mFirstSelectedPosition, true, false, false);
  43. } else if (!mBottomNavigationTabs.isEmpty()) {
  44. selectTabInternal(0, true, false, false);
  45. }
  46. }
  47. }

mMode代表不同的点击效果,一般底部导航栏不超过3个时,都是MODE_FIXED模式,超过则为MODE_SHIFTING模式。我们希望修改MODE_FIXED模式下的点击动画,于是找到:

  1. if (mMode == MODE_FIXED) {
  2. int[] widths = BottomNavigationHelper.getMeasurementsForFixedMode(getContext(), screenWidth, mBottomNavigationItems.size(), mScrollable);
  3. int itemWidth = widths[0];
  4. for (BottomNavigationItem currentItem : mBottomNavigationItems) {
  5. FixedBottomNavigationTab bottomNavigationTab = new FixedBottomNavigationTab(getContext());
  6. setUpTab(bottomNavigationTab, currentItem, itemWidth, itemWidth);
  7. }
  8. }

跟进setUpTab这个方法:

  1. /**
  2. * Internal method to setup tabs
  3. *
  4. * @param bottomNavigationTab Tab item
  5. * @param currentItem data structure for tab item
  6. * @param itemWidth tab item in-active width
  7. * @param itemActiveWidth tab item active width
  8. */
  9. private void setUpTab(BottomNavigationTab bottomNavigationTab, BottomNavigationItem currentItem, int itemWidth, int itemActiveWidth) {
  10. bottomNavigationTab.setInactiveWidth(itemWidth);
  11. bottomNavigationTab.setActiveWidth(itemActiveWidth);
  12. bottomNavigationTab.setPosition(mBottomNavigationItems.indexOf(currentItem));
  13. bottomNavigationTab.setOnClickListener(new OnClickListener() {
  14. @Override
  15. public void onClick(View v) {
  16. BottomNavigationTab bottomNavigationTabView = (BottomNavigationTab) v;
  17. selectTabInternal(bottomNavigationTabView.getPosition(), false, true, false);
  18. }
  19. });
  20. mBottomNavigationTabs.add(bottomNavigationTab);
  21. BottomNavigationHelper.bindTabWithData(currentItem, bottomNavigationTab, this);
  22. bottomNavigationTab.initialise(mBackgroundStyle == BACKGROUND_STYLE_STATIC);
  23. mTabContainer.addView(bottomNavigationTab);
  24. }

发现底部图标和文字由bottomNavigationTab控制,跟进bottomNavigationTab发现可以设置item选中和非选中的状态,这正是我想要修改的:

  1. public void select(boolean setActiveColor, int animationDuration) {
  2. isActive = true;
  3. ValueAnimator animator = ValueAnimator.ofInt(containerView.getPaddingTop(), paddingTopActive);
  4. animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
  5. @Override
  6. public void onAnimationUpdate(ValueAnimator valueAnimator) {
  7. containerView.setPadding(containerView.getPaddingLeft(),
  8. (Integer) valueAnimator.getAnimatedValue(),
  9. containerView.getPaddingRight(),
  10. containerView.getPaddingBottom());
  11. }
  12. });
  13. animator.setDuration(animationDuration);
  14. animator.start();
  15. iconView.setSelected(true);
  16. if (setActiveColor) {
  17. labelView.setTextColor(mActiveColor);
  18. } else {
  19. labelView.setTextColor(mBackgroundColor);
  20. }
  21. if (badgeItem != null) {
  22. badgeItem.select();
  23. }
  24. }

也就是说我们给这个属性动画加上一个控制就可以了,那应该在BottomNavigationBar设置的时候传入进来,于是我在BottomNavigationBar加入了mIconAnimation变量。

  1. private void setUpTab(BottomNavigationTab bottomNavigationTab, BottomNavigationItem currentItem, int itemWidth, int itemActiveWidth) {
  2. bottomNavigationTab.setInactiveWidth(itemWidth);
  3. bottomNavigationTab.setActiveWidth(itemActiveWidth);
  4. bottomNavigationTab.setPosition(mBottomNavigationItems.indexOf(currentItem));
  5. /** modified here **/
  6. if (mMode != MODE_SHIFTING)
  7. bottomNavigationTab.setIconAnimation(mIconAnimation);//1111
  8. bottomNavigationTab.setTextSize(mLabelTextSize);//1111
  9. bottomNavigationTab.setOnClickListener(new OnClickListener() {
  10. @Override
  11. public void onClick(View v) {
  12. BottomNavigationTab bottomNavigationTabView = (BottomNavigationTab) v;
  13. selectTabInternal(bottomNavigationTabView.getPosition(), false, true, false);
  14. }
  15. });
  16. mBottomNavigationTabs.add(bottomNavigationTab);
  17. BottomNavigationHelper.bindTabWithData(currentItem, bottomNavigationTab, this);
  18. bottomNavigationTab.initialise(mBackgroundStyle == BACKGROUND_STYLE_STATIC);
  19. mTabContainer.addView(bottomNavigationTab);
  20. }

BottomNavigationTab中在动画部分添加一个判断控制即可。

React-native 相关实践

详见 Home3Fragment,react-src


Android CollapsingToolbarLayout 和ToolBar多种实践

CollapsingToolbarLayout

详见 Home4fragment


Canvas Xfermode 绘制引导页蒙层

详见: http://www.jianshu.com/p/4f9fbcce3bf8


HorizontalTimeLineLinearLayout

类似横向的时间轴,主要是计算单个View的padding值作为当前timeline point的x值,再将起点和终点绘制一条线即可。

详见 TimeLineShowActivity

效果:

HorizontalTimeLineLinearLayout