閱讀724 返回首頁    go 京東網上商城


高仿今日頭條(轉載)

高仿今日頭條 --- 第一篇:(android高仿係列)今日頭條 --新聞閱讀器 (一)   

上次,已經完成了頭部新聞分類欄目的拖動效果。

這篇文章是繼續去完善APP 今日頭條  這個新聞閱讀器的其他功能。

這次所實現的功能清單

1.通過SlidingMenu實現左右側拉菜單效果

2.通過重寫CompoundButton實現--晝夜模式切換按鈕效果。

3.通過PopupWindow控件實現了列表中更多菜單彈框操作效果。

4.通過universal-image-loader庫實現了圖片的加載和緩存。

5.通過列表中各個屬性的判斷,實現了頭條新聞列表的相應布局和顯示效果。


下麵把每個功能和對應的實現方式相關博文都列出了,方便大家根據自身需求查看。


下麵就是官方的效果截圖,詳細操作請繼續向下看。

                


一.通過SlidingMenu實現左右側拉菜單效果

在第一講中,我們已經知道了,它使用了SlidingMenu 這個側拉菜單開源庫,所以我特地將 SlidingMenu的使用和配置寫了一個文章,文章地址:Android SlidingMenu 開源項目 側拉菜單的使用(詳細配置)

所以具體的配置就不在這裏說明了,大家可以去看上麵給的鏈接。

注意:由於 今日頭條用的是左右都可以側拉的菜單,所以設置側拉模式為:SlidingMenu.LEFT_RIGHT,代碼如下

  1. localSlidingMenu.setMode(SlidingMenu.LEFT_RIGHT);//設置左右滑菜單    
由於左右可以拖出菜單,並且中間的ViewPager可以切換新聞頁麵,所以SlidingMenu的必須如此設置以下屬性:

  1. localSlidingMenu.setTouchModeAbove(SlidingMenu.SLIDING_WINDOW);//設置要使菜單滑動,觸碰屏幕的範圍  
SLIDEING_WINDOW就是觸摸邊緣才會出發,這樣的話滑動操作就不用衝突了。

為了方便代碼的維護,我將SlidingMenu 自定義成了一個DrawerView類,這樣的話所有菜單中的操作就和主界麵分離開來,代碼就不會顯得那麼臃腫了,並且在用到的地址直接實例化這個類就可以了。

代碼如下:

  1. public class DrawerView implements OnClickListener{  
  2.     private final Activity activity;  
  3.     SlidingMenu localSlidingMenu;  
  4.     private SwitchButton night_mode_btn;  
  5.     private TextView night_mode_text;  
  6.     private RelativeLayout setting_btn;  
  7.     public DrawerView(Activity activity) {  
  8.         this.activity = activity;  
  9.     }  
  10.   
  11.     public SlidingMenu initSlidingMenu() {  
  12.         localSlidingMenu = new SlidingMenu(activity);  
  13.         localSlidingMenu.setMode(SlidingMenu.LEFT_RIGHT);//設置左右滑菜單  
  14.         localSlidingMenu.setTouchModeAbove(SlidingMenu.SLIDING_WINDOW);//設置要使菜單滑動,觸碰屏幕的範圍  
  15. //      localSlidingMenu.setTouchModeBehind(SlidingMenu.RIGHT);  
  16.         localSlidingMenu.setShadowWidthRes(R.dimen.shadow_width);//設置陰影圖片的寬度  
  17.         localSlidingMenu.setShadowDrawable(R.drawable.shadow);//設置陰影圖片  
  18.         localSlidingMenu.setBehindOffsetRes(R.dimen.slidingmenu_offset);//SlidingMenu劃出時主頁麵顯示的剩餘寬度  
  19.         localSlidingMenu.setFadeDegree(0.35F);//SlidingMenu滑動時的漸變程度  
  20.         localSlidingMenu.attachToActivity(activity, SlidingMenu.RIGHT);//使SlidingMenu附加在Activity右邊  
  21. //      localSlidingMenu.setBehindWidthRes(R.dimen.left_drawer_avatar_size);//設置SlidingMenu菜單的寬度  
  22.         localSlidingMenu.setMenu(R.layout.left_drawer_fragment);//設置menu的布局文件  
  23. //      localSlidingMenu.toggle();//動態判斷自動關閉或開啟SlidingMenu  
  24.         localSlidingMenu.setSecondaryMenu(R.layout.profile_drawer_right);  
  25.         localSlidingMenu.setSecondaryShadowDrawable(R.drawable.shadowright);  
  26.         localSlidingMenu.setOnOpenedListener(new SlidingMenu.OnOpenedListener() {  
  27.                     public void onOpened() {  
  28.                           
  29.                     }  
  30.                 });  
  31.           
  32.         initView();  
  33.         return localSlidingMenu;  
  34.     }  
  35.   
  36.     private void initView() {  
  37.         night_mode_btn = (SwitchButton)localSlidingMenu.findViewById(R.id.night_mode_btn);  
  38.         night_mode_text = (TextView)localSlidingMenu.findViewById(R.id.night_mode_text);  
  39.         night_mode_btn.setOnCheckedChangeListener(new OnCheckedChangeListener() {  
  40.               
  41.             @Override  
  42.             public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {  
  43.                 // TODO Auto-generated method stub  
  44.                 if(isChecked){  
  45.                     night_mode_text.setText(activity.getResources().getString(R.string.action_night_mode));  
  46.                 }else{  
  47.                     night_mode_text.setText(activity.getResources().getString(R.string.action_day_mode));  
  48.                 }  
  49.             }  
  50.         });  
  51.         night_mode_btn.setChecked(false);  
  52.         if(night_mode_btn.isChecked()){  
  53.             night_mode_text.setText(activity.getResources().getString(R.string.action_night_mode));  
  54.         }else{  
  55.             night_mode_text.setText(activity.getResources().getString(R.string.action_day_mode));  
  56.         }  
  57.           
  58.         setting_btn =(RelativeLayout)localSlidingMenu.findViewById(R.id.setting_btn);  
  59.         setting_btn.setOnClickListener(this);  
  60.     }  
  61.   
  62.     @Override  
  63.     public void onClick(View v) {  
  64.         switch (v.getId()) {  
  65.         case R.id.setting_btn:  
  66.             activity.startActivity(new Intent(activity,SettingsActivity.class));  
  67.             activity.overridePendingTransition(R.anim.slide_in_right, R.anim.slide_out_left);  
  68.             break;  
  69.   
  70.         default:  
  71.             break;  
  72.         }  
  73.     }  
  74. }  

