web-dev-qa-db-ja.com

ビューページャーを使用したTabLayoutがスムーズにスクロールしない

編集

私はこれらのチュートリアルに従ってこの問題を修正しました。

http://www.truiton.com/2015/06/Android-tabs-example-fragments-viewpager/https://guides.codepath.com/Android/google-play -style-tabs-using-tablayouthttp://www.voidynullness.net/blog/2015/08/16/Android-tablayout-design-support-library-tutorial/

しかし、いくつかの解決策を試した後でも、その厄介な問題は解決しません。ここに私が直面している問題のデモがあります。この問題にこだわってから数週間が経ちました。

リンク デモ用。

テストに使用しているデバイスはNexus 4とNexus 5です。

TabLayoutViewPagerがスムーズにスクロールしません。次のタップでシフトするには2回スワイプする必要があります。 Webを見回しましたが、解決策が見つかりませんでした。最新のサポートデザインライブラリを使用しています。ここにgradleファイルがあります

apply plugin: 'com.Android.application'

Android {
compileSdkVersion 23
buildToolsVersion "23.0.3"

defaultConfig {
    applicationId "com.softoven.ultron"
    minSdkVersion 15
    targetSdkVersion 23
    versionCode 1
    versionName "1.0"
}
buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-Android.txt'), 'proguard-rules.pro'
    }
}
}

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.Android.support:appcompat-v7:23.3.0'
compile 'com.Android.support:design:23.3.0'
compile 'org.jsoup:jsoup:1.6.1'
compile 'com.mikhaellopez:circularimageview:3.0.0'
compile 'com.Android.support:recyclerview-v7:23.3.0'
compile 'com.mcxiaoke.volley:library:1.0.19'
compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.5'
compile 'com.google.code.gson:gson:2.5'
}

アクティビティコードは次のとおりです。

private DrawerLayout drawerLayout;
private ViewPager viewPager;
private TabLayout tabLayout;
private NavigationView navigationView;
private CategoriesDTO categoriesDTO;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    initToolbar();
    initUi();
    loadCategories();
}

private void initToolbar() {
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_action_menu);
}

private void initUi() {
    drawerLayout = (DrawerLayout) findViewById(R.id.drawer);
    navigationView = (NavigationView) findViewById(R.id.navigation);
    viewPager = (ViewPager) findViewById(R.id.viewPager);
    tabLayout = (TabLayout) findViewById(R.id.tab);

}

private void loadCategories() {
    StringRequest request = new StringRequest(Constants.URL_GET_CATEGORIES, new Response.Listener<String>() {
        @Override
        public void onResponse(String response) {
            categoriesDTO = Constants.gson.fromJson(response, CategoriesDTO.class);
            ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
            viewPager.setOffscreenPageLimit(1);
            viewPager.setAdapter(adapter);
            setTabLayout();
        }
    }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {

        }
    });

    ApplicationController.getmInstance().addToRequestQueue(request);
}

private void setTabLayout() {

    tabLayout.setupWithViewPager(viewPager);

}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater menuInflater = getMenuInflater();
    menuInflater.inflate(R.menu.home_side_menu, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    int id = item.getItemId();
    switch (id) {
        case Android.R.id.home:
            drawerLayout.openDrawer(GravityCompat.START);
            return true;
    }
    return super.onOptionsItemSelected(item);
}

private class ViewPagerAdapter extends FragmentPagerAdapter {

    public ViewPagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int position) {
        return new ContentFragment();
    }

    @Override
    public int getCount() {
        return 10;
    }

    @Override
    public CharSequence getPageTitle(int position) {
        String title = categoriesDTO.getCategories().get(position).getTitle();
        return (CharSequence) title;
    }
}

そしてxmlファイル

<?xml version="1.0" encoding="utf-8"?>
<Android.support.design.widget.CoordinatorLayout
    Android:layout_width="match_parent"
    Android:layout_height="match_parent">


    <Android.support.design.widget.AppBarLayout
        Android:id="@+id/app_bar"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content">

        <include
            Android:id="@+id/toolbar"
            layout="@layout/toolbar"
            app:layout_scrollFlags="scroll|enterAlways"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />

        <Android.support.design.widget.TabLayout
            Android:id="@+id/tab"
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content"
            app:tabTextColor="#fff"
            app:tabGravity="fill"
            app:tabMode="scrollable"
            >

        </Android.support.design.widget.TabLayout>
    </Android.support.design.widget.AppBarLayout>

    <Android.support.v4.view.ViewPager
        Android:id="@+id/viewPager"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

    </Android.support.v4.view.ViewPager>
