高仿今日头条

高仿今日头条 --- 第一篇:(android高仿系列)今日头条 --新闻阅读器 (一)

上次,已经完成了头部新闻分类栏目的拖动效果。

这篇文章是继续去完善APP 今日头条  这个新闻阅读器的其他功能。

这次所实现的功能清单:

1.通过SlidingMenu实现左右侧拉菜单效果

2.通过重写CompoundButton实现--昼夜模式切换按钮效果。

3.通过PopupWindow控件实现了列表中更多菜单弹框操作效果。

4.通过universal-image-loader库实现了图片的加载和缓存。

5.通过列表中各个属性的判断,实现了头条新闻列表的相应布局和显示效果。

下面把每个功能和对应的实现方式相关博文都列出了,方便大家根据自身需求查看。

下面就是官方的效果截图,详细操作请继续向下看。

一.通过SlidingMenu实现左右侧拉菜单效果

在第一讲中,我们已经知道了,它使用了SlidingMenu 这个侧拉菜单开源库,所以我特地将 SlidingMenu的使用和配置写了一个文章,文章地址:Android SlidingMenu 开源项目 侧拉菜单的使用(详细配置)

所以具体的配置就不在这里说明了,大家可以去看上面给的链接。

注意:由于 今日头条用的是左右都可以侧拉的菜单,所以设置侧拉模式为:SlidingMenu.LEFT_RIGHT,代码如下

localSlidingMenu.setMode(SlidingMenu.LEFT_RIGHT);//设置左右滑菜单   

由于左右可以拖出菜单,并且中间的ViewPager可以切换新闻页面,所以SlidingMenu的必须如此设置以下属性:

localSlidingMenu.setTouchModeAbove(SlidingMenu.SLIDING_WINDOW);//设置要使菜单滑动,触碰屏幕的范围 

 SLIDEING_WINDOW就是触摸边缘才会出发,这样的话滑动操作就不用冲突了。

为了方便代码的维护,我将SlidingMenu 自定义成了一个DrawerView类,这样的话所有菜单中的操作就和主界面分离开来,代码就不会显得那么臃肿了,并且在用到的地址直接实例化这个类就可以了。

代码如下:

public class DrawerView implements OnClickListener{  
 private final Activity activity;  
    SlidingMenu localSlidingMenu;  
 private SwitchButton night_mode_btn;  
 private TextView night_mode_text;  
 private RelativeLayout setting_btn;  
 public DrawerView(Activity activity) {  
 this.activity = activity;  
    }  
 
 public SlidingMenu initSlidingMenu() {  
        localSlidingMenu = new SlidingMenu(activity);  
        localSlidingMenu.setMode(SlidingMenu.LEFT_RIGHT);//设置左右滑菜单 
        localSlidingMenu.setTouchModeAbove(SlidingMenu.SLIDING_WINDOW);//设置要使菜单滑动,触碰屏幕的范围 
//      localSlidingMenu.setTouchModeBehind(SlidingMenu.RIGHT); 
        localSlidingMenu.setShadowWidthRes(R.dimen.shadow_width);//设置阴影图片的宽度 
        localSlidingMenu.setShadowDrawable(R.drawable.shadow);//设置阴影图片 
        localSlidingMenu.setBehindOffsetRes(R.dimen.slidingmenu_offset);//SlidingMenu划出时主页面显示的剩余宽度 
        localSlidingMenu.setFadeDegree(0.35F);//SlidingMenu滑动时的渐变程度 
        localSlidingMenu.attachToActivity(activity, SlidingMenu.RIGHT);//使SlidingMenu附加在Activity右边 
//      localSlidingMenu.setBehindWidthRes(R.dimen.left_drawer_avatar_size);//设置SlidingMenu菜单的宽度 
        localSlidingMenu.setMenu(R.layout.left_drawer_fragment);//设置menu的布局文件 
//      localSlidingMenu.toggle();//动态判断自动关闭或开启SlidingMenu 
        localSlidingMenu.setSecondaryMenu(R.layout.profile_drawer_right);  
        localSlidingMenu.setSecondaryShadowDrawable(R.drawable.shadowright);  
        localSlidingMenu.setOnOpenedListener(new SlidingMenu.OnOpenedListener() {  
 public void onOpened() {  
 
                    }  
                });  
 
        initView();  
 return localSlidingMenu;  
    }  
 
