看到有人在问如何实现淘宝商品详情页效果,献上效果图
大致梳理一下思路,这里不提供源码
状态栏透明使用开源库StatusBarCompat,为了兼容手机4.4
1
2
3
4
5
6
7
8
9
10
11
12
|
dependencies { compile ( 'com.github.niorgai:StatusBarCompat:2.1.4' , { exclude group: 'com.android.support' }) } allprojects { repositories { ... maven { url "https://jitpack.io" } } } |
标题栏图标透明度变化参考Api setAlpha()已过时
1
|
icon.setImageAlpha( 0 ); |
Banner控件为ViewPager,淘宝显示为正方形,这里需要修改ViewPager measure函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
public class IdeaViewPager extends ViewPager { private Point point; public IdeaViewPager(Context context) { this (context, null ); } public IdeaViewPager(Context context, AttributeSet attrs) { super (context, attrs); WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); point = new Point(); windowManager.getDefaultDisplay().getSize(point); } @Override protected void onMeasure( int widthMeasureSpec, int heightMeasureSpec) { super .onMeasure(widthMeasureSpec, heightMeasureSpec); setMeasuredDimension(point.x,point.x); } } |
测量View高度,获取到高度集合绑定到ScrollView,根据ScrollView滑动距离判断是属于哪一个Tab选项
1
2
3
4
5
6
7
8
|
public int getMeasureHeight(View view){ int width = View.MeasureSpec.makeMeasureSpec( 0 , View.MeasureSpec.UNSPECIFIED); int height = View.MeasureSpec.makeMeasureSpec( 0 , View.MeasureSpec.UNSPECIFIED); view.measure(width, height); return view.getMeasuredHeight(); } |
重新onScrollChanged函数,实现ViewPager滑动速度比其他View慢
1
2
3
4
5
6
7
|
@Override protected void onScrollChanged( int l, int t, int oldl, int oldt) { super .onScrollChanged(l, t, oldl, oldt); if (viewPager != null && t != oldt) { viewPager.setTranslationY(t/ 2 ); } } |
根据限定距离(Banner)计算百分比偏移量,实现颜色渐变、透明度渐变(淘宝商品详情页有二次颜色渐变)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
@Override protected void onScrollChanged( int l, int t, int oldl, int oldt) { super .onScrollChanged(l, t, oldl, oldt); if (viewPager!= null &&t<=point.x-headerHeight&&getOnScrollChangedColorListener()!= null ){ getOnScrollChangedColorListener().onChanged(Math.abs(t)/Float.valueOf(point.x-headerHeight)); if (t<=(point.x-headerHeight)/ 2 ){ getOnScrollChangedColorListener().onChangedFirstColor(t/(point.x-headerHeight)/ 2 ); } else { getOnScrollChangedColorListener().onChangedSecondColor((t-(point.x-headerHeight)/ 2 )/(point.x-headerHeight)/ 2 ); } } int currentPosition = getCurrentPosition(t,arrayDistance); if (currentPosition!=position&&getOnSelectedIndicateChangedListener()!= null ){ getOnSelectedIndicateChangedListener().onSelectedChanged(currentPosition); } this .position = currentPosition; } |
单一颜色渐变透明度,还原argb通道,修改a值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
ideaScrollView.setOnScrollChangedColorListener( new IdeaScrollView.OnScrollChangedColorListener() { @Override public void onChanged( float percentage) { int color = getAlphaColor(percentage> 0 .9f? 1 .0f:percentage); header.setBackgroundDrawable( new ColorDrawable(color)); radioGroup.setBackgroundDrawable( new ColorDrawable(color)); icon.setImageAlpha(( int ) ((percentage> 0 .9f? 1 .0f:percentage)* 255 )); radioGroup.setAlpha((percentage> 0 .9f? 1 .0f:percentage)* 255 ); setRadioButtonTextColor(percentage); } @Override public void onChangedFirstColor( float percentage) { } @Override public void onChangedSecondColor( float percentage) { } }); ideaScrollView.setOnSelectedIndicateChangedListener( new IdeaScrollView.OnSelectedIndicateChangedListener() { @Override public void onSelectedChanged( int position) { isNeedScrollTo = false ; radioGroup.check(radioGroup.getChildAt(position).getId()); isNeedScrollTo = true ; } }); public int getAlphaColor( float f){ return Color.argb(( int ) (f* 255 ), 0x09 , 0xc1 , 0xf4 ); } |
Tab选项属性不能太频繁,会有颜色值闪烁情况出现,这里需要策略
1
2
3
4
5
6
7
8
9
|
public void setRadioButtonTextColor( float percentage){ if (Math.abs(percentage-currentPercentage)>= 0 .1f){ for ( int i= 0 ;i<radioGroup.getChildCount();i++){ RadioButton radioButton = (RadioButton) radioGroup.getChildAt(i); radioButton.setTextColor(radioButton.isChecked()?getRadioCheckedAlphaColor(percentage):getRadioAlphaColor(percentage)); } this .currentPercentage = percentage; } } |
判断当前属于哪个选项,根据滑动距离与传入绑定的View高度集合来计算
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
private int getCurrentPosition( int t, ArrayList<Integer> arrayDistance) { int index = 0 ; for ( int i= 0 ;i<arrayDistance.size();i++){ if (i==arrayDistance.size()- 1 ){ index = i; } else { if (t>=arrayDistance.get(i)&&t<arrayDistance.get(i+ 1 )){ index = i; break ; } } } return index; } |
切换选项卡以及回到顶部按钮的具体实现参考scrollTo函数
1
2
3
|
private void scrollToPosition( int position){ scrollTo( 0 ,arrayDistance.get(position)); } |
以上代码实现了上图效果,当然也可以使用RecyclerView AbsListView做容器。
希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:https://blog.csdn.net/AnalyzeSystem/article/details/79442196?utm_source=blogxgwz4