最近常見的一個導航欄指示器

圖片發(fā)自簡書App

由于個人使用慕課網(wǎng)APP和網(wǎng)易云音樂APP比較多棠枉,發(fā)現(xiàn)兩者都有這種指示器,現(xiàn)動手實現(xiàn)下颠蕴。

分析:

一條線段埠对,在標題之間移動,移動到兩個標題中間時長度最長裁替,反之,移動到標題正下方時最短貌笨。也就是說弱判,該線段在水平位移的同時,長度也隨之變化锥惋,接近左邊標題時昌腰,長度與位移成正相關(guān),接近右邊標題時膀跌,長度與位移成負相關(guān)遭商。這本質(zhì)上是兩個二元一次方程,求系數(shù)和常數(shù)項的問題捅伤。起點終點都有值劫流,可解。


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);
            }
        });
    }

    //根據(jù)頁面切換過程丛忆,改變指示器位置和寬度
    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);
        }
        //設(shè)置左右位置
        indictor.setLeft(middle - realW / 2);
        indictor.setRight(middle + realW / 2);
    }

}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市熄诡,隨后出現(xiàn)的幾起案子可很,更是在濱河造成了極大的恐慌,老刑警劉巖凰浮,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件我抠,死亡現(xiàn)場離奇詭異苇本,居然都是意外死亡,警方通過查閱死者的電腦和手機菜拓,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進店門瓣窄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人尘惧,你說我怎么就攤上這事康栈。” “怎么了喷橙?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵啥么,是天一觀的道長。 經(jīng)常有香客問我贰逾,道長悬荣,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任疙剑,我火速辦了婚禮氯迂,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘言缤。我一直安慰自己嚼蚀,他們只是感情好,可當我...
    茶點故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布管挟。 她就那樣靜靜地躺著轿曙,像睡著了一般。 火紅的嫁衣襯著肌膚如雪僻孝。 梳的紋絲不亂的頭發(fā)上导帝,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天,我揣著相機與錄音穿铆,去河邊找鬼您单。 笑死,一個胖子當著我的面吹牛荞雏,可吹牛的內(nèi)容都是我干的虐秦。 我是一名探鬼主播,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼凤优,長吁一口氣:“原來是場噩夢啊……” “哼羡疗!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起别洪,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤叨恨,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后挖垛,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體痒钝,經(jīng)...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡秉颗,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了送矩。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蚕甥。...
    茶點故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖栋荸,靈堂內(nèi)的尸體忽然破棺而出菇怀,到底是詐尸還是另有隱情,我是刑警寧澤晌块,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布爱沟,位于F島的核電站,受9級特大地震影響匆背,放射性物質(zhì)發(fā)生泄漏呼伸。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一钝尸、第九天 我趴在偏房一處隱蔽的房頂上張望括享。 院中可真熱鬧,春花似錦珍促、人聲如沸铃辖。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽娇斩。三九已至,卻和暖如春沐悦,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背五督。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工藏否, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人充包。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓副签,卻偏偏與公主長得像,于是被迫代替她去往敵國和親基矮。 傳聞我的和親對象是個殘疾皇子淆储,可洞房花燭夜當晚...
    茶點故事閱讀 45,060評論 2 355

推薦閱讀更多精彩內(nèi)容