三星以前的手機自帶一個FlipBoard的app哈雏,就是個簡報吧。在主頁面手指右滑可以看到,新版本的samsung貌似取消這個app了贩疙,用bixby取代了讹弯。要看效果得去找個以前的samsung手機。
下圖是仿照寫的一個效果这溅,有點粗糙组民。
device-2018-05-23-113305.gif
來幾張圖片
剛進去的效果如下圖
image.png
稍微滾動下如下圖
image.png
繼續(xù)滾動
image.png
實現(xiàn)的思路
最上邊應(yīng)該就是個recyclerview,然后頂部帶了個懸浮條悲靴。
根據(jù)上邊的圖片分下臭胜,
最下層一個relativelayout,里邊是張圖片癞尚,文字耸三,然后我蓋了個view,用來處理滑動的時候透明度變暗的效果浇揩,
在上層就是個recyclerview仪壮,最頂部來個懸浮條。
至于recyclerview,我是給第一個item加了個itemDecoration临燃,offsetTop=底部那個relativelayout的高度睛驳。
分析完就開始代碼實現(xiàn)功能了。
題外話膜廊,這里要處理懸浮窗高度的變化乏沸,字體的變化,第一個item的時候懸浮窗的特殊處理
先上布局文件
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:id="@+id/layout_top_bg"
android:layout_width="match_parent"
android:layout_height="300dp">
<ImageView
android:id="@+id/iv_top_"
android:src="@mipmap/pic11"
android:scaleType="fitXY"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<TextView
android:id="@+id/tv_title"
android:textColor="#fff"
android:textSize="20sp"
android:textStyle="bold"
android:layout_alignParentBottom="true"
android:text="title................title..........title"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</RelativeLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/rv_brief"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<View
android:id="@+id/view_mask"
android:background="#000000"
android:alpha="0.0"
android:layout_width="match_parent"
android:layout_height="300dp"/>
<RelativeLayout
android:id="@+id/layout_float_top1"
android:layout_width="match_parent"
android:layout_height="50dp">
<ImageView
android:id="@+id/iv_3dot1"
android:layout_alignParentRight="true"
android:layout_margin="3dp"
android:src="@android:drawable/ic_input_add"
android:layout_width="44dp"
android:layout_height="44dp" />
<TextView
android:id="@+id/tv_float_title1"
android:text="商業(yè)"
android:textSize="26sp"
android:textColor="#fff"
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tv_float_sub_title1"
android:text="8 articles"
android:textColor="#fff"
android:textSize="13sp"
android:layout_alignParentBottom="true"
android:layout_marginBottom="10dp"
android:layout_centerHorizontal="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
</FrameLayout>
實體類就簡單造了一個
data class BriefBean(var title:String,var newArticle: Int,var testContent:String,var color:Int)
item的布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="wrap_content">
<RelativeLayout
android:id="@+id/layout_float_top"
android:layout_width="match_parent"
android:layout_height="150dp">
<ImageView
android:id="@+id/iv_3dot"
android:layout_alignParentRight="true"
android:layout_margin="3dp"
android:src="@android:drawable/ic_input_add"
android:layout_width="46dp"
android:layout_height="46dp" />
<TextView
android:id="@+id/tv_float_title"
android:text="title"
android:textSize="18sp"
android:textColor="#fff"
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tv_float_sub_title"
android:text="8 articles"
android:textColor="#fff"
android:textSize="13sp"
android:layout_alignParentBottom="true"
android:layout_marginBottom="10dp"
android:layout_centerHorizontal="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
<TextView
android:id="@+id/tv_placeholder"
android:text="place holder"
android:gravity="center"
android:background="#ffffff"
android:layout_width="match_parent"
android:layout_height="530dp" />
</LinearLayout>
activity的代碼如下
//我們頂部懸浮窗的高度是從150到50變化的爪瓜,因為recyclerview里那個高度默認是150
var minHeight=50//頂部懸浮窗的最小高度
var maxHeigth=150//最大高度.和item里的頂部分類高度一樣
var originalHeigth=300//默認顯示的底圖的高度蹬跃,也是recyclerview第一個item的itemDecoration的top的高度
var datas= arrayListOf<BriefBean>()
private fun initRv(){
datas.add(BriefBean("商業(yè)",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<BriefBean>(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<View>(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){//第一條數(shù)據(jù)和后邊有點區(qū)別,單獨處理
if(firstTop>=minHeight){
layoutParams1.height=minHeight//剛開始的時候上邊的標題也就文字從透明到不透明薄货,而高度是沒變化的翁都,
layout_float_top1.setBackgroundColor(Color.TRANSPARENT)//背景開始是透明的
var alpha=1-(firstTop-minHeight)*1f/(originalHeigth-minHeight)//根據(jù)滑動距離來修改透明度。
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)//實際體驗發(fā)現(xiàn)首個黑色的背景標題字體顏色比較大
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
}
})
}