</Android.support.design.widget.CoordinatorLayout>

<Android.support.design.widget.NavigationView
    Android:id="@+id/navigation"
    Android:layout_width="wrap_content"
    Android:layout_height="match_parent"
    Android:layout_gravity="start"
    app:menu="@menu/home_drawer_menu">

</Android.support.design.widget.NavigationView>

インジケーターが部分的に分割されているのを確認できるスクリーンショットを次に示します。

enter image description here

解決策はありますか?

35
Zeeshan Shabbir

私はあなたのコードを調べました。問題は、ContentFragment.Java内で膨張させるレイアウトを提供していないことです。

私はあなたの方法を

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        //return super.onCreateView(inflater, container, savedInstanceState);
        return  inflater.inflate(R.layout.feed_item, container, false);

    }

これらの変更を行った後、タブはスムーズにスクロールしていました。この動作の背後にある理由はわかりませんが、このことが原因で動作しました

33
Ankit Aggarwal

アクティビティの次の行を変更します。

ViewPagerAdapter adapter = new ViewPagerAdapter(getChildFragmentManager());
11
Hamed Nabizadeh

overrideメソッドsetUserVisibleHintを使用する必要があると思います。

これをFragmentに追加する必要があります。

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if (isVisibleToUser) {
        // load data here
    }else{
       // fragment is no longer visible
    }
}

offScreenPageLimitをTABの数に合わせて作成します。

setUserVisibleHinthere の詳細をご覧ください。

3
Jay Rathod RJ

フラグメント内にTabLayoutを作成する場合は、getChildFragmentManager()の代わりにgetSupportFragmentManager()をパラメーターとして使用します。

ViewPagerAdapter adapter = new ViewPagerAdapter(getChildFragmentManager());
2
Arihant Jain

ViewPager.setOffscreenPageLimit(1)を設定してください。 viewPager.setOffscreenPageLimit(5);

2
Aditay Kaushal

アプリですべてのStrictModeポリシーを有効にして、メインスレッドで不注意に実行して遅延を引き起こしている可能性のある長い操作を検出し、さらに必要な修正措置を講じることができます。

StrictModeは、偶発的に行っている可能性のあることを検出し、修正できるように注意を喚起する開発者ツールです。 StrictModeは、UI操作が受信され、アニメーションが発生するアプリケーションのメインスレッドで、偶発的なディスクまたはネットワークアクセスをキャッチするために最もよく使用されます。

詳細については https://developer.Android.com/reference/Android/os/StrictMode.html をご覧ください。

    // Enable all thread strict mode policies
    StrictMode.ThreadPolicy.Builder threadPolicyBuilder = new StrictMode.ThreadPolicy.Builder();

    // Detect everything that's potentially suspect
    threadPolicyBuilder.detectAll();

    // Crash the whole process on violation
    threadPolicyBuilder.penaltyDeath();

    // Log detected violations to the system log
    threadPolicyBuilder.penaltyLog();

    // Crash the whole process on any network usage.
    threadPolicyBuilder.penaltyDeathOnNetwork();


    StrictMode.ThreadPolicy threadPolicy = threadPolicyBuilder.build();
    StrictMode.setThreadPolicy(threadPolicy);

    // Enable all VM strict mode policies
    StrictMode.VmPolicy.Builder vmPolicyBuilder = new StrictMode.VmPolicy.Builder();

    // Detect everything that's potentially suspect
    vmPolicyBuilder.detectAll();

    // Log detected violations to the system log
    vmPolicyBuilder.penaltyLog();

    StrictMode.VmPolicy vmPolicy = vmPolicyBuilder.build();
    StrictMode.setVmPolicy(vmPolicy);
1
Chebyr

これは、Androidの座標レイアウトとappBarレイアウトでは新しいことではありません。あなたが何をしても、あなたはそれをよりスムーズにすることができないと確信しています。しかしながら

https://github.com/henrytao-me/smooth-app-bar-layout

これにより、要件を満たすことができます。ただし、最初にサンプルアプリをダウンロードします

https://play.google.com/store/apps/details?id=me.henrytao.smoothappbarlayout

ニーズに合っているかどうかを確認します(念のため)。

