開源app之MyHearts
前言
這個月,說實話,有忙有閑,經歷了一次病痛的洗禮,才認識到了只有好好的生活,認真的對待自己的身體,才能更好的去工作,沒有了身體的支撐,什么工作都只能是紙老虎,不攻自破。在這里也祝愿大家,在生活中好好對待自己,身體第一,工作第二。
為什么要寫這個app
群里的一個哥們前幾天晚上給我看了一下一個app,我粗略看了下界面(還沒運行下載,他給我發的),我看了一下,感覺挺不錯的,當時心里一熱,哈哈,這不是挺簡單的么,幾天就搞完了,但是當我去下載的時候,看到了30-40MB的大小,我驚呆了,要知道一個淘寶才那么大。哈哈,不過還是被這個界面吸引了,而且里面的內容也挺不錯的,大多關于心理方面的。那就自己模仿一下吧,順帶的自己去學習一下,因為這個app涉及到的知識點挺多(即時通訊、直播、視屏播放、第三方登錄),想著自己就慢慢的寫,然后去學習一下會用到的知識,伴隨著這樣的想法,就有了這個MyHearts項目。
幾個小知識點
一、進入到主界面,可以看到下方的幾個Tab鍵,原本想著是用FragmentTabhost實現,但是看到中間的那個Tab鍵和其他的按鍵是不同等高度的,而且這個還是有動畫效果的,后面想著,如果用framelayout覆蓋在上面應該是可以實現的,但是動畫呢,這個時候想到之前用到的幀動畫,想必這個幀動畫也是可以實現的,然后自己就去試了試,結果還真給實現了,對于程序這東西來說,當別人問這個能不能實現,我在這個地方加一個字段、加個方法,可以實現么,我想說的就是,既然已經想到了,那就試一下唄,行了就證明方法可以,不行證明需要找其他的方法,最重要的是動手寫程序,程序不是問出來的,而是一句一句代碼積累出來的。
lt;?xml version=quot;1.0quot; encoding=quot;utf-8quot;?gt; lt;animation-list xmlns:android=quot;http://schemas.android.com/apk/res/androidquot; android:oneshot=quot;falsequot;gt; lt;item android:drawable=quot;@mipmap/main_layout_center_image_1quot; android:duration=quot;100quot;/gt; lt;item android:drawable=quot;@mipmap/main_layout_center_image_2quot; android:duration=quot;100quot;/gt; lt;item android:drawable=quot;@mipmap/main_layout_center_image_3quot; android:duration=quot;100quot;/gt; lt;item android:drawable=quot;@mipmap/main_layout_center_image_4quot; android:duration=quot;100quot;/gt; lt;item android:drawable=quot;@mipmap/main_layout_center_image_5quot; android:duration=quot;100quot;/gt; lt;item android:drawable=quot;@mipmap/main_layout_center_image_6quot; android:duration=quot;100quot;/gt; lt;item android:drawable=quot;@mipmap/main_layout_center_image_7quot; android:duration=quot;100quot;/gt; lt;item android:drawable=quot;@mipmap/main_layout_center_image_8quot; android:duration=quot;100quot;/gt; lt;item android:drawable=quot;@mipmap/main_layout_center_image_9quot; android:duration=quot;100quot;/gt; //這里并沒有寫完,可以直接去代碼里面查看,最后會附上git地址 lt;/animation-listgt;
在代碼中這樣就可以執行動畫了
// 獲取ImageView上的動畫背景 AnimationDrawable spinnerImg = (AnimationDrawable) mIvImg.getBackground(); // 開始動畫 spinnerImg.start();
這樣就可以實現直播和life動畫的切換了。
二、心事界面的圖片展示,之前在用postman(用于接口調試的,值得推薦)請求數據接口的時候,看到里面有個photos字段,并不是所有的item都有這個字段,而且里面個數不一,但都是一個圖片地址,想著應該是類似于qq空間發表說說的附帶的圖片。自己想著用RecyclerView實現,因為這個是很好實現的,但是我在看到okgo(本項目的網絡請求框架,支持Rx,挺不錯的)項目中,他的項目也有這個類似的功能,用到的就是NineGridView( https://github.com/jeasonlzy/NineGridView),okgo這個項目也是這位大神寫的。這個也是很簡單使用的,他是在ViewGroup的基礎上自定義的。用法也是很簡單,如下
//也就是用戶發朋友圈的那種,添加圖片 Listlt;Stringgt; 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 amp;amp; 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
Listlt;CommentsBeangt; comments = bean.getComments(); if (comments != null amp;amp; comments.size() gt; 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(quot; quot;); String replay = mContext.getResources().getString(R.string.replay_comment); if (!replayName.equals(quot;quot;)) { //判斷是否有被回復的,沒有就是默認發帖者 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(quot;quot;)) { 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,然后處理了一些邏輯,基本解決了沖突),代碼如下:
/** * 事件分發,請求父控件是否攔截 * lt;p/gt; * 1、右滑,而且是第一個頁面,需要父控件攔截 * lt;p/gt; * 2、左滑,而且當前的頁面是最后一個頁面,需要父控件攔截 * lt;p/gt; * 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) gt; Math.abs(endY - startY)) { if (endX gt; startX) { //右滑 //獲取到第一個 需要父控件攔截 if (getCurrentItem() == 0) { getParent().requestDisallowInterceptTouchEvent(false); } } else if (endX lt;= 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(quot;LEFTquot;)) { 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下)
Tags: 開源 安卓開發
文章來源:http://www.jianshu.com/p/8e8975f12ce0