2.通過重寫CompoundButton實現--晝夜模式切換按鈕效果

看源碼發現,今日頭條的中的是SwitchButton晝夜模式選擇控件,是通過重寫CompoundButton實現的,以下便是實現對應方法的相關帖子:

SwitchButton 開關按鈕 的多種實現方式 (附源碼DEMO)

根據需求選擇你喜歡的SwitchButton去修改和使用。


3.通過PopupWindow控件實現了列表中更多菜單彈框操作效果。

在開發中發現,每個新聞列表中對應的ITEM中按鈕出發的彈框效果其實是通過PopupWindow實現的,相關博文如下
android 仿 新聞閱讀器 菜單彈出效果(附源碼DEMO)

4.通過universal-image-loader庫實現了圖片的加載和緩存。

一個新聞客戶端肯定涉及到一個圖片異步加載緩存的方法,所以這裏使用開發中最常用的開源庫之一

universal-image-loader來實現相關的需求。如果你對這個庫的使用不是很了解的話,可以查看以下鏈接:

---根據你需求配置相應的屬性即可。

5.通過列表中各個屬性的判斷,實現了頭條新聞列表的相應布局和顯示效果。

新聞客戶端中,每個新聞的布局都可能不一樣,所以你可以選擇2種最常用的方式去根據需求改變一個LISTVIEW裏麵的布局。
1.操作上會麻煩一點,維護起來很方便
BaseAdapter中有個自帶的方法,就是getViewTypeCount() ,用戶可以使用這個方法獲取ITEM的種類數量,之後在getView()的時候判斷對應到額種類type之後設給他對應的布局即可,常見的例子有:唱吧中的名人榜

2.操作上很方便,隻用根據需求設置布局的顯示隱藏效果,缺點:如果控件一多,不在注釋的話,可能維護起來就很麻煩。

在這裏,其實采用第2種方式就可以了,分析它對應的以下布大致的5種局:
 
布局---1 

布局---2

布局---3

布局---4

布局---5


分析上述布局,其實他們的大體布局是一樣的,知識根據圖片的張數,圖片的大小,以及新聞類別的評論來判斷布局的對應顯示隱藏問題,隻要根據相對應的屬性便可以很好的實現這個效果,所以方法2是最合適的。

其他操作就是根據服務器返回的數據類型,是否為空等作相應操作即可。

上述就是目前完成的進度,雖然數據啥都是在本地寫死的,可是已經大體的算得上是的一個新聞閱讀器了,之後會繼續完善其他為完成的功能。

開發中的幾個問題總結:

關於Fragment

1)

  1. @Override  
  2. public void onAttach(Activity activity) {  
  3. // TODO Auto-generated method stub  
  4. this.activity = activity;  
  5. super.onAttach(activity);  
  6. }  

通過onAttach()方法獲取父類ACTIVITY,如果在調用getActivity()方法獲取的話,可能會在FRAGMENT被回收後報空指針錯誤。

2)

看今日頭條的效果是,沒切換至類型界麵後,才去刷新數據,Fragment自帶了這個方法,如下

  1. public void setUserVisibleHint(boolean isVisibleToUser) {}  
你可以判斷isVisibleToUser屬性來知道是否是切換的界麵已經完全可見,之後進行操作。代碼中也注釋了。


下麵看看這次的效果圖:

            

           


最後附上源碼DEMO地址:下載地址

可能在代碼方麵寫的不是很好,優化不足,希望大家提出來,共同進步。轉載請注明https://blog.csdn.net/vipzjyno1/article/details/23619269

謝謝。

最後更新:2017-04-03 12:56:18

  上一篇:go 仿今日頭條頂部導航效果
  下一篇:go C# 係統應用之調用SDelete程序粉碎文件及基礎原理知識