三星以前的手机自带一个FlipBoard的app,就是个简报吧。在主页面手指右滑可以看到,新版本的samsung貌似取消这个app了,用bixby取代了。要看效果得去找个以前的samsung手机。
下图是仿照写的一个效果,有点粗糙。
来几张图片
刚进去的效果如下图
稍微滚动下如下图
继续滚动
实现的思路
最上边应该就是个recyclerview,然后顶部带了个悬浮条。
根据上边的图片分下,
最下层一个relativelayout,里边是张图片,文字,然后我盖了个view,用来处理滑动的时候透明度变暗的效果,
在上层就是个recyclerview,最顶部来个悬浮条。
至于recyclerview,我是给第一个item加了个itemDecoration,offsetTop=底部那个relativelayout的高度。
分析完就开始代码实现功能了。
题外话,这里要处理悬浮窗高度的变化,字体的变化,第一个item的时候悬浮窗的特殊处理
先上布局文件
实体类就简单造了一个
data class BriefBean(var title:String,var newArticle: Int,var testContent:String,var color:Int)
item的布局
activity的代码如下
//我们顶部悬浮窗的高度是从150到50变化的,因为recyclerview里那个高度默认是150
var minHeight=50//顶部悬浮窗的最小高度
var maxHeigth=150//最大高度.和item里的顶部分类高度一样
var originalHeigth=300//默认显示的底图的高度,也是recyclerview第一个item的itemDecoration的top的高度
var datas= arrayListOf()
private fun initRv(){
datas.add(BriefBean("商业",8,"place holder business",Color.BLACK))
datas.add(BriefBean("新闻",2,"place holder news",Color.RED))
datas.add(BriefBean("科技",3,"place holder technology",Color.GREEN))
datas.add(BriefBean("体育",6,"place holder sports",Color.BLUE))
datas.add(BriefBean("娱乐",8,"place holder recreation",Color.YELLOW))
rv_brief.apply {
layoutManager=LinearLayoutManager(this@ActivityBriefSamsung)
addItemDecoration(object :RecyclerView.ItemDecoration(){
override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State?) {
var position=parent.getChildAdapterPosition(view)
if(position==0){
outRect.top=originalHeigth //只给第一个弄个偏移量,方便刚进去的时候能看到底部的图片文字
}
}
})
adapter=object :BaseRvAdapter(datas){
override fun getLayoutID(viewType: Int): Int {
return R.layout.item_brief_samsung
}
override fun onBindViewHolder(holder: BaseRvHolder, position: Int) {
var bean=getItemData(position)
holder.setText(R.id.tv_float_title,bean.title)
holder.setText(R.id.tv_float_sub_title,"${bean.newArticle} new articles")
holder.setText(R.id.tv_placeholder,bean.testContent)
holder.getView(R.id.layout_float_top).apply {
visibility=if(position==0) View.GONE else View.VISIBLE//第一个不显示顶部的分类条目的
setBackgroundColor(bean.color)
}
}
}
}
rv_brief.addOnScrollListener(object :RecyclerView.OnScrollListener(){
override fun onScrollStateChanged(recyclerView: RecyclerView?, newState: Int) {
super.onScrollStateChanged(recyclerView, newState)
}
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
var manager=recyclerView.layoutManager as LinearLayoutManager
var first=manager.findFirstVisibleItemPosition();
var holder=recyclerView.findViewHolderForAdapterPosition(first)
var firstTop=holder.itemView.top//第一个可见item的top,和屏幕顶部的距离
var firstBottom=holder.itemView.bottom
var layoutParams1=layout_float_top1.layoutParams//这个是顶部悬浮条的布局,因为滑动的时候要修改
var data=datas[first]
if(first==0){//第一条数据和后边有点区别,单独处理
if(firstTop>=minHeight){
layoutParams1.height=minHeight//刚开始的时候上边的标题也就文字从透明到不透明,而高度是没变化的,
layout_float_top1.setBackgroundColor(Color.TRANSPARENT)//背景开始是透明的
var alpha=1-(firstTop-minHeight)*1f/(originalHeigth-minHeight)//根据滑动距离来修改透明度。
tv_float_title1.alpha=alpha
view_mask.alpha=alpha
view_mask.y=firstTop-originalHeigth*1f
iv_top_.scrollTo(0,-(firstTop-originalHeigth)/2)//滚动底图,用实际的一半距离。
}else{
view_mask.y=-originalHeigth*1f//把mask这个view滚到屏幕外边去,免得影响
layout_float_top1.setBackgroundColor(data.color)/修改悬浮条颜色
}
tv_float_title1.setTextSize(TypedValue.COMPLEX_UNIT_SP,26f)//实际体验发现首个黑色的背景标题字体颜色比较大
tv_float_sub_title1.setText("")
}else{
var changeHeight=maxHeigth+firstTop
layoutParams1.height=Math.max(changeHeight,minHeight)
//字体大小从18sp到15sp变化,而悬浮窗高度从maxheight到minHeight变化
tv_float_title1.setTextSize(TypedValue.COMPLEX_UNIT_SP,15f+3f*(layoutParams1.height-minHeight)/(maxHeigth-minHeight))
layout_float_top1.setBackgroundColor(data.color)
tv_float_sub_title1.setText("${data.newArticle} new articles")
tv_float_sub_title1.alpha=Math.max(0f,1-(maxHeigth-layoutParams1.height)/40f)//滑动个40dp就让子标题不可见
}
tv_float_title1.setText(data.title)
if(firstBottom<=minHeight){//这里处理悬浮窗往上滚出屏幕的效果
layout_float_top1.y=firstBottom-minHeight*1f
layoutParams1.height=minHeight
}else{
layout_float_top1.y=0f
}
layout_float_top1.layoutParams=layoutParams1
}
})
}