山寨风,高仿QQ附近的人筛选功能的滑动选择列表来袭!
今天在准备新项目的界面,偶然翻到了QQ附近的人那个筛选功能,嗯,觉得效果还不错,效果大概是这样子的。QQ的原图我就不上了,我就上我做的效果图。
觉得so easy是吧,但是我整整做了4个多小时,个多小时,多小时,小时,时。。。。
唉,苦话不多说,先分析一下界面。
主要功能分析
界面分析
功能实现
public class MainActivity extends AppCompatActivity
{FocusRecyclerView mRecyclerView;private List<String> mDatas = new ArrayList<>();@Overrideprotected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mDatas = new ArrayList<>();for (int i = 0; i < 30; i++){mDatas.add("嘻嘻:" + i);}mRecyclerView = (FocusRecyclerView) findViewById(R.id.recyclerView);mRecyclerView.setAdapter(new RecyclerView.Adapter<MyViewHolder>(){@Overridepublic MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType){View view = LayoutInflater.from(MainActivity.this).inflate(R.layout.recyclerview_item, parent, false);MyViewHolder viewHolder = new MyViewHolder(view);return viewHolder;}@Overridepublic void onBindViewHolder(MyViewHolder holder, int position){holder.textView.setText(mDatas.get(position));}@Overridepublic int getItemCount(){return mDatas.size();}});mRecyclerView.setLayoutManager(new SnappingLinearLayoutManager(this, LinearLayoutManager.VERTICAL,false));}class MyViewHolder extends RecyclerView.ViewHolder{private TextView textView;public MyViewHolder(View itemView){super(itemView);textView = (TextView) itemView.findViewById(R.id.tv);}}}
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayoutxmlns: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="com.chenantao.main.MainActivity"><com.chenantao.main.FocusRecyclerViewandroid:id="@+id/recyclerView"android:layout_width="match_parent"android:layout_height="match_parent"/>
</RelativeLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><TextViewandroid:id="@+id/tv"android:text="嘻嘻"android:layout_width="wrap_content"android:layout_height="wrap_content"android:gravity="center"android:textSize="25sp"/>
</LinearLayout>
自定义RecyclerView
public static final int DISPLAY_ITEM_COUNT = 5;//只能同时展示5条数据,注意,只能展示奇数条数据private int mMaxTextSize = 30, mMinTextSize = 10;//sp,textview字体大小最大以及最小限制private double mMaxTextAlpha = 0.9, mMinTextAlpha = 0.4;//textview透明度最大以及最小限制private Paint mSelectedBorderPaint;//绘制选择框的paintprivate SnappingLinearLayoutManager mLayoutManager;//自定义的布局管理器,可以缓慢滑动到指定位置private double mTextSizeScale, mTextAlphaScale;//字体大小以及透明度的梯度值public FocusRecyclerView(Context context, AttributeSet attrs){super(context, attrs);//将dp转换为pxmMaxTextSize = (int) DimensionUtils.sp2px(mMaxTextSize, getResources().getDisplayMetrics());mMinTextSize = (int) DimensionUtils.sp2px(mMinTextSize, getResources().getDisplayMetrics());mSelectedBorderPaint = new Paint();mSelectedBorderPaint.setColor(0x6600BFFF);mSelectedBorderPaint.setAntiAlias(true);mSelectedBorderPaint.setStyle(Paint.Style.STROKE);mSelectedBorderPaint.setStrokeWidth(3);}
绘制选择框
/*** 画出选择框** @param c*/@Overridepublic void onDraw(Canvas c){super.onDraw(c);int width = getMeasuredWidth();int height = getMeasuredHeight();int itemHeight = height / DISPLAY_ITEM_COUNT;int t = (height - itemHeight) / 2;Rect rect = new Rect(0, t, width, t + itemHeight);c.drawRect(rect, mSelectedBorderPaint);}
滑动到中点对应的item
/*** 在滑动停止的时候设置选中的条目** @param state*/@Overridepublic void onScrollStateChanged(int state){super.onScrollStateChanged(state);if (state == SCROLL_STATE_IDLE){scrollToSelectedView();}}
/*** 滑动到目前选择框选中的item*/private void scrollToSelectedView(){//取得中点对应的item,类似于listview的pointToPositionView selectView = findChildViewUnder(getMeasuredWidth() / 2, getMeasuredHeight() / 2);int pos = getChildAdapterPosition(selectView);mLayoutManager.smoothScrollToPosition(this, null, pos - ((DISPLAY_ITEM_COUNT - 1) / 2));}
/*** 滑动到目前选择框选中的item*/private void scrollToSelectedView(){//取得中点对应的item,类似于listview的pointToPositionView selectView = findChildViewUnder(getMeasuredWidth() / 2, getMeasuredHeight() / 2);int pos = getChildAdapterPosition(selectView);
// mLayoutManager.smoothScrollToPosition(this, null, pos - ((DISPLAY_ITEM_COUNT - 1) / 2));mLayoutManager.scrollToPositionWithOffset(pos - ((DISPLAY_ITEM_COUNT - 1) / 2),0);}
public class SnappingLinearLayoutManager extends LinearLayoutManager
{private static final float MILLISECONDS_PER_INCH = 500f;private Context mContext;public SnappingLinearLayoutManager(Context context, int orientation, boolean reverseLayout){super(context, orientation, reverseLayout);}@Overridepublic void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state,int position){RecyclerView.SmoothScroller smoothScroller = new TopSnappedSmoothScroller(recyclerView.getContext()){//This controls the direction in which smoothScroll looks for your view@Overridepublic PointF computeScrollVectorForPosition(int targetPosition){return new PointF(0, 1);}//This returns the milliseconds it takes to scroll one pixel.@Overrideprotected float calculateSpeedPerPixel(DisplayMetrics displayMetrics){return MILLISECONDS_PER_INCH / displayMetrics.densityDpi;}};smoothScroller.setTargetPosition(position);startSmoothScroll(smoothScroller);}private class TopSnappedSmoothScroller extends LinearSmoothScroller{public TopSnappedSmoothScroller(Context context){super(context);}@Overridepublic PointF computeScrollVectorForPosition(int targetPosition){return SnappingLinearLayoutManager.this.computeScrollVectorForPosition(targetPosition);}@Overrideprotected int getVerticalSnapPreference(){return SNAP_TO_START;}}
}
/*** 滑动到目前选择框选中的item*/private void scrollToSelectedView(){//取得中点对应的item,类似于listview的pointToPositionView selectView = findChildViewUnder(getMeasuredWidth() / 2, getMeasuredHeight() / 2);int pos = getChildAdapterPosition(selectView);mLayoutManager.smoothScrollToPosition(this, null, pos - ((DISPLAY_ITEM_COUNT - 1) / 2));}
其实就跟第一次的时候一样了,到这里就完成了,可以自动将中点的item装入到选择框。那么接下来的事情就简单了,无非就是改改透明度字体大小。
随着距离而改变的item
/*** 设置可视recyclerView可视item的属性(字体大小、透明度)*/public void setItemStyle(){int firstVisiblePos = mLayoutManager.findFirstVisibleItemPosition();int lastVisiblePos = mLayoutManager.findLastVisibleItemPosition();for (int i = firstVisiblePos; i <= lastVisiblePos; i++){View view = mLayoutManager.findViewByPosition(i);int itemHeight = getMeasuredHeight() / DISPLAY_ITEM_COUNT;int x = (int) view.getX();int y = (int) view.getY();//itemCenter:item的中点,相对于parent的y距离int itemCenter = y + itemHeight / 2;if (itemCenter < 0) itemCenter = 0;//distanceToCenter:item的中点距离parent的y距离int distanceToCenter = Math.abs(getMeasuredHeight() / 2 - itemCenter);TextView textview = (TextView) view.findViewById(R.id.tv);//距离中点最近的时候透明度最大,字体也最大//设置textview字体大小随着距离中点距离的改变而改变textview.setTextSize((float) (mMaxTextSize - mTextSizeScale * distanceToCenter));//设置textview透明度随着距离中点距离的改变而改变textview.setAlpha((float) (mMaxTextAlpha - mTextAlphaScale * distanceToCenter));}}
嗯,根据第一个可视item的位置以及最后一个最后可视item的位置来遍历可视的view。然后计算这些view距离中点的距离,在结合前面定义的梯度值来设置字体大小与透明度,关于这个梯度值,你看最后两行你也明白了,其实也可以理解成根据距离来决定变化幅度的因子,这个你想怎么决定就怎么决定,没有什么要求的。ok,到这里基本就完成了,还有什么得注意的呢?在哪里调用这个setItemStyle方法呢?我们滑动的时候这些item的样子也要跟着变化吧?首次加载显式出来的时候也要有样子吧?
@Overridepublic void onScrolled(int dx, int dy){super.onScrolled(dx, dy);setItemStyle();}
@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b){super.onLayout(changed, l, t, r, b);if (changed){if (mLayoutManager != null){setItemStyle();}}}
注意这里要判断一下布局管理器设置进来了没,因为你就算还没设置布局管理器,它还是会调用onMeasure、onLayout的。这样可能会空指针异常。Ok,到这里就完了。
完结
End!~
山寨风,高仿QQ附近的人筛选功能的滑动选择列表来袭!相关推荐
- Android实现高仿QQ附近的人搜索展示
本文主要实现了高仿QQ附近的人搜索展示,用到了自定义控件的方法 最终效果如下 1.下面展示列表我们可以使用ViewPager来实现(当然如果你不觉得麻烦,你也可以用HorizontalScrollVi ...
- 安卓高仿京东淘宝的筛选功能,全网最简单方便
最近需要实现一个筛选的功能.但是在网上找了半天都写得特别乱,要不就是收费,今天做一个.实现效果图如下. 点击按钮直接弹出.可以放在任何控件下面.下面是使用代码: 首先需要添加依赖: 在build.gr ...
- 高仿QQ的手机管家的小火箭加速
高仿QQ的手机管家的小火箭加速 1.前言 腾讯的手机管家,用过这个App的人都应该知道桌面的火箭一键加速这个功能,研究一下这个小火箭是怎么做出来的.先来了解一下小火箭有神马动作,首先在没有触碰它时,就 ...
- android 自定义特效,Android自定义View之高仿QQ健康
我们都知道自定义View一般有三种直接继承View.继承原有的控件对控件的进行修改.重新拼装组合,最后一种主要针对于ViewGroup.具体的怎么做不是本文的所涉及的内容(本文是基于第一种方式实现的) ...
- 高仿qq搜索附近界面
首页 资讯 文章 频道 资源 小组 相亲 登录 注册 首页 所有文章 行业动态 技术分享 产品设计 工具资源 安卓小组 更多频道▼ - 导航条 - 首页所有文章 行业动态技术分享 产品设计 工具资源安 ...
- 如何使用MFC编写自定义UI界面【附高仿QQ 2014登陆界面范例程序】
地址: http://blog.csdn.net/hujkay作者:Jekkay Hu(34538980@qq.com)关键词:MFC, 编写异行窗体,自定义UI控件,VC++,异形控件,高仿QQ登陆 ...
- 高仿QQ即时聊天软件开发系列之三登录窗口用户选择下拉框
上一篇高仿QQ即时聊天软件开发系列之二登录窗口界面写了一个大概的布局和原理 这一篇详细说下拉框的实现原理 先上最终效果图 一开始其实只是想给下拉框加一个placeholder效果,让下拉框在未选择未输 ...
- android qq红点,Android高仿QQ小红点功能
先给大家展示下效果图: 绘制贝塞尔曲线: 主要是当在一定范围内拖拽时算出固定圆和拖拽圆的外切直线以及对应的切点,就可以通过path.quadTo()来绘制二阶贝塞尔曲线了~ 整体思路: 1.当小红点静 ...
- android+qq底部界面,Android 高仿QQ 界面滑动效果
Android高仿QQ界面滑动效果 点击或者滑动切换画面,用ViewPager实现, 首先是布局文件: android:layout_width="match_parent" an ...
最新文章
- 利用反射计芯片进行非接触式液位测量
- REST API出错响应的设计(转)
- LindDotNetCore~Mock对实际应用中的意义
- boost::interprocess::ipcdetail::private_adaptive_node_pool用法的测试程序
- java中for的常规用法_Java for循环的几种用法详解
- 『飞秋』WCF热门问题编程示例
- 2c总线的布线宽度_PCIExpress总线接口的布线规则
- keepalived vrrp script|interface weight when positive,nagtive,zero vrrp's status transition
- 杰奇python采集器_linux下能完美运行的杰奇采集器ckp
- 在spyder怎么升级_怎么更新spyder?
- css鼠标移入变成小手
- mqdf python_GitHub - jugg1024/court_recognition
- Packet Tracer - 排除 HSRP 故障
- 体验godaddy域名转入,添加A记录,及使用dnspod的NS
- Github标签管理
- 堆是先进先出,栈是先进后出
- 英语读书笔记-Book Lovers Day 04
- 用Python写前端是什么体验?
- Android kotlin 基础知识codelab Fragment Summary
- 《刻意练习》读书笔记思维导图精华版,探索成功的秘诀