 private void initView() {  
        night_mode_btn = (SwitchButton)localSlidingMenu.findViewById(R.id.night_mode_btn);  
        night_mode_text = (TextView)localSlidingMenu.findViewById(R.id.night_mode_text);  
        night_mode_btn.setOnCheckedChangeListener(new OnCheckedChangeListener() {  
 
 @Override 
 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {  
 // TODO Auto-generated method stub 
 if(isChecked){  
                    night_mode_text.setText(activity.getResources().getString(R.string.action_night_mode));  
                }else{  
                    night_mode_text.setText(activity.getResources().getString(R.string.action_day_mode));  
                }  
            }  
        });  
        night_mode_btn.setChecked(false);  
 if(night_mode_btn.isChecked()){  
            night_mode_text.setText(activity.getResources().getString(R.string.action_night_mode));  
        }else{  
            night_mode_text.setText(activity.getResources().getString(R.string.action_day_mode));  
        }  
 
        setting_btn =(RelativeLayout)localSlidingMenu.findViewById(R.id.setting_btn);  
        setting_btn.setOnClickListener(this);  
    }  
 
 @Override 
 public void onClick(View v) {  
 switch (v.getId()) {  
 case R.id.setting_btn:  
            activity.startActivity(new Intent(activity,SettingsActivity.class));  
            activity.overridePendingTransition(R.anim.slide_in_right, R.anim.slide_out_left);  
 break;  
 
 default:  
 break;  
        }  
    }  
}  

2.通过重写CompoundButton实现--昼夜模式切换按钮效果

看源码发现,今日头条的中的是SwitchButton昼夜模式选择控件,是通过重写CompoundButton实现的,以下便是实现对应方法的相关帖子:

SwitchButton 开关按钮 的多种实现方式 (附源码DEMO)

根据需求选择你喜欢的SwitchButton去修改和使用。

3.通过PopupWindow控件实现了列表中更多菜单弹框操作效果。

在开发中发现,每个新闻列表中对应的ITEM中按钮出发的弹框效果其实是通过PopupWindow实现的,相关博文如下

android 仿 新闻阅读器 菜单弹出效果(附源码DEMO)

4.通过universal-image-loader库实现了图片的加载和缓存。

一个新闻客户端肯定涉及到一个图片异步加载缓存的方法,所以这里使用开发中最常用的开源库之一

universal-image-loader来实现相关的需求。如果你对这个库的使用不是很了解的话,可以查看以下链接:

Android-Universal-Image-Loader 图片异步加载类库的使用(超详细配置)

---根据你需求配置相应的属性即可。

5.通过列表中各个属性的判断,实现了头条新闻列表的相应布局和显示效果。

新闻客户端中,每个新闻的布局都可能不一样,所以你可以选择2种最常用的方式去根据需求改变一个LISTVIEW里面的布局。

1.操作上会麻烦一点,维护起来很方便

BaseAdapter中有个自带的方法,就是getViewTypeCount() ,用户可以使用这个方法获取ITEM的种类数量,之后在getView()的时候判断对应到额种类type之后设给他对应的布局即可,常见的例子有:唱吧中的名人榜

2.操作上很方便,只用根据需求设置布局的显示隐藏效果,缺点:如果控件一多,不在注释的话,可能维护起来就很麻烦。

在这里,其实采用第2种方式就可以了,分析它对应的以下布大致的5种局:

布局---1

布局---2

布局---3

布局---4

布局---5

