前言

这个月,说实话,有忙有闲,经历了一次病痛的洗礼,才认识到了只有好好的生活,认真的对待自己的身体,才能更好的去工作,没有了身体的支撑,什么工作都只能是纸老虎,不攻自破。在这里也祝愿大家,在生活中好好对待自己,身体第一,工作第二。

为什么要写这个app

群里的一个哥们前几天晚上给我看了一下一个app,我粗略看了下界面(还没运行下载,他给我发的),我看了一下,感觉挺不错的,当时心里一热,哈哈,这不是挺简单的么,几天就搞完了,但是当我去下载的时候,看到了30-40MB的大小,我惊呆了,要知道一个淘宝才那么大。哈哈,不过还是被这个界面吸引了,而且里面的内容也挺不错的,大多关于心理方面的。那就自己模仿一下吧,顺带的自己去学习一下,因为这个app涉及到的知识点挺多(即时通讯、直播、视屏播放、第三方登录),想着自己就慢慢的写,然后去学习一下会用到的知识,伴随着这样的想法,就有了这个MyHearts项目。

几个小知识点

一、进入到主界面,可以看到下方的几个Tab键,原本想着是用FragmentTabhost实现,但是看到中间的那个Tab键和其他的按键是不同等高度的,而且这个还是有动画效果的,后面想着,如果用framelayout覆盖在上面应该是可以实现的,但是动画呢,这个时候想到之前用到的帧动画,想必这个帧动画也是可以实现的,然后自己就去试了试,结果还真给实现了,对于程序这东西来说,当别人问这个能不能实现,我在这个地方加一个字段、加个方法,可以实现么,我想说的就是,既然已经想到了,那就试一下呗,行了就证明方法可以,不行证明需要找其他的方法,最重要的是动手写程序,程序不是问出来的,而是一句一句代码积累出来的。

<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"android:oneshot="false"><itemandroid:drawable="@mipmap/main_layout_center_image_1"android:duration="100"/><itemandroid:drawable="@mipmap/main_layout_center_image_2"android:duration="100"/><itemandroid:drawable="@mipmap/main_layout_center_image_3"android:duration="100"/><itemandroid:drawable="@mipmap/main_layout_center_image_4"android:duration="100"/><itemandroid:drawable="@mipmap/main_layout_center_image_5"android:duration="100"/><itemandroid:drawable="@mipmap/main_layout_center_image_6"android:duration="100"/><itemandroid:drawable="@mipmap/main_layout_center_image_7"android:duration="100"/><itemandroid:drawable="@mipmap/main_layout_center_image_8"android:duration="100"/><itemandroid:drawable="@mipmap/main_layout_center_image_9"android:duration="100"/>//这里并没有写完,可以直接去代码里面查看,最后会附上git地址</animation-list>

在代码中这样就可以执行动画了

// 获取ImageView上的动画背景AnimationDrawable spinnerImg = (AnimationDrawable) mIvImg.getBackground();// 开始动画spinnerImg.start();

这样就可以实现直播和life动画的切换了。