1

Androidマニフェストファイル<Application>タグ

 Android:largeHeap="true" 
0
Krupa

まず第一に、すべてをスムーズにするためにメインスレッドで重い操作を行わないように、非同期タスクを使用し(非同期タスクのビューに触れないでください)、とにかくすべてがスムーズになります:)

これを行うための私の方法を試してください:

SlidingTabLayout:

public class SlidingTabLayout extends HorizontalScrollView {
    /**
     * Allows complete control over the colors drawn in the tab layout. Set with
     * {@link #setCustomTabColorizer(TabColorizer)}.
     */
    View oldSelection = null;

    public interface TabColorizer {

        /**
         * @return return the color of the indicator used when {@code position} is selected.
         */
        int getIndicatorColor(int position);

    }

    private static final int TITLE_OFFSET_DIPS = 24;
    private static final int TAB_VIEW_PADDING_DIPS = 8;
    private static final int TAB_VIEW_TEXT_SIZE_SP = 12;

    private int mTitleOffset;

    private int mTabViewLayoutId;
    private int mTabViewTextViewId;
    private boolean mDistributeEvenly;

    private ViewPager mViewPager;
    private SparseArray<String> mContentDescriptions = new SparseArray<String>();
    private ViewPager.OnPageChangeListener mViewPagerPageChangeListener;

    private final SlidingTabStrip mTabStrip;

    public SlidingTabLayout(Context context) {
        this(context, null);
    }