分析上述布局,其实他们的大体布局是一样的,知识根据图片的张数,图片的大小,以及新闻类别的评论来判断布局的对应显示隐藏问题,只要根据相对应的属性便可以很好的实现这个效果,所以方法2是最合适的。

其他操作就是根据服务器返回的数据类型,是否为空等作相应操作即可。

上述就是目前完成的进度,虽然数据啥都是在本地写死的,可是已经大体的算得上是的一个新闻阅读器了,之后会继续完善其他为完成的功能。

开发中的几个问题总结:

关于Fragment

1)

@Override 
public void onAttach(Activity activity) {  
// TODO Auto-generated method stub 
this.activity = activity;  
super.onAttach(activity);  
}  

通过onAttach()方法获取父类ACTIVITY,如果在调用getActivity()方法获取的话,可能会在FRAGMENT被回收后报空指针错误。

2)

看今日头条的效果是,没切换至类型界面后,才去刷新数据,Fragment自带了这个方法,如下:

public void setUserVisibleHint(boolean isVisibleToUser) {}  

你可以判断isVisibleToUser属性来知道是否是切换的界面已经完全可见,之后进行操作。代码中也注释了。

下面看看这次的效果图:

最后附上源码DEMO地址:下载地址

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Flutter入门到实战

WebView深度学习(二)之全面总结WebView遇到的坑及优化

这篇文章讲一下WebView遇到的那些坑,带领各位爬坑。这里如果有你没遇到的问题,欢迎留言告诉我,我尽我所能帮你解决。感谢大家支持。

71730
来自专栏飞雪无情的博客

新浪微博布局学习——妙用TabHost

为了更好的开发Android应用程序,除了熟练掌握基本的UI组件和API外,还需要掌握一些技巧,而这些技巧可以通过阅读一些代码来提高,本系列将与大家分享一些新浪...

9820
来自专栏androidBlog

使用ViewDragHelper打造属于自己的DragLayout(抽屉开关 )

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gdutxiaoxu/article/details...

16520
来自专栏郭霖

Android弹幕功能实现,模仿斗鱼直播的弹幕效果

大家好,感觉好像已经很久没更新博客了。前段时间主要是忙于新书的事情,时间比较紧张。而现在新书已经完稿,剩下的事情就都是出版社的工作了,那么我又可以抽出时间来写写...

1.1K90
来自专栏李蔚蓬的专栏

Material Design 实战 之第三弹—— 悬浮按钮和可交互提示

下面开始来具体实现。首先仍然需要提前准备好一个图标,这里放置了一张ic_done.png到drawable-xxhdpi目录下。然后修改activity-m...

26430
来自专栏Android 技术栈

Android 关于WebView全方面的使用(项目应用篇)

WebView的使用已经是老生常谈了,看到很多文章说了用法,但我很少看到全的或者是项目中可以直接使用的,都是看了很多后,自己把功能都集合在一起。这里是一份比较全...

25140
来自专栏developerHaoz 的安卓之旅

知乎 Matisse 源码解析,带你探究高效图片选择库的秘密

可以看到 Matisse 的可拓展性是非常强的,不仅可以自定义我们需要的主题,而且还可以按照需求来过滤出我们想要的文件,除此之外,Matisse 采用了建造者模...

60110
来自专栏Android干货

Android多媒体录制--MediaRecorder视频录制

49670
来自专栏mukekeheart的iOS之旅

iOS学习—— UINavigationController的返回按钮与侧滑返回手势的研究

侧滑返回手势是从iOS7开始增加的一个返回操作,经历了两年时间估计iPhone用户大部分都已经忽略了屏幕左上角那个碍眼的back按钮了。之前在网上搜过有关侧滑...

1.1K60
来自专栏宋凯伦的技术小栈

Android - 页面返回上一页面的三种方式

  今年刚刚跳槽到了新公司,也开始转型做Android,由此开始Android的学习历程。   最近在解很多UI的bug,在解bug过程中,总结了在UI的实现过...

47780

扫码关注云+社区

领取腾讯云代金券