开源app之MyHearts

开源app之MyHearts

前言

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

为什么要写这个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">
    <item
        android:drawable="@mipmap/main_layout_center_image_1"
        android:duration="100"/>
    <item
        android:drawable="@mipmap/main_layout_center_image_2"
        android:duration="100"/>
    <item
        android:drawable="@mipmap/main_layout_center_image_3"
        android:duration="100"/>
    <item
        android:drawable="@mipmap/main_layout_center_image_4"
        android:duration="100"/>
    <item
        android:drawable="@mipmap/main_layout_center_image_5"
        android:duration="100"/>
    <item
        android:drawable="@mipmap/main_layout_center_image_6"
        android:duration="100"/>
    <item
        android:drawable="@mipmap/main_layout_center_image_7"
        android:duration="100"/>
    <item
        android:drawable="@mipmap/main_layout_center_image_8"
        android:duration="100"/>
    <item
        android: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
     */

    @Override
    public 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() {
            @Override
            public 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);
                }
            }

            @Override
            public void onDrawerOpened(View drawerView) {

            }

            @Override
            public void onDrawerClosed(View drawerView) {
                mDrawerLayout.setDrawerLockMode(
                        DrawerLayout.LOCK_MODE_LOCKED_CLOSED, Gravity.RIGHT);
            }

            @Override
            public void onDrawerStateChanged(int newState) {

            }
        });

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





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

https://github.com/wuyinlei/MyHearts

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,723评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,080评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,604评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,440评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,431评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,499评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,893评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,541评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,751评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,547评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,619评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,320评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,890评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,896评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,137评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,796评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,335评论 2 342

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,364评论 25 707
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,010评论 4 62
  • 开源App之MyHearts(二) 前言 小弟技术有限,有的地方也是自己摸索出来的,可能和大神们写的好的代码没法比...
    菜鸟_一枚阅读 1,278评论 4 36
  • 前几天在讨论鞋子,说起了很多鞋子的话题。这几天我就被鞋子这件事折磨的寝食难安。 想起有一次跟木兮喝茶,她说自己为了...
    寅颖阅读 379评论 3 0
  • 今天突然发现自己变成了一个靠谱的人。从小到大,亲朋好友都不敢把重要事情交给我,因为我一定会出岔子。高中的时候是班里...
    四鬼阅读 143评论 0 0