    public SlidingTabLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public SlidingTabLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);

        // Disable the Scroll Bar
        setHorizontalScrollBarEnabled(false);
        // Make sure that the Tab Strips fills this View
        setFillViewport(true);

        mTitleOffset = (int) (TITLE_OFFSET_DIPS * getResources().getDisplayMetrics().density);

        mTabStrip = new SlidingTabStrip(context);
        addView(mTabStrip, LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
    }


    public void hideTab(int tabIndex){
        for (int i = 0; i < mTabStrip.getChildCount(); i++) {
            if(i == tabIndex){
                ((TextView)mTabStrip.getChildAt(i)).setVisibility(GONE);
            }
        }


    }

    /**
     * Set the custom {@link TabColorizer} to be used.
     *
     * If you only require simple custmisation then you can use
     * {@link #setSelectedIndicatorColors(int...)} to achieve
     * similar effects.
     */
    public void setCustomTabColorizer(TabColorizer tabColorizer) {
        mTabStrip.setCustomTabColorizer(tabColorizer);
    }

    public void setDistributeEvenly(boolean distributeEvenly) {
        mDistributeEvenly = distributeEvenly;
    }

    /**
     * Sets the colors to be used for indicating the selected tab. These colors are treated as a
     * circular array. Providing one color will mean that all tabs are indicated with the same color.
     */
    public void setSelectedIndicatorColors(int... colors) {
        mTabStrip.setSelectedIndicatorColors(colors);
    }

    /**
     * Set the {@link ViewPager.OnPageChangeListener}. When using {@link SlidingTabLayout} you are
     * required to set any {@link ViewPager.OnPageChangeListener} through this method. This is so
     * that the layout can update it's scroll position correctly.
     *
     * @see ViewPager#setOnPageChangeListener(ViewPager.OnPageChangeListener)
     */
    public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) {
        mViewPagerPageChangeListener = listener;
    }

    /**
     * Set the custom layout to be inflated for the tab views.
     *
     * @param layoutResId Layout id to be inflated
     * @param textViewId id of the {@link TextView} in the inflated view
     */
    public void setCustomTabView(int layoutResId, int textViewId) {
        mTabViewLayoutId = layoutResId;
        mTabViewTextViewId = textViewId;
    }

    /**
     * Sets the associated view pager. Note that the assumption here is that the pager content
     * (number of tabs and tab titles) does not change after this call has been made.
     */
    public void setViewPager(ViewPager viewPager) {
        mTabStrip.removeAllViews();

        mViewPager = viewPager;
        if (viewPager != null) {
            viewPager.setOnPageChangeListener(new InternalViewPagerListener());
            populateTabStrip();
        }
    }

    /**
     * Create a default view to be used for tabs. This is called if a custom tab view is not set via
     * {@link #setCustomTabView(int, int)}.
     */
    protected TextView createDefaultTabView(Context context) {
        TextView textView = new TextView(context);
        textView.setGravity(Gravity.CENTER);
        textView.setTextSize(16);
        textView.setTypeface(Constants.TYPE_FACE_FONT_MEDIUM);
        textView.setLayoutParams(new LinearLayout.LayoutParams(
                ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));

        TypedValue outValue = new TypedValue();
        getContext().getTheme().resolveAttribute(Android.R.attr.selectableItemBackground,
                outValue, true);
        textView.setBackgroundResource(outValue.resourceId);
        if(Constants.PRODUCT_DETAILS_TAB_BAR_STYLE == 2) {
            textView.setBackgroundColor(getResources().getColor(R.color.tab_bar_color));
            mTabStrip.setBackgroundColor(getResources().getColor(R.color.tab_bar_color));
        }

        textView.setAllCaps(true);

        int padding = (int) (TAB_VIEW_PADDING_DIPS * getResources().getDisplayMetrics().density);
        textView.setPadding(padding, padding, padding, padding);

        return textView;
    }

    private void populateTabStrip() {
        removeOldSelection();
        oldSelection = null;
        final PagerAdapter adapter = mViewPager.getAdapter();
        final View.OnClickListener tabClickListener = new TabClickListener();

        for (int i = 0; i < adapter.getCount(); i++) {
            View tabView = null;
            TextView tabTitleView = null;

            if (mTabViewLayoutId != 0) {
                // If there is a custom tab view layout id set, try and inflate it
                tabView = LayoutInflater.from(getContext()).inflate(mTabViewLayoutId, mTabStrip,
                        false);
                tabTitleView = (TextView) tabView.findViewById(mTabViewTextViewId);
            }

            if (tabView == null) {
                tabView = createDefaultTabView(getContext());
            }

            if (tabTitleView == null && TextView.class.isInstance(tabView)) {
                tabTitleView = (TextView) tabView;
            }

            if (mDistributeEvenly) {
                LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) tabView.getLayoutParams();
                lp.width = 0;
                lp.weight = 1;
            }

            tabTitleView.setText(adapter.getPageTitle(i));

            tabView.setOnClickListener(tabClickListener);
            String desc = mContentDescriptions.get(i, null);
            if (desc != null) {
                tabView.setContentDescription(desc);
            }

            mTabStrip.addView(tabView);
            if(Constants.PRODUCT_DETAILS_TAB_BAR_STYLE == 1)
                tabTitleView.setTextColor(getResources().getColorStateList(R.color.primary_ultralight));
            else
                tabTitleView.setTextColor(getResources().getColor(R.color.primary_text));
            if (i == mViewPager.getCurrentItem()) {
                tabView.setSelected(true);
                tabTitleView.setTextColor(getResources().getColorStateList(R.color.primary_ultralight));
            }

        }

    }

    public void setContentDescription(int i, String desc) {
        mContentDescriptions.put(i, desc);
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();

        if (mViewPager != null) {
            scrollToTab(mViewPager.getCurrentItem(), 0);
        }
    }

    private void scrollToTab(int tabIndex, int positionOffset) {
        final int tabStripChildCount = mTabStrip.getChildCount();
        if (tabStripChildCount == 0 || tabIndex < 0 || tabIndex >= tabStripChildCount) {
            return;
        }

        View selectedChild = mTabStrip.getChildAt(tabIndex);
        if (selectedChild != null) {

            if(positionOffset == 0 && selectedChild != oldSelection) { // added part
                selectedChild.setSelected(true);
                removeOldSelection();
                oldSelection = selectedChild;
            }

            int targetScrollX = selectedChild.getLeft() + positionOffset;

            if (tabIndex > 0 || positionOffset > 0) {
                // If we're not at the first child and are mid-scroll, make sure we obey the offset
                targetScrollX -= mTitleOffset;
            }

            scrollTo(targetScrollX, 0);
        }
    }

    private class InternalViewPagerListener implements ViewPager.OnPageChangeListener {
        private int mScrollState;

        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            int tabStripChildCount = mTabStrip.getChildCount();
            if ((tabStripChildCount == 0) || (position < 0) || (position >= tabStripChildCount)) {
                return;
            }

            mTabStrip.onViewPagerPageChanged(position, positionOffset);

            View selectedTitle = mTabStrip.getChildAt(position);
            int extraOffset = (selectedTitle != null)
                    ? (int) (positionOffset * selectedTitle.getWidth())
                    : 0;
            scrollToTab(position, extraOffset);

            if (mViewPagerPageChangeListener != null) {
                mViewPagerPageChangeListener.onPageScrolled(position, positionOffset,
                        positionOffsetPixels);
            }
        }

        @Override
        public void onPageScrollStateChanged(int state) {
            mScrollState = state;

            if (mViewPagerPageChangeListener != null) {
                mViewPagerPageChangeListener.onPageScrollStateChanged(state);
            }
        }

        @Override
        public void onPageSelected(int position) {
            if (mScrollState == ViewPager.SCROLL_STATE_IDLE) {
                mTabStrip.onViewPagerPageChanged(position, 0f);
                scrollToTab(position, 0);
            }
            for (int i = 0; i < mTabStrip.getChildCount(); i++) {
                mTabStrip.getChildAt(i).setSelected(position == i);

                if(Constants.PRODUCT_DETAILS_TAB_BAR_STYLE == 2){
                    if(position == i)
                        ((TextView)mTabStrip.getChildAt(i)).setTextColor(getResources().getColorStateList(R.color.primary_ultralight));
                    else
                        ((TextView)mTabStrip.getChildAt(i)).setTextColor(getResources().getColor(R.color.primary_text));
                }




            }
            if (mViewPagerPageChangeListener != null) {
                mViewPagerPageChangeListener.onPageSelected(position);
            }
        }

    }
    private void removeOldSelection() {
        if(oldSelection != null) {
            oldSelection.setSelected(false);
        }
    }
    private class TabClickListener implements View.OnClickListener {
        @Override
        public void onClick(View v) {
            for (int i = 0; i < mTabStrip.getChildCount(); i++) {
                if (v == mTabStrip.getChildAt(i)) {
                    mViewPager.setCurrentItem(i);
                    return;
                }
            }
        }
    }

}

