先上效果图
效果就是上面图片的效果 接下来看看如何实现
-
首先我们来看下布局文件
<LinearLayoutandroid:id="@+id/header"android:layout_width="match_parent"android:layout_height="72dp"android:paddingTop="24dp"android:background="#00FFFFFF"android:orientation="horizontal"><ImageViewandroid:layout_width="30dp"android:layout_height="30dp"android:layout_gravity="center"android:src="@drawable/back"/><Viewandroid:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"/><ImageViewandroid:id="@+id/icon"android:layout_width="30dp"android:layout_height="30dp"android:src="@drawable/aa"android:layout_gravity="center"/><Viewandroid:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"/><ImageViewandroid:layout_width="30dp"android:layout_height="30dp"android:layout_gravity="center"/></LinearLayout>
这块主要是设置刚进入页面时的透明头部 主要组成部分有返回键 和头部的方形小图片 还有分享按钮 以及你想附加的标题功能 默认进入是透明的只显示返回按钮
<FrameLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"><RadioGroupandroid:id="@+id/radioGroup"android:background="#00FFFFFF"android:layout_width="match_parent"android:orientation="horizontal"android:layout_height="48dp"><RadioButtonandroid:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:button="@null"android:textColor="#00000000"android:gravity="center"android:text="宝贝"/><RadioButtonandroid:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:button="@null"android:textColor="#00000000"android:gravity="center"android:text="评价"/><RadioButtonandroid:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:button="@null"android:textColor="#00000000"android:gravity="center"android:text="详情"/><RadioButtonandroid:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:gravity="center"android:button="@null"android:textColor="#00000000"android:text="推荐"/></RadioGroup><Viewandroid:id="@+id/layer"android:layout_width="match_parent"android:background="#00FFFFFF"android:layout_height="48dp"/></FrameLayout>
这部分主要是我们的标签选项卡 我这边采用的是RadioGroup+radioButton实现的 类似于淘宝的商品、评价、详情等标签
这样我们的页面布局头部就完成了 下面我们来看下具体组成内容
<com.text.lg.ideascrollview.IdeaScrollViewandroid:id="@+id/ideaScrollView"android:layout_width="match_parent"android:layout_height="match_parent"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"><LinearLayoutandroid:id="@+id/one"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"><com.text.lg.ideascrollview.IdeaViewPagerandroid:id="@+id/viewPager"android:layout_width="match_parent"android:background="@drawable/aa"android:layout_height="wrap_content"/><ImageViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:src="@drawable/one"/></LinearLayout><LinearLayoutandroid:id="@+id/two"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"><ImageViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:src="@drawable/two"/><ImageViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:src="@drawable/three"/></LinearLayout><ImageViewandroid:id="@+id/three"android:layout_width="match_parent"android:layout_height="wrap_content"android:src="@drawable/four"/><LinearLayoutandroid:id="@+id/four"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"><ImageViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:src="@drawable/five"/><ImageViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:src="@drawable/six"/><ImageViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:src="@drawable/six"/><ImageViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:src="@drawable/six"/></LinearLayout></LinearLayout></com.text.lg.ideascrollview.IdeaScrollView>
这部分就是我们的具体页面内容 可以看到我们的详情页面数据使用自定义的一个Scrollview来包裹的 其中分为4块 我们布局里面写的很清楚 分别对应着详情页中的四个模块 当然 我这里面只是用图片来代替内容了 具体内容可自己填充
-
下面来看下我们具体实现代码
StatusBarCompat.translucentStatusBar(this);
我这边是采用的第三方的沉浸式透明状态栏 你们可以自行替换
dependencies {compile ('com.github.niorgai:StatusBarCompat:2.1.4', {exclude group: 'com.android.support'})}
这个是我沉浸式状态栏的依赖 感兴趣的可以了解一下
Rect rectangle= new Rect();getWindow().getDecorView().getWindowVisibleDisplayFrame(rectangle);ideaScrollView.setViewPager(viewPager,getMeasureHeight(headerParent)-rectangle.top);icon.setImageAlpha(0);radioGroup.setAlpha(0);radioGroup.check(radioGroup.getChildAt(0).getId());
上面是获取状态栏的高度并且使用自定义scrollview绑定banner图片 并获取图片高度
以及初始化我们头部部分控件的透明度 和默认选择第一个标签
View one = findViewById(R.id.one);
View two = findViewById(R.id.two);
View four = findViewById(R.id.four);
View three = findViewById(R.id.three);
ArrayList<Integer> araryDistance = new ArrayList<>();araryDistance.add(0);
araryDistance.add(getMeasureHeight(one)-getMeasureHeight(headerParent));
araryDistance.add(getMeasureHeight(one)+getMeasureHeight(two)-getMeasureHeight(headerParent)); araryDistance.add(getMeasureHeight(one)+getMeasureHeight(two)+getMeasureHeight(three)-getMeasureHeight(headerParent));ideaScrollView.setArrayDistance(araryDistance);
这块是我们获取到我们的四个模块的高度 并把高度存到集合中 传入到我们自定义的scrollview中
private void scrollToPosition(int position){scrollTo(0,arrayDistance.get(position));}
scrollview通过传过来的高度进行定位滑动 意思就是点击我们的标题选项滑动到相应的位置
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();}
这个是获取控件高度的方法
ideaScrollView.setOnScrollChangedColorListener(new IdeaScrollView.OnScrollChangedColorListener() {@Overridepublic 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);}@Overridepublic void onChangedFirstColor(float percentage) {}@Overridepublic void onChangedSecondColor(float percentage) {}});
这个监听方法是监测我们滑动的距离 来改变我们标题的颜色 从透明慢慢滑动进行颜色渐变 以及设置我们头部控件的颜色 和展示我们的标题选项卡
public int getAlphaColor(float f){return Color.argb((int) (f*255),0x09,0xc1,0xf4);}public int getLayerAlphaColor(float f){return Color.argb((int) (f*255),0x09,0xc1,0xf4);}public int getRadioCheckedAlphaColor(float f){return Color.argb((int) (f*255),0x44,0x44,0x44);}public int getRadioAlphaColor(float f){return Color.argb((int) (f*255),0xFF,0xFF,0xFF);}
可以根据这块来改变我们头部以及标题的颜色 根据传入的值来进行颜色渐变
ideaScrollView.setOnSelectedIndicateChangedListener(new IdeaScrollView.OnSelectedIndicateChangedListener() {@Overridepublic void onSelectedChanged(int position) {isNeedScrollTo = false;radioGroup.check(radioGroup.getChildAt(position).getId());isNeedScrollTo = true;}});radioGroup.setOnCheckedChangeListener(radioGroupListener);private RadioGroup.OnCheckedChangeListener radioGroupListener =new RadioGroup.OnCheckedChangeListener() {@Overridepublic void onCheckedChanged(RadioGroup group, @IdRes int checkedId) {for(int i=0;i<radioGroup.getChildCount();i++){RadioButton radioButton = (RadioButton) radioGroup.getChildAt(i);radioButton.setTextColor(radioButton.isChecked()?getRadioCheckedAlphaColor(currentPercentage):getRadioAlphaColor(currentPercentage));if(radioButton.isChecked()&&isNeedScrollTo){ideaScrollView.setPosition(i);}}}};
根据这两个监听方法来改变我们标题的选中tab 滑动到不同的位置选中对应的Tab并改变颜色 具体实现方法看自定义Scrollview
根据限定距离(Banner)计算百分比偏移量,实现颜色渐变、透明度渐变(淘宝商品详情页有二次颜色渐变)
@Overrideprotected 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);}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;}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;}
下面是自定义Scrollview的全部代码
package com.text.lg.ideascrollview;import android.content.Context;
import android.graphics.Point;
import android.util.AttributeSet;
import android.view.WindowManager;
import android.widget.ScrollView;import java.util.ArrayList;public class IdeaScrollView extends ScrollView {private final Point point;private IdeaViewPager viewPager;private int position = 0;ArrayList<Integer> arrayDistance = new ArrayList<>();private int headerHeight;public IdeaScrollView(Context context) {this(context,null,0);}public IdeaScrollView(Context context, AttributeSet attrs) {this(context, attrs,0);}public IdeaScrollView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);point = new Point();windowManager.getDefaultDisplay().getSize(point);}@Overrideprotected 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);}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;}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;}private void scrollToPosition() {scrollToPosition(position);}private void scrollToPosition(int position){scrollTo(0,arrayDistance.get(position));}public void setViewPager(IdeaViewPager viewPager,int headerHeight){this.viewPager = viewPager;this.headerHeight = headerHeight;}public interface OnScrollChangedColorListener{void onChanged(float percentage);void onChangedFirstColor(float percentage);void onChangedSecondColor(float percentage);}public interface OnSelectedIndicateChangedListener{void onSelectedChanged(int position);}private OnSelectedIndicateChangedListener onSelectedIndicateChangedListener;private OnScrollChangedColorListener onScrollChangedColorListener;public OnScrollChangedColorListener getOnScrollChangedColorListener() {return onScrollChangedColorListener;}public void setOnScrollChangedColorListener(OnScrollChangedColorListener onScrollChangedColorListener) {this.onScrollChangedColorListener = onScrollChangedColorListener;}public IdeaViewPager getViewPager() {return viewPager;}public int getPosition() {return position;}public void setPosition(int position) {this.position = position;scrollToPosition();}public ArrayList<Integer> getArrayDistance() {return arrayDistance;}public void setArrayDistance(ArrayList<Integer> arrayDistance) {this.arrayDistance = arrayDistance;}public OnSelectedIndicateChangedListener getOnSelectedIndicateChangedListener() {return onSelectedIndicateChangedListener;}public void setOnSelectedIndicateChangedListener(OnSelectedIndicateChangedListener onSelectedIndicateChangedListener) {this.onSelectedIndicateChangedListener = onSelectedIndicateChangedListener;}
}
以上代码就实现了文中效果图样式
本文借鉴了大佬博客内容 https://blog.csdn.net/AnalyzeSystem/article/details/79442196?from=singlemessage