Android 中轴时光轴
Android 中轴时光轴
ps:好久都没有写博客了,今天正好比较空,就来写一篇,好像这才是第二篇,不过不要在意这些细节啦。
转载请注明出处:http://blog.csdn.net/qq_15736263/article/details/51941066
效果图
:
美女图片都是 熊(百)掌(度)找的,如果有涉及到您的权益,请及时联系我进行删除。
就是这样的效果,这张图片因为某些原因,已经经过ps修改,请见谅我ps功底差!
第二个Item因为需要,固定添加了paddingTop。
一些说明
刚开始在网上找这种效果的实现,也在论坛上提过问。都没有能解决问题。
其实瀑布流是很好实现的。主要是中间圆点让人十分蛋疼。
最开始有考虑过几种解决方式
使用网络上开源的瀑布流控件,然后进行重写:
发现都是用使用GridView或者是ListView或者ViewGroup实现的,使用的都是类似LinnearLayout的布局方式,修改起来比较困难,牵扯面较多,然后放弃了。
使用RecyclerView然后自定义LayoutManager:
其实这个是最好的实现方式,但是因为时间太赶,加上网络上相关资源太少。只好去参考官方StaggeredGridLayoutManager了。
然后就源码旅游了。
@Override
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {onLayoutChildren(recycler, state, true);
} private void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state,boolean shouldCheckForGaps) {final AnchorInfo anchorInfo = mAnchorInfo;anchorInfo.reset();if (mPendingSavedState != null || mPendingScrollPosition != NO_POSITION) {if (state.getItemCount() == 0) {removeAndRecycleAllViews(recycler);return;}}if (mPendingSavedState != null) {applyPendingSavedState(anchorInfo);} else {resolveShouldLayoutReverse();anchorInfo.mLayoutFromEnd = mShouldReverseLayout;}updateAnchorInfoForLayout(state, anchorInfo);if (mPendingSavedState == null) {if (anchorInfo.mLayoutFromEnd != mLastLayoutFromEnd ||isLayoutRTL() != mLastLayoutRTL) {mLazySpanLookup.clear();anchorInfo.mInvalidateOffsets = true;}}if (getChildCount() > 0 && (mPendingSavedState == null ||mPendingSavedState.mSpanOffsetsSize < 1)) {if (anchorInfo.mInvalidateOffsets) {for (int i = 0; i < mSpanCount; i++) {// Scroll to position is set, clear.mSpans[i].clear();if (anchorInfo.mOffset != INVALID_OFFSET) {mSpans[i].setLine(anchorInfo.mOffset);}}} else {for (int i = 0; i < mSpanCount; i++) {mSpans[i].cacheReferenceLineAndClear(mShouldReverseLayout, anchorInfo.mOffset);}}}detachAndScrapAttachedViews(recycler);mLayoutState.mRecycle = false;mLaidOutInvalidFullSpan = false;updateMeasureSpecs(mSecondaryOrientation.getTotalSpace());updateLayoutState(anchorInfo.mPosition, state);if (anchorInfo.mLayoutFromEnd) {// Layout start.setLayoutStateDirection(LAYOUT_START);fill(recycler, mLayoutState, state);// Layout end.setLayoutStateDirection(LAYOUT_END);mLayoutState.mCurrentPosition = anchorInfo.mPosition + mLayoutState.mItemDirection;fill(recycler, mLayoutState, state);} else {// Layout end.setLayoutStateDirection(LAYOUT_END);fill(recycler, mLayoutState, state);// Layout start.setLayoutStateDirection(LAYOUT_START);mLayoutState.mCurrentPosition = anchorInfo.mPosition + mLayoutState.mItemDirection;fill(recycler, mLayoutState, state);}repositionToWrapContentIfNecessary();if (getChildCount() > 0) {if (mShouldReverseLayout) {fixEndGap(recycler, state, true);fixStartGap(recycler, state, false);} else {fixStartGap(recycler, state, true);fixEndGap(recycler, state, false);}}boolean hasGaps = false;if (shouldCheckForGaps && !state.isPreLayout()) {final boolean needToCheckForGaps = mGapStrategy != GAP_HANDLING_NONE&& getChildCount() > 0&& (mLaidOutInvalidFullSpan || hasGapsToFix() != null);if (needToCheckForGaps) {removeCallbacks(mCheckForGapsRunnable);if (checkForGaps()) {hasGaps = true;}}mPendingScrollPosition = NO_POSITION;mPendingScrollPositionOffset = INVALID_OFFSET;}mLastLayoutFromEnd = anchorInfo.mLayoutFromEnd;mLastLayoutRTL = isLayoutRTL();mPendingSavedState = null; // we don't need this anymoreif (hasGaps) {onLayoutChildren(recycler, state, false);}
}
这里牵扯的东西非常多,因为StaggeredGridLayoutManager不单单考虑两列的情况。这个类的代码量在3000行,牵扯的到的同包的类也很多,这么算下来,代码量就远远不止3000行了,得需要点时间进行研究了。但是真的时间太赶了,只能另寻它路了。ps:加上水平有点烂啦。
我的实现方式:
- 简述:
因为上面的各种问题,主要是项目时间不够,想想用low的方法好了。直接用RecyclerView和StaggeredGridLayoutManager实现他,在onBindViewHolder用ViewHolder.post(Runnable) 在顶层用RelativeLayout动态添加View,并且绑定RecyclerView的滑动监听,进行滑动管理,自己进行维护生成的View的各种状态,包括进行缓存。但是这种效率真的是太低了,而且滑动的View复用处理不好的话,很容易就添加了N个圆点,只是不在屏幕内而且,而且这么写,圆点基本上就只能做成一种。项目中又需要不止一种类的圆点,存在一种年份的Item,和正常的Item带箭头的、颜色、大小都不一样的。
后来想起来一个神奇的属性,这个属性经常被人遗忘,因为他确实用的不多,但是确实好用。‘android:clipChildren=”false”’与之相配套的是’ android:clipToPadding=”false”’关于这两个属性这里就不多做介绍了,相关效果请自行熊(百)掌(度)。 代码:
XML布局:
- Activity/Fragment:
<FrameLayout android:layout_width="match_parent"android:layout_height="match_parent"android:background="#DDD"android:clipChildren="false"android:clipToPadding="false"><View android:layout_width="1dp"android:layout_height="match_parent"android:layout_gravity="center_horizontal"android:background="#DFDAD7" /><android.support.v7.widget.RecyclerView android:id="@+id/view1"android:layout_width="match_parent"android:layout_height="match_parent"android:clipChildren="false" /></FrameLayout>
这里在在FrameLayout和RecyclerView上添加android:clipChildren=”false”属性是很有必要的,不然Item中的效果可能发挥不出来。
Item:
标准Item:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:clipChildren="false" android:clipToPadding="false" android:orientation="horizontal"><ImageViewandroid:id="@+id/view1"android:layout_width="30dp"android:layout_height="20dp"android:layout_marginLeft="@dimen/_dp8"android:layout_marginTop="30dp"android:clipChildren="false"android:clipToPadding="false"android:contentDescription="@string/app_name"android:src="@mipmap/right" /><ImageViewandroid:id="@+id/view3"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_marginBottom="@dimen/dp10"android:layout_marginTop="@dimen/dp10"android:layout_weight="1"android:background="@drawable/progress_dialog"android:contentDescription="@string/app_name"android:scaleType="fitCenter" /><ImageViewandroid:id="@+id/view2"android:layout_width="30dp"android:layout_height="20dp"android:layout_marginRight="@dimen/_dp8"android:layout_marginTop="30dp"android:clipChildren="false"android:clipToPadding="false"android:contentDescription="@string/app_name"android:src="@mipmap/letf" /> </LinearLayout>
YearItem:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:clipChildren="false" android:clipToPadding="false" android:paddingBottom="@dimen/dp10" android:paddingTop="@dimen/dp10"><ImageViewandroid:id="@id/view1"android:layout_width="20dp"android:layout_height="20dp"android:layout_gravity="left"android:layout_marginLeft="-10dp"android:clipChildren="false"android:clipToPadding="false"android:contentDescription="@string/app_name"android:src="@mipmap/year" /><TextViewandroid:id="@id/textV1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="30dp"android:layout_marginRight="30dp"android:background="@drawable/year"android:gravity="center"android:minHeight="20dp"android:paddingBottom="5dp"android:paddingLeft="20dp"android:paddingRight="20dp"android:paddingTop="5dp"android:textColor="@color/colorPrimary" /><ImageViewandroid:id="@id/view2"android:layout_width="20dp"android:layout_height="20dp"android:layout_gravity="right"android:layout_marginRight="-10dp"android:clipChildren="false"android:clipToPadding="false"android:contentDescription="@string/app_name"android:src="@mipmap/year" /> </FrameLayout>
这里的view1和View2代表了左右两个箭头及圆点。中间的View3可以替换成任意的View(Layout也行),@dimen/_dp8是-8dp,让View位置超出父View的可见位置。
- Activity/Fragment:
Java:
Activity/Fragment:
public class Activity_Fragment {private RecyclerView mRecyclerView;private Adapter mAdapter;onCreate/onCreateView(){mRecyclerView = (RecyclerView) rootView.findViewById(R.id.view1);mRecyclerView.setAdapter(adapter);StaggeredGridLayoutManager df = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);df.invalidateSpanAssignments();//↑↑↑这里很重要,不然Item会自动换位置,会导致圆圈和箭头的方向不对mRecyclerView.setLayoutManager(df);mAdapter= new Adapter(Context,List);mRecyclerView.setAdaper(mAdapter);}}
Adapter:
public class Adapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {private LayoutInflater mInflater;private final ArrayList<Data> datas;public BigEventAdapter(Context mCtx, ArrayList<Data> dataList) {super();mInflater = LayoutInflater.from(mCtx);this.datas= dataList;}@Overridepublic int getItemViewType(int position) {return datas.get(position).getDtype().ordinal();}@Overridepublic RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewgroup, int viewType) {if (type == DTYPE.ITEM.ordinal()) {rootView = mInflater.inflate(R.layout.view_item_add, viewgroup, false);return new ItemViewHolder(rootView);}if (type == DTYPE.YEAR.ordinal()) {rootView = mInflater.inflate(R.layout.view_item_year, viewgroup, false);return new TextViewHolder(rootView);}}/*** 判读左右显示相应的圆圈及箭头*/private void isLeftOfRight(final CardViewHolder viewHolder) {((ViewGroup) viewHolder.itemView).setClipChildren(false);viewHolder.itemView.post(new Runnable() {@Overridepublic void run() {int left = viewHolder.itemView.getLeft();if (left == 0) {viewHolder.itemArrow_Left.setVisibility(View.VISIBLE);viewHolder.itemArrow_Right.setVisibility(View.INVISIBLE);if (viewHolder.itemView instanceof FrameLayout) {FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) ((FrameLayout) viewHolder.itemView).getChildAt(1).getLayoutParams();params.gravity = Gravity.RIGHT;((FrameLayout) viewHolder.itemView).getChildAt(1).setLayoutParams(params);}} else {if (viewHolder.itemView instanceof FrameLayout) {FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) ((FrameLayout) viewHolder.itemView).getChildAt(1).getLayoutParams();params.gravity = Gravity.LEFT;((FrameLayout) viewHolder.itemView).getChildAt(1).setLayoutParams(params);}viewHolder.itemArrow_Left.setVisibility(View.INVISIBLE);viewHolder.itemArrow_Right.setVisibility(View.VISIBLE);}}});}@Overridepublic void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {isLeftOfRight((CardViewHolder) viewHolder);......}public class CardViewHolder extends RecyclerView.ViewHolder {public ImageView itemArrow_Left;public ImageView itemArrow_Right;CardViewHolder(View layout) {super(layout);itemArrow_Left = (ImageView) layout.findViewById(R.id.view2);itemArrow_Right = (ImageView) layout.findViewById(R.id.view1);}}public class ItemViewHolder extends CardViewHolder {public ImageView icon;ItemViewHolder (View layout) {super(layout);icon = (ImageView) layout.findViewById(R.id.view3);}}public class TextViewHolder extends CardViewHolder {public TextView time;TextViewHolder(View layout) {super(layout);time = (TextView) layout.findViewById(R.id.textV1);}}}
Data.getDtype获取到的是一个枚举类型 现在唯一的问题是isLeftOfRight方法实现的有点丑陋,并且影响了效率,如果你有更好的欢迎留言建议。
Android 中轴时光轴相关推荐
- Android 3D滑动菜单完全解析,实现推拉门式的立体特效
转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/10471245 在上一篇文章中,我们学习了Camera的基本用法,并借助它们编写了一 ...
- Android高级图片滚动控件,编写3D版的图片轮播器
转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/17482089 大家好,好久不见了,最近由于工作特别繁忙,已经有一个多月的时间没写博 ...
- Android 常用开发功能 博客导航
转载地址:http://blog.csdn.net/ciqing123/article/details/52931663?locationNum=16&fps=1 简介:第一次在CSDN上发表 ...
- 使用ExpandableListView实现一个时光轴
在许多App上都能看到时光轴的效果,比如携程等等,那么我们今天就利用ExpandableListView来实现一个时光轴效果,先来看看效果图: 效果还是挺简单的,这里我们主要是采用Expandable ...
- androidd时光轴效果实现
一个好的应用肯定有一个好看的界面,给自己界面增加各种各样的特效或者独树一帜的外观,即使功能差不多,但你的应用肯定更受欢迎, 给应用加特效一般会写很多xml文件作为控件的背景,这种方式很容易实现,也很简 ...
- 搜集整理的一些博客导航
简介:第一次在CSDN上发表博客,将自己关注或者看过的一些博客整理了一下,其中包含了鸿神和郭神的全部博客,包括两位大神微信公众号推荐的博客,另外还有一些安卓开发社区的博客,后续每天都会更新这个导航,希 ...
- 轴旋转——制作别样的图片浏览器
首页 博客 学院 下载 GitChat TinyMind 论坛 问答 商城 VIP 活动 招聘 ITeye CSTO 写博客 发Chat 贵公子丶笔记 千里之行,始于足下. RSS订阅 转 Andro ...
- 【压岁干货】精彩技术博客+优秀源码集锦
虽然2015年已经过了一月有余,但在中国,好像只有过了春节才算进入新的一年.眼看着这也春节倒计时了,大家好像又都忙了起来,赶项目赶项目-- 从DevStore整理了一些优秀的技术博客和源码作为新春贺礼 ...
- Android之RecyclerView实现时光轴
做项目的过程中有个需求需要时光轴,于是网上找了部分资料 ,写了个案例,现在分享给大家. 如图: activity_main.xml <?xml version="1.0" e ...
- Android 时光轴 -记录生活
/** * * 转载请标明出处:http://blog.csdn.net/u013598111/article/details/50519404 * @author:[JunTao_sun] ...
最新文章
- 两条波浪线符号_四年级数学上册第二单元“线的认识”作业单(附带答案)
- 【机器学习】libsvm使用的数据格式
- 城市轨道交通运营票务管理论文_城市轨道交通票务组织管理论文
- sklearn线性回归
- Android之录音--AudioRecord、MediaRecorder
- ORACLE中表死锁的处理
- linux7自动挂载怎么做,CentOS7 Virtual Box 开机自动挂载共享文件夹
- 数据库实验6 数据库的分组查询和统计查询
- Linux 如何限制用户的磁盘使用量 -- quota
- 20200627每日一句
- Mybatis源码深度解析
- 数据统计分析(SPSS)【8】
- 用uniapp做的一个在线简历,可以发布成为微信小程序,给面试加分
- ShareX(截图工具) 绿色版,功能异常强大
- python的cubes怎么使用_Python measure.marching_cubes方法代碼示例
- 采集新闻数据的10个经典方法
- ps2015安装guideguide参考线辅助工具
- SpringMVC之405错误码
- Android布局优化
- 都说在阿里年薪百万不难,面试入职阿里需要准备什么?
热门文章
- 计算机ps图片在哪里看,怎么看图片有没有PS 两种查看照片有没被PS过的方法-电脑教程...
- 油猴插件安装以及好用的脚本推荐
- windows10搜索卡死(有出现Cortana的请看这篇文章)
- 视频编解码(一):ffmpeg编码H.264帧类型判断
- Mac Spotlight 聚焦搜索
- WinEdit编辑器中中文乱码
- 解决 winedit 打开tex文件 reading error
- 物联网安全风险威胁报告
- 封装jquery的方法
- The server time zone value '?й???????' is unrecognized or represents more than one time zone.