SlidingTabStrip:

class SlidingTabStrip extends LinearLayout {

    private static final int DEFAULT_BOTTOM_BORDER_THICKNESS_DIPS = 0;
    private static final byte DEFAULT_BOTTOM_BORDER_COLOR_ALPHA = 0x26;
    private static final int SELECTED_INDICATOR_THICKNESS_DIPS = 3;
    private static final int DEFAULT_SELECTED_INDICATOR_COLOR = 0xFF33B5E5;

    private final int mBottomBorderThickness;
    private final Paint mBottomBorderPaint;

    private final int mSelectedIndicatorThickness;
    private final Paint mSelectedIndicatorPaint;

    private final int mDefaultBottomBorderColor;

    private int mSelectedPosition;
    private float mSelectionOffset;

    private SlidingTabLayout.TabColorizer mCustomTabColorizer;
    private final SimpleTabColorizer mDefaultTabColorizer;

    SlidingTabStrip(Context context) {
        this(context, null);
    }

    SlidingTabStrip(Context context, AttributeSet attrs) {
        super(context, attrs);
        setWillNotDraw(false);

        final float density = getResources().getDisplayMetrics().density;

        TypedValue outValue = new TypedValue();
        context.getTheme().resolveAttribute(Android.R.attr.colorForeground, outValue, true);
        final int themeForegroundColor =  outValue.data;

        mDefaultBottomBorderColor = setColorAlpha(themeForegroundColor,
                DEFAULT_BOTTOM_BORDER_COLOR_ALPHA);

        mDefaultTabColorizer = new SimpleTabColorizer();
        mDefaultTabColorizer.setIndicatorColors(DEFAULT_SELECTED_INDICATOR_COLOR);

        mBottomBorderThickness = (int) (DEFAULT_BOTTOM_BORDER_THICKNESS_DIPS * density);
        mBottomBorderPaint = new Paint();
        mBottomBorderPaint.setColor(mDefaultBottomBorderColor);

        mSelectedIndicatorThickness = (int) (SELECTED_INDICATOR_THICKNESS_DIPS * density);
        mSelectedIndicatorPaint = new Paint();
    }

    void setCustomTabColorizer(SlidingTabLayout.TabColorizer customTabColorizer) {
        mCustomTabColorizer = customTabColorizer;
        invalidate();
    }

    void setSelectedIndicatorColors(int... colors) {
        // Make sure that the custom colorizer is removed
        mCustomTabColorizer = null;
        mDefaultTabColorizer.setIndicatorColors(colors);
        invalidate();
    }

