【RecyclerView】Android 横竖屏切换 超便捷解决方案
2015-09-25 10:28
627 查看
相信Android 开发者大多数都遇到过横竖屏切换的需求,往往最后选择了锁定竖屏,或者锁定横屏的体验。或者每次切换屏幕就要切换显示数据的控件。谷歌官方推出的RecyclerView控件让你不再有这样的烦恼。
最近这两天又不是很忙了,闲下来看了些关于5.0的一些特性,比如材料设计规范、阴影、主题等等,还有RecyclerView和CardView这两个不错的控件。看到RecyclerView的时候感觉眼前一亮,毫无疑问,它能够完全胜任ListView,GridView以及现在流行的瀑布流(交错布局)显示,并且有着高度解耦,高自由度(自定义分隔线,自定义载入/删除动画等)等特点。
在这里,我用它写了一个横竖屏切换便捷解决方案的Demo。
本demo于API 23 + eclipse环境中完成(但本demo兼容低版本,如下载demo可以修改最低版本)
更新SDK Manager 中Extras的support library到21+版本后,其jar包在如下位置:
sdk\extras\android\support\v7\recyclerview\libs\android-support-v7-recyclerview.jar
如果不方便更新sdk的话,点击jar包下载地址
导入项目并add to build path。
item_char.xml
就能看到瀑布流的效果啦。
RecyclerView的强大之处就是解耦,以往常常将所有的代码,分隔线、动画、逻辑处理、视图缓存等都放在Adapter中而导致Adapter根本无法复用。相信在大型项目中RecyclerView会有很好的表现以及编程体验。
demo下载
注意:本demo有一处疏漏,需要在Manifest.xml中对对应需要 横竖屏切换 的Activity添加一条属性:
最近这两天又不是很忙了,闲下来看了些关于5.0的一些特性,比如材料设计规范、阴影、主题等等,还有RecyclerView和CardView这两个不错的控件。看到RecyclerView的时候感觉眼前一亮,毫无疑问,它能够完全胜任ListView,GridView以及现在流行的瀑布流(交错布局)显示,并且有着高度解耦,高自由度(自定义分隔线,自定义载入/删除动画等)等特点。
在这里,我用它写了一个横竖屏切换便捷解决方案的Demo。
本demo于API 23 + eclipse环境中完成(但本demo兼容低版本,如下载demo可以修改最低版本)
1.获取RecyclerView的jar包
RecyclerView虽然是谷歌官方推出的控件,但是为了兼容5.0以前的系统版本,它是属于V7兼容包下独立打包的。所以如果我们要使用RecyclerView的话需要导入这个jar包。更新SDK Manager 中Extras的support library到21+版本后,其jar包在如下位置:
sdk\extras\android\support\v7\recyclerview\libs\android-support-v7-recyclerview.jar
如果不方便更新sdk的话,点击jar包下载地址
导入项目并add to build path。
2.Activity中横竖屏切换控制
OrientationChangeActivity.java/** * @author 尘笑ys * RecyclerView 横竖屏切换demo */ public class OrientationChangeActivity extends Activity { private RecyclerView recyclerView; private ArrayList<String> datas = new ArrayList<String>(); private LinearLayoutManager mLlayoutmanager; private GridLayoutManager mGlayoutmanager; CharAdapter charad; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); recyclerView = (RecyclerView) findViewById(R.id.id_recyclerview); //切换屏幕时保存数据,如有数据,则不再进行数据的初始化 if (savedInstanceState != null && savedInstanceState.getStringArrayList("data") != null) { datas = savedInstanceState.getStringArrayList("data"); }else { initData(); } //竖屏线性展示 mLlayoutmanager = new LinearLayoutManager(this); //横屏每行显示3个 mGlayoutmanager = new GridLayoutManager(this,3); reviewonScreenChanged(getResources().getConfiguration()); recyclerView.setAdapter(charad = new CharAdapter(this, datas)); charad.setOnItemClickLitener(new OnItemClickLitener() { @Override public void onItemLongClick(View view, int position) { //这里要先使用这个数据再删除,因为一旦删除,就获取不到这个数据了,获取的就是下一个数据了 Toast.makeText(OrientationChangeActivity.this, datas.get(position)+'\t'+"delete...", Toast.LENGTH_SHORT).show(); charad.removeData(position); } @Override public void onItemClick(View view, int position) { Toast.makeText(OrientationChangeActivity.this, datas.get(position), Toast.LENGTH_SHORT).show(); } }); } private void reviewonScreenChanged(Configuration newConfig) { if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) { //横屏 recyclerView.setLayoutManager(mGlayoutmanager); }else { //竖屏 recyclerView.setLayoutManager(mLlayoutmanager); } } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); reviewonScreenChanged(newConfig); } private void initData() { for (int i = 'A'; i <= 'z'; i++) { datas.add((char)i + ""); } } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putStringArrayList("data", datas); } }
3.RecyclerView.Adapter
CharAdapter.java/** * @author 尘笑ys * */ public class CharAdapter extends RecyclerView.Adapter<CharAdapter.MyViewHolder>{ //类型用自定义的ViewHolder private List<String> mDatas; private LayoutInflater mInflater; //RecyclerView目前需要自己来定义接口 public interface OnItemClickLitener { //点击事件 void onItemClick(View view, int position); //长按事件 void onItemLongClick(View view , int position); } private OnItemClickLitener mOnItemClickLitener; //设置监听的方法,注意参数是CharAdapter.OnItemClickLitener而不是View.OnItemClickLitener public void setOnItemClickLitener(OnItemClickLitener mOnItemClickLitener) { this.mOnItemClickLitener = mOnItemClickLitener; } //构造时传入数据,如果考虑数据解耦,可将数据赋值放到setData()中 public CharAdapter(Context context, List<String> datas) { mInflater = LayoutInflater.from(context); mDatas = datas; } @Override //视图缓存创建 public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { //视图缓存,在ViewHolder构造时获取视图控件 MyViewHolder holder = new MyViewHolder(mInflater.inflate( R.layout.item_char, parent, false)); return holder; } @Override //视图缓存的数据绑定 public void onBindViewHolder(final MyViewHolder holder, final int position) { holder.tv.setText(mDatas.get(position)); // 如果设置了回调,则设置点击事件 if (mOnItemClickLitener != null) { holder.itemView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { int pos = holder.getPosition(); //尽量在回调时处理逻辑,此处不进行处理,增加Adapter复用的可能 mOnItemClickLitener.onItemClick(holder.itemView, pos); } }); holder.itemView.setOnLongClickListener(new OnLongClickListener() { @Override public boolean onLongClick(View v) { int pos = holder.getPosition(); //尽量在回调时处理逻辑,此处不进行处理,增加Adapter复用的可能 mOnItemClickLitener.onItemLongClick(holder.itemView, pos); return false; } }); } } @Override public int getItemCount() { return mDatas.size(); } //需要自己定义,添加数据后需要调用notifyItemInserted(position),效果类似于ListView的notifyDataSetChanged() //但是这里会调用预设或者自定义的增加item动画 public void addData(int position) { mDatas.add(position, "Insert One"); notifyItemInserted(position); } //需要自己定义,添加数据后需要调用notifyItemRemoved(position),效果类似于ListView的notifyDataSetChanged() //但是这里会调用预设或者自定义的删除item动画 public void removeData(int position) { mDatas.remove(position); notifyItemRemoved(position); } //视图缓存 class MyViewHolder extends ViewHolder { TextView tv; //在构造方法中获取控件 public MyViewHolder(View view) { super(view); tv = (TextView) view.findViewById(R.id.id_num); } } }
4.布局
activity_main.xml<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="${relativePackage}.${activityClass}" > <android.support.v7.widget.RecyclerView android:id="@+id/id_recyclerview" android:divider="#ffff0000" android:dividerHeight="10dp" android:layout_width="match_parent" android:layout_height="match_parent" /> </RelativeLayout>
item_char.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/item_bg" android:layout_margin="2dp" android:gravity="center" > <TextView android:id="@+id/id_num" android:layout_width="100dp" android:layout_gravity="center" android:layout_height="100dp" android:gravity="center" /> </RelativeLayout>
5.瀑布流
在Adpater里面修改一下每个item的宽高,RecyclerView的LayoutManager再换成mLlayoutmanager = new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL); mGlayoutmanager = new StaggeredGridLayoutManager(5,StaggeredGridLayoutManager.HORIZONTAL);
就能看到瀑布流的效果啦。
6.总结与demo下载
这其实是一个十分简单的demo,你可以在此基础上去修改RecyclerView的分隔线以及载入删除动画。RecyclerView的强大之处就是解耦,以往常常将所有的代码,分隔线、动画、逻辑处理、视图缓存等都放在Adapter中而导致Adapter根本无法复用。相信在大型项目中RecyclerView会有很好的表现以及编程体验。
demo下载
注意:本demo有一处疏漏,需要在Manifest.xml中对对应需要 横竖屏切换 的Activity添加一条属性:
android:configChanges="orientation"
相关文章推荐
- Android 相关属性
- 编译android4.4问题--【gcc】:unknow (64-bit) [FAIL]
- Android 沉浸式状态栏
- android dialog 获得edittext的值 避免一些弹出窗口的错误
- Android聊天界面刷新消息
- AlertDialog为什么显示不出来,仅出现变暗呢?
- Chromium for Android已经开源
- 安卓Android自定义控件:200行代码实现一个简约时钟
- 浅谈Android4.4和Android L中的trim技术
- android 绘图机制源码分析
- [Android] 混音线程MixerThread
- Android 插件开发,做成动态加载
- Android的NFC教程(一)
- Android解决java.lang.OutOfMemoryError: bitmap size exceeds VM budget(转)
- AndroidStackOverFlow
- Android Fragment中使用SurfaceView切换时闪一下黑屏的解决办法
- 简明了解Android中的AsyncTask异步操作
- android学习笔记11 - LayoutParams布局控制
- 57、android 应用内全局通知的实现方法
- Android更新页面上的数据的常见三种方法