Tried implementing a toolbar for my layout but a gap keeps appearing underneath it. What is the correct way to eliminated that gap? I believe android:fitsSystemWindows="false"
or android:fitsSystemWindows="true"
but I'm not entirely sure which code needs to be used as I've heard several different solutions. Also I'm not sure where it needs to go.
Fragment XML code
<?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:layout_height="match_parent">
<include layout="@layout/my_toolbar"/>
<com.packagename.SlidingTabLayout_DarkTabStrip
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<android.support.v4.view.ViewPager
android:id="@+id/pager"
android:layout_height="0dp"
android:layout_width="match_parent"
android:layout_weight="1"/>
</LinearLayout>
Toolbar XML code
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/toolbar_2lines"
android:layout_width="match_parent"
android:layout_height="?actionBarSize">
<LinearLayout
android:id="@+id/dualline_text_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#00FFFFFF"
android:gravity="center_vertical"
android:orientation="vertical">
<TextView
android:id="@+id/toolbar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/TextAppearance.AppCompat.Widget.ActionBar.Title"/>
<TextView
android:id="@+id/toolbar_subtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/TextAppearance.AppCompat.Widget.ActionBar.Subtitle"/>
</LinearLayout>
</android.support.v7.widget.Toolbar>
SlidingTabLayout_DarkTabStrip.java
public class SlidingTabLayout_DarkTabStrip extends HorizontalScrollView {
public interface TabColorizer {
int getIndicatorColor(int position);
}
private static final int TITLE_OFFSET_DIPS = 24;
private static final int TAB_VIEW_PADDING_DIPS = 16;
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<>();
private ViewPager.OnPageChangeListener mViewPagerPageChangeListener;
private final SlidingTabStrip_Dark mTabStrip;
public SlidingTabLayout_DarkTabStrip(Context context) {
this(context, null);
}
public SlidingTabLayout_DarkTabStrip(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public SlidingTabLayout_DarkTabStrip(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_Dark(context);
addView(mTabStrip, LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
}
public void setCustomTabColorizer(SlidingTabLayout_DarkTabStrip.TabColorizer tabColorizer) {
mTabStrip.setCustomTabColorizer(tabColorizer);
}
public void setDistributeEvenly(boolean distributeEvenly) {
mDistributeEvenly = distributeEvenly;
}
public void setSelectedIndicatorColors(int... colors) {
mTabStrip.setSelectedIndicatorColors(colors);
}
public void addOnPageChangeListener(ViewPager.OnPageChangeListener listener) {
mViewPagerPageChangeListener = listener;
}
public void setCustomTabView(int layoutResId, int textViewId) {
mTabViewLayoutId = layoutResId;
mTabViewTextViewId = textViewId;
}
public void setViewPager(ViewPager viewPager) {
mTabStrip.removeAllViews();
mViewPager = viewPager;
if (viewPager != null) {
viewPager.addOnPageChangeListener(new SlidingTabLayout_DarkTabStrip.InternalViewPagerListener());
populateTabStrip();
}
}
protected TextView createDefaultTabView(Context context) {
TextView textView = new TextView(context);
textView.setGravity(Gravity.CENTER);
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, TAB_VIEW_TEXT_SIZE_SP);
textView.setTypeface(Typeface.DEFAULT_BOLD);
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);
textView.setAllCaps(true);
int padding = (int) (TAB_VIEW_PADDING_DIPS * getResources().getDisplayMetrics().density);
textView.setPadding(padding, padding, padding, padding);
return textView;
}
private void populateTabStrip() {
final PagerAdapter adapter = mViewPager.getAdapter();
final View.OnClickListener tabClickListener = new SlidingTabLayout_DarkTabStrip.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;
}
assert tabTitleView != null;
tabTitleView.setText(adapter.getPageTitle(i));
tabView.setOnClickListener(tabClickListener);
String desc = mContentDescriptions.get(i, null);
if (desc != null) {
tabView.setContentDescription(desc);
}
mTabStrip.addView(tabView);
if (i == mViewPager.getCurrentItem()) {
tabView.setSelected(true);
}
tabTitleView.setTextColor(Color.parseColor("#000099"));
tabTitleView.setTextSize(14);
}
}
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) {
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 (mViewPagerPageChangeListener != null) {
mViewPagerPageChangeListener.onPageSelected(position);
}
}
}
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_Dark.java
public class SlidingTabStrip_Dark 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 int mSelectedPosition;
private float mSelectionOffset;
private SlidingTabLayout_DarkTabStrip.TabColorizer mCustomTabColorizer;
private final SlidingTabStrip_Dark.SimpleTabColorizer mDefaultTabColorizer;
SlidingTabStrip_Dark(Context context) {
this(context, null);
}
SlidingTabStrip_Dark(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;
int mDefaultBottomBorderColor = setColorAlpha(themeForegroundColor,
DEFAULT_BOTTOM_BORDER_COLOR_ALPHA);
mDefaultTabColorizer = new SlidingTabStrip_Dark.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_DarkTabStrip.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_DarkTabStrip.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_DarkTabStrip.TabColorizer {
private int[] mIndicatorColors;
@Override
public final int getIndicatorColor(int position) {
return mIndicatorColors[position % mIndicatorColors.length];
}
void setIndicatorColors(int... colors) {
mIndicatorColors = colors;
}
}
}
Activity java code
public class TBarActivity extends AppCompatActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_withtbar);
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
final String actionBarColor = "#66CCCC";
Toolbar customToolbar = (Toolbar)findViewById(R.id.toolbar_2lines);
setSupportActionBar(customToolbar);
customToolbar.setBackgroundColor(Color.parseColor(actionBarColor));
//add back arrow to toolbar
if (getSupportActionBar() != null){
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
}
//Declaring 'title' text view & applying marquee effect to 'title' text view
TextView mTitle = (TextView) this.findViewById(R.id.toolbar_title);
mTitle.setText(getString(R.string.toolbar));
mTitle.setTextColor(Color.parseColor("#000099"));
mTitle.setEllipsize(TextUtils.TruncateAt.MARQUEE);
mTitle.setMarqueeRepeatLimit(-1);
mTitle.setSingleLine(true);
mTitle.setSelected(true);
//Declaring 'subtitle' text view & applying marquee effect to 'subtitle' text view
TextView mSubtitle = (TextView) this.findViewById(R.id.toolbar_subtitle);
mSubtitle.setText(getString(R.string.toolbars_are_awesome));
mSubtitle.setTextColor(Color.parseColor("#000099"));
mSubtitle.setEllipsize(TextUtils.TruncateAt.MARQUEE);
mSubtitle.setMarqueeRepeatLimit(-1);
mSubtitle.setSingleLine(true);
mSubtitle.setSelected(true);
if (savedInstanceState == null) {
FragmentwithTBar newFragment = new FragmentwithTBar();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.detail_container, newFragment);
transaction.commit();
}
}
}
Fragment java code
public class FragmentwithTBar extends android.support.v4.app.Fragment {
public FragmentwithTBar() {
// Required empty constructor
}
// Declaring views and variables
ViewPager pager;
TBarViewPagerAdapter adapter;
SlidingTabLayout_DarkTabStrip tabs;
int Numboftabs = 4;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_with_tbar, container, false);
super.onCreate(savedInstanceState);
return v;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
View v = getView();
// Creating the ViewPagerAdapter and passing the Fragment Manager, titles for the Tabs and Number of Tabs.
adapter = new TBarViewPagerAdapter(getChildFragmentManager(), Numboftabs, getActivity());
// Assigning ViewPager View and setting the adapter
assert v != null;
pager = (ViewPager) v.findViewById(R.id.pager);
pager.setAdapter(adapter);
// Assigning the Sliding Tab Layout view
tabs = (SlidingTabLayout_DarkTabStrip) v.findViewById(R.id.tabs);
tabs.setDistributeEvenly(false);
// Setting Custom color for the scroll bar indicator of the Tab View
tabs.setCustomTabColorizer(new SlidingTabLayout_DarkTabStrip.TabColorizer() {
@Override
public int getIndicatorColor(int position) {
return Color.parseColor("#000099");
}
});
// Setting the ViewPager for the SlidingTabsLayout
tabs.setViewPager(pager);
super.onActivityCreated(savedInstanceState);
}
}
com.packagename.TabLayout
? – Bailiff<android.support.design.widget.TabLayout>
tag I do not see any issues. – BailiffSlidingTabStrip_Dark
– BailiffTBarViewPagerAdapter
which I do not have the source for. Perhaps you have a github link with your entire project? – Bailiff