    void onViewPagerPageChanged(int position, float positionOffset) {
        mSelectedPosition = position;
        mSelectionOffset = positionOffset;
        invalidate();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        final int height = getHeight();
        final int childCount = getChildCount();
        final SlidingTabLayout.TabColorizer tabColorizer = mCustomTabColorizer != null
                ? mCustomTabColorizer
                : mDefaultTabColorizer;

        // Thick colored underline below the current selection
        if (childCount > 0) {
            View selectedTitle = getChildAt(mSelectedPosition);
            int left = selectedTitle.getLeft();
            int right = selectedTitle.getRight();
            int color = tabColorizer.getIndicatorColor(mSelectedPosition);

            if (mSelectionOffset > 0f && mSelectedPosition < (getChildCount() - 1)) {
                int nextColor = tabColorizer.getIndicatorColor(mSelectedPosition + 1);
                if (color != nextColor) {
                    color = blendColors(nextColor, color, mSelectionOffset);
                }

                // Draw the selection partway between the tabs
                View nextTitle = getChildAt(mSelectedPosition + 1);
                left = (int) (mSelectionOffset * nextTitle.getLeft() +
                        (1.0f - mSelectionOffset) * left);
                right = (int) (mSelectionOffset * nextTitle.getRight() +
                        (1.0f - mSelectionOffset) * right);
            }

            mSelectedIndicatorPaint.setColor(color);

            canvas.drawRect(left, height - mSelectedIndicatorThickness, right,
                    height, mSelectedIndicatorPaint);
        }

        // Thin underline along the entire bottom Edge
        canvas.drawRect(0, height - mBottomBorderThickness, getWidth(), height, mBottomBorderPaint);
    }

    /**
     * Set the alpha value of the {@code color} to be the given {@code alpha} value.
     */
    private static int setColorAlpha(int color, byte alpha) {
        return Color.argb(alpha, Color.red(color), Color.green(color), Color.blue(color));
    }

    /**
     * Blend {@code color1} and {@code color2} using the given ratio.
     *
     * @param ratio of which to blend. 1.0 will return {@code color1}, 0.5 will give an even blend,
     *              0.0 will return {@code color2}.
     */
    private static int blendColors(int color1, int color2, float ratio) {
        final float inverseRation = 1f - ratio;
        float r = (Color.red(color1) * ratio) + (Color.red(color2) * inverseRation);
        float g = (Color.green(color1) * ratio) + (Color.green(color2) * inverseRation);
        float b = (Color.blue(color1) * ratio) + (Color.blue(color2) * inverseRation);
        return Color.rgb((int) r, (int) g, (int) b);
    }

    private static class SimpleTabColorizer implements SlidingTabLayout.TabColorizer {
        private int[] mIndicatorColors;

        @Override
        public final int getIndicatorColor(int position) {
            return mIndicatorColors[position % mIndicatorColors.length];
        }

        void setIndicatorColors(int... colors) {
            mIndicatorColors = colors;
        }
    }
}

そして、使用方法:

<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:tools="http://schemas.Android.com/tools"
    Android:layout_width="match_parent"
    Android:background="@color/layouts_background"
    Android:layout_height="match_parent">

        <LinearLayout
            Android:layout_width="match_parent"
            Android:layout_height="match_parent"
            Android:orientation="vertical">
            <RelativeLayout
                Android:id="@+id/page_root_container"
                Android:layout_width="match_parent"
                Android:layout_height="match_parent"
                Android:orientation="vertical">
                <include
                    Android:id="@+id/app_bar"
                    layout="@layout/app_bar"/>
                <LinearLayout
                    Android:layout_width="match_parent"
                    Android:layout_height="match_parent"
                    Android:layout_below="@+id/app_bar"
                    Android:orientation="vertical">
                    <com.app.myapp.tab.SlidingTabLayout
                        Android:id="@+id/detailsTabs"
                        Android:layout_width="match_parent"
                        Android:layout_height="wrap_content">

                    </com.app.myapp.tab.SlidingTabLayout>
                    <Android.support.v4.view.ViewPager
                        Android:id="@+id/detailsPager"
                        Android:layout_width="match_parent"
                        Android:layout_height="0dp"
                        Android:layout_weight="1">
                    </Android.support.v4.view.ViewPager>
                </LinearLayout>
            </RelativeLayout>
        </LinearLayout>
</RelativeLayout>

アプリバーとしてのツールバー:

