美文网首页Android Demo
仿慕课APP的导航栏指示器

仿慕课APP的导航栏指示器

作者: 飞奔吧牛牛 | 来源:发表于2019-12-09 13:41 被阅读0次
    仿慕课APP的导航栏指示器

    分析:一条线段,在标题之间移动,移动到两个标题中间时长度最长,反之,移动到标题正下方时最短。也就是说,该线段在水平位移的同时,长度也随之变化,接近左边标题时,长度与位移成正相关,接近右边标题时,长度与位移成负相关。这本质上是两个二元一次方程,求系数和常数项的问题。起点终点都有值,可解。

    
    import android.content.Context;
    import android.graphics.Color;
    import android.util.AttributeSet;
    import android.util.Log;
    import android.util.SparseArray;
    import android.util.SparseIntArray;
    import android.view.View;
    import android.view.ViewGroup;
    import android.view.ViewTreeObserver;
    import android.widget.LinearLayout;
    import android.widget.TextView;
    
    import androidx.viewpager.widget.ViewPager;
    
    import com.sony.dtv.moocnavbar.R;
    
    import java.util.List;
    
    public class MoocNavBar extends LinearLayout {
    
        private List<String> titles;
        private Context context;
        private View indictor;
        private SparseIntArray toLeftMap = new SparseIntArray();//title到left的距离
        private int defaultPos = 0; //默认pos
        private int minW = 15;  //指示器的最小width
    
        public MoocNavBar(Context context) {
            this(context, null);
        }
    
        public MoocNavBar(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public MoocNavBar(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            this.context = context;
            setOrientation(VERTICAL);
        }
    
        public void setTitle(List<String> title) {
            this.titles = title;
            //titles
            LinearLayout titleContainer = new LinearLayout(context);
            titleContainer.setOrientation(HORIZONTAL);
            LayoutParams titleLP = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
            titleContainer.setLayoutParams(titleLP);
            fillTitle(titleContainer, title);
            addView(titleContainer);
            //indictor
            indictor = new View(context);
            LinearLayout.LayoutParams indictorLP = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
            indictorLP.bottomMargin = 10;
            indictorLP.width = minW;
            indictorLP.height = 6;
            indictor.setLayoutParams(indictorLP);
            indictor.setBackgroundResource(R.drawable.nav_indictor_bg);
            addView(indictor);
        }
    
        private void fillTitle(final LinearLayout titleContainer, List<String> titles) {
            for (int i = 0; i < titles.size(); i++) {
                String s = titles.get(i);
                final TextView titleItemView = new TextView(context);
                LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
                titleItemView.setLayoutParams(params);
                titleItemView.setText(s);
                titleItemView.setTextColor(Color.BLACK);
                titleItemView.setPadding(30, 10, 30, 10);
                final int finalI = i;
                titleItemView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                    @Override
                    public void onGlobalLayout() {
                        titleItemView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                        int left = titleItemView.getWidth() / 2 + titleItemView.getLeft();
                        Log.e("TAG", finalI + " : " + left);
                        toLeftMap.append(finalI, left);
                        if (finalI == defaultPos) {
                            //
                            moveIndictor(finalI, 0);
                        }
                    }
                });
                titleContainer.addView(titleItemView);
            }
        }
    
        public void setViewPager(ViewPager viewPager) {
            viewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
                @Override
                public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                    moveIndictor(position, positionOffset);
                }
            });
        }
    
        //根据页面切换过程,改变指示器位置和大小
        private void moveIndictor(int position, float positionOffset) {
            //在某两个page之间滑动时,获取对应的两个title的中点位置
            int l1 = toLeftMap.get(position);
            int l2 = toLeftMap.get(position + 1);
            //两点间距
            int datL = l2 - l1;
            //指示器中点应该在哪个位置
            int middle = (int) (l1 + datL * positionOffset);
            //指示器宽度最大值
            int maxW = datL / 3 * 2;
            //指示器最大最小值差距
            int datW = maxW - minW;
            //实际宽度
            int realW;
            if (positionOffset <= 0.5) {
                realW = (int) (minW + 2 * positionOffset * datW);
            } else {
                realW = (int) (minW + (1 - positionOffset) * 2 * datW);
            }
            //设置左右位置
            indictor.setLeft(middle - realW / 2);
            indictor.setRight(middle + realW / 2);
        }
    
    }
    
    

    相关文章

      网友评论

        本文标题:仿慕课APP的导航栏指示器

        本文链接:https://www.haomeiwen.com/subject/bezcgctx.html