欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android开发之仿淘宝商品详情页

程序员文章站 2022-05-31 14:04:34
...

看到有人在问如何实现淘宝商品详情页效果,手痒了就撸了一个,献上效果图
Android开发之仿淘宝商品详情页

大致梳理一下思路,这里不提供源码

状态栏透明使用开源库StatusBarCompat,为了兼容手机4.4

dependencies {
        compile ('com.github.niorgai:StatusBarCompat:2.1.4', {
            exclude group: 'com.android.support'
        })
    }

allprojects {
        repositories {
            ...
            maven { url "https://jitpack.io" }
        }
    }

标题栏图标透明度变化参考Api setAlpha()已过时

 icon.setImageAlpha(0);

Banner控件为ViewPager,淘宝显示为正方形,这里需要修改ViewPager measure函数


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选项


    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慢

  @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)计算百分比偏移量,实现颜色渐变、透明度渐变(淘宝商品详情页有二次颜色渐变)

 @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值

 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选项属性不能太频繁,会有颜色值闪烁情况出现,这里需要策略

 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高度集合来计算

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函数


    private void scrollToPosition(int position){
        scrollTo(0,arrayDistance.get(position));
    }

以上代码实现了上图效果,当然也可以使用RecyclerView AbsListView做容器