<?xml version="1.0" encoding="utf-8"?>
<Android.support.v7.widget.Toolbar xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:app="http://schemas.Android.com/apk/res-auto"
    Android:layout_width="match_parent"
    Android:layout_height="?android:attr/actionBarSize"
    Android:background="@color/primary"
    app:theme="@style/CustomToolbarTheme">


</Android.support.v7.widget.Toolbar>

活動中:

class DetailsTabsAdaptor extends FragmentPagerAdapter {
        String [] tabsTitlesPrepare = {getString(R.string.details),getString(R.string.features), getString(R.string.spects), getString(R.string.downloads)};
        List<String> tabsTitles = new ArrayList<>();
        int tabsCount = 0;
        boolean featuresExist = false;
        boolean specificationsExist = false;
        boolean downloadsExist = false;

        public DetailsTabsAdaptor(FragmentManager fm) {
            super(fm);
            tabsTitles.add(tabsTitlesPrepare[0]);
            tabsCount++;
            if ((mProductDetails.ProductStructure.Features != null && mProductDetails.ProductStructure.Features.size()>0)) {
                tabsTitles.add(tabsTitlesPrepare[1]);
                featuresExist = true;
                tabsCount++;
            }
            if ((mProductDetails.ProductStructure.SpecificationBlocks != null && mProductDetails.ProductStructure.SpecificationBlocks.size()>0)) {
                tabsTitles.add(tabsTitlesPrepare[2]);
                specificationsExist = true;
                tabsCount++;
            }
            if ((mProductDetails.ProductStructure.SupportFiles != null && mProductDetails.ProductStructure.SupportFiles.size()>0)) {
                tabsTitles.add(tabsTitlesPrepare[3]);
                downloadsExist = true;
                tabsCount++;
            }

        }

        @Override
        public CharSequence getPageTitle(int position) {
            return tabsTitles.get(position);
        }

        @Override
        public Fragment getItem(int position) {
            if(position == 0){
                ProductDetailsFragment fragment = new ProductDetailsFragment();
                return fragment;
            }
            if(position == 1 && featuresExist){
                ProductFeaturesFragment fragment = new ProductFeaturesFragment();
                return fragment;
            }
            if((position == 2 && specificationsExist) || (position == 1 && (!featuresExist) && specificationsExist)){
                ProductSpectsFragment fragment = new ProductSpectsFragment();
                return fragment;
            }
            if((position == 3 && downloadsExist) || (position == 1 && (!featuresExist) && (!specificationsExist) && downloadsExist ) ||
                    (position == 2 && (!specificationsExist) && downloadsExist )){
                ProductDownloadsFragment fragment = new ProductDownloadsFragment();
                return fragment;
            }

            return null;
        }

        @Override
        public int getCount() {
            return tabsCount;
        }
    }

設定タブ

public void setupTabs() {
        mDetailsPager.setAdapter(new DetailsTabsAdaptor(getSupportFragmentManager()));
        mDetailsTabs.setViewPager(mDetailsPager);
        mDetailsTabs.setBackgroundResource(R.color.primary);
        mDetailsTabs.setCustomTabView(R.layout.custom_details_view_tab_layout, R.id.tabText);
        mDetailsTabs.setCustomTabColorizer(new SlidingTabLayout.TabColorizer() {
            @Override
            public int getIndicatorColor(int position) {
                return getResources().getColor(R.color.primary_light);
            }
        });


        mDetailsTabs.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            }

            @Override
            public void onPageSelected(int position) {

                for (int i = 0; i < mDetailsTabs.getChildCount(); i++)
                    mDetailsTabs.getChildAt(i).setSelected(i == position);
                if (position == DESCRIPTION_PAGE_ID)
                    mFavoritesButton.setVisibility(View.VISIBLE);
                else
                    mFavoritesButton.setVisibility(View.GONE);

            }

            @Override
            public void onPageScrollStateChanged(int state) {
            }
        });

    }

custom_details_view_tab_layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:orientation="vertical"
    Android:layout_width="match_parent"
    Android:background="@color/primary"
    Android:layout_height="match_parent">
    <com.avad.avaddroid.customModels.TextViewMedium
        Android:id="@+id/tabText"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:textColor="@color/primary_light"
        Android:layout_gravity="center"/>

</LinearLayout>

最後の注意:すべての変数のinitをここに投稿しないでください。

0
Stepan Maksymov