二、心事界面的图片展示,之前在用postman(用于接口调试的,值得推荐)请求数据接口的时候,看到里面有个photos字段,并不是所有的item都有这个字段,而且里面个数不一,但都是一个图片地址,想着应该是类似于qq空间发表说说的附带的图片。自己想着用RecyclerView实现,因为这个是很好实现的,但是我在看到okgo(本项目的网络请求框架,支持Rx,挺不错的)项目中,他的项目也有这个类似的功能,用到的就是NineGridView(https://github.com/jeasonlzy/NineGridView),okgo这个项目也是这位大神写的。这个也是很简单使用的,他是在ViewGroup的基础上自定义的。用法也是很简单,如下

 //也就是用户发朋友圈的那种,添加图片List<String> images = bean.getPhotos();if (images != null) {for (String image : images) {//ImageInfo 是他的实体类,用于image的地址ImageInfo info = new ImageInfo();info.setThumbnailUrl(image);info.setBigImageUrl(image);imageInfo.add(info);}}holder.mPhotoRecycler.setAdapter(new NineGridViewClickAdapter(mContext, imageInfo));if (images != null && images.size() == 1) {//如果用户只发了一张图片的话,就设置图片的宽和高holder.mPhotoRecycler.setSingleImageSize(300);holder.mPhotoRecycler.setSingleImageRatio(1);//holder.mPhotoRecycler.setSingleImageRatio(images.get(0).width * 1.0f / images.get(0).height);}

实现的结果如下:

三、二级评论列表,这个我一直想不到好的解决办法(在我脑海里一直以为有更好的方法),这里我就是用的item里面嵌套一个RecyclerView,得到的comment list,然后在进行item分配。如果有好的,请告知。谢谢啦。
这里就看下代码,也没什么可写的,无非就是RecyclerView嵌套RecyclerView

  List<CommentsBean> comments = bean.getComments();if (comments != null && comments.size() > 0) {CommentAdapter adapter = new CommentAdapter(comments);holder.mCommentRe.setVisibility(View.VISIBLE);holder.mCommentRecycler.setLayoutManager(new LinearLayoutManager(mContext));//  holder.mCommentRecycler.addItemDecoration(new DividerItemDecoration(mContext//,DividerItemDecoration.VERTICAL_LIST));holder.mCommentRecycler.setItemAnimator(new DefaultItemAnimator());holder.mCommentRecycler.setAdapter(adapter);}

对于评论里面的回复和被回复者,为了便于区分,我这里使用到了SpanableString。类似于下面:

CommentsBean bean = mCommentsBeen.get(position);//评论用户String profileName = bean.getName();//被回复者  如果为空  默认回复发帖者String replayName = bean.getReplyToUserName();StringBuffer sb = new StringBuffer();sb.append(profileName);sb.append(" ");String replay = mContext.getResources().getString(R.string.replay_comment);if (!replayName.equals("")) {  //判断是否有被回复的,没有就是默认发帖者sb.append(replay);sb.append(replayName);}String commentContent = bean.getContent();sb.append(commentContent);// String result = ;SpannableString msp = new SpannableString(sb.toString());//对评论者进行颜色配置msp.setSpan(new ForegroundColorSpan(Color.BLUE), 0,profileName.length(),Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);//如果有被回复的对象,那么被回复的对象也要进行颜色配置if (!replayName.equals("")) {int start = profileName.length() + 3;int end = start + replayName.length();msp.setSpan(new ForegroundColorSpan(Color.BLUE), start, end,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);}//这个地方要直接设置成msp  不能用msp.toString() 要不然没有样式holder.mTvCommentContent.setText(msp);

效果图,大家可以git代码去运行一下。
四、之前用到左滑出菜单栏,第一个是Draglayout,但是这个存在冲突,滑动不是很流畅,自己后面换到了git上的一个仿QQ5.2的,但是和自己app里面的轮播(从左向右滑动的时候,会带出左侧边栏,还有就是心事界面的Tablayout也是存在同样的方式,后面自己想到了应该是用到的ViewPager滑动事件的问题,就想着之前用到的,就重写了ViewPager,然后处理了一些逻辑,基本解决了冲突),代码如下:

/*** 事件分发,请求父控件是否拦截* <p/>* 1、右滑,而且是第一个页面,需要父控件拦截* <p/>* 2、左滑,而且当前的页面是最后一个页面,需要父控件拦截* <p/>* 3、上下滑动,需要父控件拦截** @param ev* @return*/@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {/*** 用getParent()去请求,请求父控件是否不要拦截滑动事件*/switch (ev.getAction()) {case MotionEvent.ACTION_DOWN://先去让父控件不要拦截,这样才可能走到ACTION_MOVE方法调用getParent().requestDisallowInterceptTouchEvent(true);/*** 拿到刚开始按下的时候的坐标*/startX = (int) ev.getRawX();startY = (int) ev.getRawY();break;case MotionEvent.ACTION_MOVE:/*** 获取到移动之后的坐标*/int endX = (int) ev.getRawX();int endY = (int) ev.getRawY();//左右滑动if (Math.abs(endX - startX) > Math.abs(endY - startY)) {if (endX > startX) {//右滑//获取到第一个 需要父控件拦截if (getCurrentItem() == 0) {getParent().requestDisallowInterceptTouchEvent(false);}} else if (endX <= startX) {//左滑//获取到最后一个// 需要父控件拦截if (getCurrentItem() == getAdapter().getCount() - 1) {getParent().requestDisallowInterceptTouchEvent(false);}}} else {//上下滑动getParent().requestDisallowInterceptTouchEvent(false);}break;default:break;}return super.dispatchTouchEvent(ev);}

哈哈,最后还是换成了DrawerLayout,不存在了滑动的冲突BUG了,Drawerlayout默认划出是覆盖在主界面上的,这里为了模仿的比较像,就重写了一些逻辑(hongyang大神的博客中有介绍)

 mDrawerLayout.setDrawerListener(new DrawerLayout.DrawerListener() {@Overridepublic void onDrawerSlide(View drawerView, float slideOffset) {View mContent = mDrawerLayout.getChildAt(0);View mMenu = drawerView;float scale = 1 - slideOffset;float rightScale = 0.8f + scale * 0.2f;if (drawerView.getTag().equals("LEFT")){float leftScale = 1 - 0.3f * scale;ViewHelper.setScaleX(mMenu, leftScale);ViewHelper.setScaleY(mMenu, leftScale);ViewHelper.setAlpha(mMenu, 0.6f + 0.4f * (1 - scale));ViewHelper.setTranslationX(mContent,mMenu.getMeasuredWidth() * (1 - scale));ViewHelper.setPivotX(mContent, 0);ViewHelper.setPivotY(mContent,mContent.getMeasuredHeight() / 2);mContent.invalidate();ViewHelper.setScaleX(mContent, rightScale);ViewHelper.setScaleY(mContent, rightScale);} else{ViewHelper.setTranslationX(mContent,-mMenu.getMeasuredWidth() * slideOffset);ViewHelper.setPivotX(mContent, mContent.getMeasuredWidth());ViewHelper.setPivotY(mContent,mContent.getMeasuredHeight() / 2);mContent.invalidate();ViewHelper.setScaleX(mContent, rightScale);ViewHelper.setScaleY(mContent, rightScale);}}@Overridepublic void onDrawerOpened(View drawerView) {}@Overridepublic void onDrawerClosed(View drawerView) {mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED, Gravity.RIGHT);}@Overridepublic void onDrawerStateChanged(int newState) {}});

到这里,基本上就没什么知识点了(因为自己也写的不是很好,加上自己的水平有限),后面增加新功能了在做补充。
最后上传几张效果图:



代码传送门(如果感觉还不错,欢迎star下)

转载于:https://www.cnblogs.com/android-blogs/p/6006598.html

开源app之MyHearts相关推荐

  1. 4 app版本号 swift_已开源 app 实现检查更新的简单方式

    如果您开发的 app 没有上架 app store,那么您肯定会考虑如何保证用户及时收到 app 更新的问题,如果您的项目是开源在某个托管平台的,那么本文就提供一种简单的方式助您实现 app 检查更新 ...

  2. Android 组件化开源 app -开眼短视频(OpenEyes)

    Android-MvvmComponent-App 项目地址:darryrzhong/Android-MvvmComponent-App  简介: Android 组件化开源 app -开眼短视频(O ...

  3. 23个开源App的App Store地址和源代码

    23个开源App的App Store地址和源代码 http://www.cocoachina.com/iphonedev/sdk/2010/0316/672.html?1359360297

  4. 一些完整的Android开源app项目

    android开源项目有很多,但是完整的app项目不多,下面是最近我 整理的一些开源app项目: 注: jcodecraeer网站上搜集了很多开源项目,更新很快,非常值得关注. 一.photoup 介 ...

  5. 开源App动画Lottie

    转自:http://blog.csdn.net/googdev/article/details/54849715 开源App动画Lottie 新年第一天上班,没想到就立春了,俗话说,一年之计在于春,全 ...

  6. “因为无法从捐赠中抽成,谷歌把我的开源 App 下架了!”

    众所周知,苹果税和谷歌税的存在,即"只要你的 App 在 App Store 或 Google Play 上架,产生的收入就必须分给苹果或谷歌." 这个"收入" ...

  7. 最好的开源App锦集

    Infoworld Bossie Awards:最好的开源App锦集 发表于17小时前| 221次阅读| 来源CSDN| 2 条评论| 作者薛梁 InfoWorldNginxWordPressOran ...

  8. 推荐5个程序员专属的开源APP

    开源最前线(ID:OpenSourceTop) 猿妹 编译链接:https://opensource.com/article/19/4/mobile-apps 和所有人一样,我也是智能手机基本不离手, ...

  9. esp8266接入米家、小爱同学,附开源app控制

    超简单,两步完事 第一步 下载程序到esp8266 第二步 绑定到米家 第三步 (附)开源app控制 第一步 下载程序到esp8266 下载地址: 点击下载 本demo 是利用arduino IDE开 ...

最新文章

  1. 周怎么换算成月_您每天需要多少能量,怎么知道自己摄入多少能量
  2. 机器视觉-相机内参数和外参数
  3. 关于Arrays类总结
  4. JavaScript 中的return true 和return false
  5. PAT-BASIC-1016-部分A+B
  6. java 初始化log4j_java – log4j:WARN请正确初始化log4j系统
  7. HttpClient 4 API –获取状态代码-getStatusLine()。getStatusCode()示例
  8. spring 配置文件模板
  9. oracle中保留2位小数的写法
  10. 【python】继承时注意事项
  11. Linux,vi编辑器使用手册
  12. 网页英文 错位_网页错位原因解决方法
  13. ubuntu 最新提权漏洞_Ubuntu和Debian最新的KDE安全漏洞,附-修复指南
  14. ORACLE有EXCEL中trend函数,EXCEL【TREND】函数,你知道如何使用吗?
  15. 分析 AlphaGo 算法原理的本质
  16. unity算法-斜抛运动(变种)
  17. 工业互联网大数据之数据管理与治理的简易理解
  18. 对“主数据”的一点吐槽
  19. MTK: LSK,RSK的标签与响应
  20. 【Java】Spring 教程

热门文章

  1. *【HDU - 2473】Junk-Mail Filter (并查集--删点操作)
  2. dataframe去重复 python_python – 在DataFrame中组合重复的列
  3. vue mysql webapp_基于Laravel+VueJS实战开发WebAPP
  4. 如何实现Oracle数据库之间的数据同步?
  5. 简单暴力到dp的优化(萌新篇)
  6. STL源码剖析 迭代器iterator的概念 和 traits编程技法
  7. 将读写锁放到共享内存中,实现进程之间对数据的读写访问控制
  8. 王道考研 计算机网络5 分层结构 协议 服务 接口
  9. 王道考研 计算机网络4 速率相关的性能指标
  10. Android设计模式之——原型模式