I have a TabLayout in my app and it holds custom views:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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="match_parent">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:orientation="horizontal">
<com.myproject.app.utils.commons.IconImageView
android:id="#android:id/icon"
android:layout_width="wrap_content"
android:layout_height="20dp"
android:layout_marginRight="14dp"
android:layout_marginEnd="14dp"
app:iconStateListColor="#color/color_order_tab"/>
<TextView
android:id="#android:id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#color/color_order_tab"
android:textSize="14sp"
android:fontFamily="sans-serif-medium"/>
</LinearLayout>
</RelativeLayout>
I want to show text on the Tab only if it selected - already done - and resize these tabs dynamically, is there any way to do that?
If I use app:tabMode="fixed" tabs don't resize, if I use app:tabMode="scrollable" my tabs are always on the left of my screen. If I do android:layout_width="wrap_content" and android:layout_gravity="center_horizontal" - TabLayout doesn't fill the screen..
So I need to:
Resize tabs when text appears or disappears;
Tabs should fill the screen in any case.
First of all, you cannot obtain all the desired feature on using fixed mode. As in fixed mode, you cannot resize your tabs.
You need to use scrollable mode in order to resize the tabs.
If I do android:layout_width="wrap_content" and
android:layout_gravity="center_horizontal" - TabLayout doesn't fill
the screen
You can set a parent container and set a background so that it gives you a feel of a tab layout with full device width.
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/holo_orange_light">
<android.support.design.widget.TabLayout
android:id="#+id/tabs"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
app:tabGravity="center"
app:tabMode="scrollable" />
</FrameLayout>
Then, you can add the tabs i.e. your custom tabs in your tab layout and after that, you can add addOnTabSelectedListener to get the desired results:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
View view = getLayoutInflater().inflate(R.layout.custom_tab, null);
((TextView) view.findViewById(R.id.text)).setText("large text one");
View view1 = getLayoutInflater().inflate(R.layout.custom_tab, null);
((TextView) view1.findViewById(R.id.text)).setText("1");
View view2 = getLayoutInflater().inflate(R.layout.custom_tab, null);
((TextView) view2.findViewById(R.id.text)).setText("Large Text Text Text");
View view3 = getLayoutInflater().inflate(R.layout.custom_tab, null);
((TextView) view3.findViewById(R.id.text)).setText("One");
View view4 = getLayoutInflater().inflate(R.layout.custom_tab, null);
((TextView) view4.findViewById(R.id.text)).setText("Another large text");
mBinding.tabs.addTab(mBinding.tabs.newTab().setCustomView(view));
mBinding.tabs.addTab(mBinding.tabs.newTab().setCustomView(view1));
mBinding.tabs.addTab(mBinding.tabs.newTab().setCustomView(view2));
mBinding.tabs.addTab(mBinding.tabs.newTab().setCustomView(view3));
mBinding.tabs.addTab(mBinding.tabs.newTab().setCustomView(view4));
mBinding.tabs.getTabAt(0).getCustomView().findViewById(R.id.text).setVisibility(View.VISIBLE);
mBinding.tabs.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
tab.getCustomView().findViewById(R.id.text).setVisibility(View.VISIBLE);
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
tab.getCustomView().findViewById(R.id.text).setVisibility(View.GONE);
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
As you can see the tabs are now resizable and only text on the selected tab is visible. Hope that help
<com.google.android.material.tabs.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabIndicatorColor="#android:color/white"
app:tabTextAppearance="?attr/tabTextAppearance"
app:tabMode="scrollable" />
Related
I want to change my tab text size when selected or unselected like this.
My tablayout
<com.google.android.material.tabs.TabLayout
android:id="#+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/toolbar"
android:overScrollMode="never"
app:tabGravity="fill"
app:tabMaxWidth="0dp"
app:tabMode="scrollable"
app:tabRippleColor="#null"
app:tabTextAppearance="#style/MyCustomTabText"
app:tabIndicatorHeight="0dp"
/>
MyCustom style
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="MyCustomTabText">
<item name="android:textSize">16sp</item>
</style>
<resources>
I use the custom style for text size but I do not know how to change when it is selected/unselected. Could someone give me a hand with this, please?
To change the Tab font size based the selected/unselected state you have to use your custom tab view and use TabLayout.OnTabSelectedListener to change the size of selected/unselected tab.
1.TabLayout in xml can be like below:
<com.google.android.material.tabs.TabLayout
android:id="#+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="60dp"
app:tabGravity="fill"
app:tabIndicatorColor="#android:color/holo_orange_light">
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Tab 1" />
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Tab 2" />
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Tab 3" />
</com.google.android.material.tabs.TabLayout>
2.Initialise for each tab a CustomView using setCustomView method and use TabLayout.OnTabSelectedListener to listen which tab is currently selected and which one is now unselected and change the text size like below:
//get each tab from tabLayout
TabLayout.Tab tab0 = tabLayout.getTabAt(0);
TabLayout.Tab tab1 = tabLayout.getTabAt(1);
TabLayout.Tab tab2 = tabLayout.getTabAt(2);
//and set for each one a custom View
tab0.setCustomView(createCustomTabView("Tab 0", 30, android.R.color.holo_green_light)); //initially this tab is selected
tab1.setCustomView(createCustomTabView("Tab 1", 15, android.R.color.black));
tab2.setCustomView(createCustomTabView("Tab 2", 15, android.R.color.black));
//add OnTabSelectedListener
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener(){
#Override
public void onTabSelected(TabLayout.Tab tab) {
setTabTextSize(tab, 30, android.R.color.holo_green_light);
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
setTabTextSize(tab, 15, android.R.color.black);
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
with the below helper functions to create the Tab CustomView and to change the text size based the selected/unselected state:
private View createCustomTabView(String tabText, int tabSizeSp, int textColor){
View tabCustomView = getLayoutInflater().inflate(R.layout.tab_customview, null);
TextView tabTextView = tabCustomView.findViewById(R.id.tabTV);
tabTextView.setText(tabText);
tabTextView.setTextSize(tabSizeSp);
tabTextView.setTextColor(ContextCompat.getColor(tabCustomView.getContext(), textColor));
return tabCustomView;
}
private void setTabTextSize(TabLayout.Tab tab, int tabSizeSp, int textColor){
View tabCustomView = tab.getCustomView();
TextView tabTextView = tabCustomView.findViewById(R.id.tabTV);
tabTextView.setTextSize(tabSizeSp);
tabTextView.setTextColor(ContextCompat.getColor(tabCustomView.getContext(), textColor));
}
3.And the custom Tab layout R.layout.tab_customview can be like this:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:tools="http://schemas.android.com/tools">
<TextView
android:id="#+id/tabTV"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:textSize="15sp"
android:textAlignment="center"
android:textColor="#android:color/black"
android:maxLines="1"
tools:text="Tab"/>
</RelativeLayout>
Result:
I need to show a multiple-line text description below my tabs icons (actually I need two lines but trying to describe it generally).
Using a one-word description will impair the readability and I do not want to use a scrollable tab layout because I need to show just 4 options.
In addition, using TextView as a custom view for the tab layout just feels wrong.
I've tried to do a custom layout for tab item and use it but for some reason words-break in the middle.
Is there any option to show the tab description but not as a single line
Solved with custom layout and OnTabSelectedListener.
My custom layout (tab_item.xml):
<?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/tab_item_icon"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginTop="8dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="#drawable/some_icon_drawable" />
<TextView
android:id="#+id/tab_item_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:autoText="false"
android:breakStrategy="simple"
android:singleLine="false"
android:text="Two Lines Text View"
android:textAlignment="center"
android:textAllCaps="true"
android:textSize="10sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/tab_item_icon" /></androidx.constraintlayout.widget.ConstraintLayout>
My setTabs and method:
private void setTabs(){
TabLayout tabLayout = view.findViewById(R.id.tabLayout);
icons.add(R.drawable.some_drawable_1);
icons.add(R.drawable.some_drawable_2);
icons.add(R.drawable.some_drawable_3);
icons.add(R.drawable.some_drawable_4);
tabsNames.add(getString(R.string.some_tab_name_1));
tabsNames.add(getString(R.string.some_tab_name_2));
tabsNames.add(getString(R.string.some_tab_name_3));
tabsNames.add(getString(R.string.some_tab_name_4));
new TabLayoutMediator(tabLayout, viewPager,
(tab, position) -> tab.setCustomView(R.layout.tab_item)
).attach();
for(int currTab = 0; currTab < tabsNames.size() ; currTab++){
tabTextView = (tabLayout.getTabAt(currTab).getCustomView().findViewById(R.id.tab_item_text));
tabImageView = (tabLayout.getTabAt(currTab).getCustomView().findViewById(R.id.tab_item_icon));
tabTextView.setText(tabsNames.get(currTab));
tabImageView.setImageDrawable(getResources().getDrawable(icons.get(currTab), null));
}
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
tabTextView = (tabLayout.getTabAt(tab.getPosition()).getCustomView().findViewById(R.id.tab_item_text));
tabImageView = (tabLayout.getTabAt(tab.getPosition()).getCustomView().findViewById(R.id.tab_item_icon));
tabTextView.setTextColor(getResources().getColor(R.color.colorPrimary));
tabImageView.setColorFilter(getResources().getColor(R.color.colorPrimary));
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
tabTextView = (tabLayout.getTabAt(tab.getPosition()).getCustomView().findViewById(R.id.tab_item_text));
tabImageView = (tabLayout.getTabAt(tab.getPosition()).getCustomView().findViewById(R.id.tab_item_icon));
tabTextView.setTextColor(getResources().getColor(R.color.colorPrimaryDark));
tabImageView.setColorFilter(getResources().getColor(R.color.colorPrimaryDark));
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
tabTextView = (tabLayout.getTabAt(tab.getPosition()).getCustomView().findViewById(R.id.tab_item_text));
tabImageView = (tabLayout.getTabAt(tab.getPosition()).getCustomView().findViewById(R.id.tab_item_icon));
tabTextView.setTextColor(getResources().getColor(R.color.colorPrimary));
tabImageView.setColorFilter(getResources().getColor(R.color.colorPrimary));
}
});
tabLayout.getTabAt(0).select();
}
i have this pager in the layout and i tried to setVisibility for the pager and the linear layout based on condition , but its not working i search in the internet and all have the same answer, any idea ?
this is the xml
<LinearLayout
android:orientation="vertical"
android:id="#+id/error_linear_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:weightSum="1"
android:visibility="visible">
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:srcCompat="#mipmap/ic_launcher"
android:id="#+id/error_image_view"
android:layout_weight="0.59" />
<TextView
android:text="This Screen Is Not Active"
android:textSize="30sp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/error_text_view"
android:layout_weight="0.59" />
</LinearLayout>
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="visible"></android.support.v4.view.ViewPager>
and this is the main activity
ViewPager imagePager;
LinearLayout errorLayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_image_pager);
//views
errorLayout = (LinearLayout) findViewById(R.id.error_linear_layout);
imagePager = (ViewPager) findViewById(R.id.pager);
IsActive();
}
public void IsActive()
{
String x = "x";
if (x=="x")
{
imagePager.setVisibility(View.VISIBLE);
errorLayout.setVisibility(View.INVISIBLE);
}else
{
imagePager.setVisibility(View.INVISIBLE);
errorLayout.setVisibility(View.VISIBLE);
}
}
Maybe the error isnt that the view isnt INVISIBLE, but that:
x can never equal "x". variable X is a reference, not the actual representation of it.
Use:
if(x.equals("x")) instead.
I want to change indicator of tablayout from bottom to top.
my code
activity_tab.xml
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light" />
<android.support.design.widget.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabIndicatorColor="#000000"
app:tabMode="scrollable"
/>
</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" />
I want this result.
how to do
thx for ask me and sorry for bad english.
Don't use scale = -1 and things like that.
From XML you can use app:tabIndicatorGravity="top"
From code you can use setSelectedTabIndicatorGravity(INDICATOR_GRAVITY_TOP)
It can be done by xml attribute, use android:scaleY="-1" in xml code. The view will flip vertically. Use the same method to correct the text and image used in tab title.
In xml file:
<android.support.design.widget.TabLayout
android:id="#+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
android:scaleY="-1"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"/>
In Java code
tabLayout = (TabLayout) findViewById(R.id.tabLayout);
// Adding the tabs using addTab() method
tabLayout.addTab(tabLayout.newTab().setText("Section 1"));
tabLayout.addTab(tabLayout.newTab().setText("Section 2"));
tabLayout.addTab(tabLayout.newTab().setText("Section 3"));
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
TextView tv1 = (TextView)(((LinearLayout)((LinearLayout)tabLayout.getChildAt(0)).getChildAt(0)).getChildAt(1));
tv1.setScaleY(-1);
TextView tv2 = (TextView)(((LinearLayout)((LinearLayout)tabLayout.getChildAt(0)).getChildAt(1)).getChildAt(1));
tv2.setScaleY(-1);
TextView tv3 = (TextView)(((LinearLayout)((LinearLayout)tabLayout.getChildAt(0)).getChildAt(2)).getChildAt(1));
tv3.setScaleY(-1);
You can achieve this by rotating the TabLayout like this:
tabLayout.setRotationX(180);
Then you must rotate all of its TextView children back, or you can set the TabLayout a custom view, instead of recursively searching for a TextView:
TabLayout.Tab tab = tabLayout.getTabAt(i);
tab.setCustomView(R.layout.layout_tab_view);
layout_tab_view.xml
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:rotationX="180"
android:text="HOME"/>
I guess you loose some default functionality if you set a custom view, such as Fragment title naming from PagerAdapter and TextView disabled appearance, but you can bind that somehow together in another way.
Unfortunately you cannot do it by setting an attribute or setting it in code.
TabLayout has a property mTabStrip of SlidingTabStrip (internal class), which is set as private final
private final SlidingTabStrip mTabStrip;
, so you cannot access it, by extending TabLayout.
So SlidingTabStrip (which extends LinearLayoyut)is a view which overrides draw method
#Override
public void draw(Canvas canvas) {
super.draw(canvas);
// Thick colored underline below the current selection
if (mIndicatorLeft >= 0 && mIndicatorRight > mIndicatorLeft) {
canvas.drawRect(mIndicatorLeft, getHeight() - mSelectedIndicatorHeight,
mIndicatorRight, getHeight(), mSelectedIndicatorPaint);
}
}
So you can see that it draws the rectangle with a top and bottom properties.
May be in future they will have a flag to change it.
I have a different approach for doing that..
Set the tab indicator color same as the background color of the tab layout (So that you will not see the tab indicator at bottom)
Add a linear layout (horizontal) just above the tab layout containing views (same number as equal to number of tabs).
<LinearLayout
android:layout_width="match_parent"
android:layout_height="5dp"
android:orientation="horizontal"
android:background="#color/tab_bg"
android:weightSum="3">
<View
android:id="#+id/view1"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:elevation="10dp"
android:background="#drawable/selector_tab_indicator_white"/>
<View
android:id="#+id/view2"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:elevation="10dp"
android:background="#drawable/selector_tab_indicator_blue"/>
<View
android:id="#+id/view3"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:elevation="10dp"
android:background="#drawable/selector_tab_indicator_blue"/>
</LinearLayout>
Now just programmatically adjust the view backgrounds.
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
setTitle(getPageTitle(position));
switch(position){
case 0:
view1.setBackgroundResource( R.drawable.selector_tab_indicator_white );
view2.setBackgroundResource( R.drawable.selector_tab_indicator_blue );
view3.setBackgroundResource( R.drawable.selector_tab_indicator_blue );
break;
case 1:
view1.setBackgroundResource( R.drawable.selector_tab_indicator_blue );
view2.setBackgroundResource( R.drawable.selector_tab_indicator_white );
view3.setBackgroundResource( R.drawable.selector_tab_indicator_blue );
break;
case 2:
view1.setBackgroundResource( R.drawable.selector_tab_indicator_blue );
view2.setBackgroundResource( R.drawable.selector_tab_indicator_blue );
view3.setBackgroundResource( R.drawable.selector_tab_indicator_white );
break;
default:
view1.setBackgroundResource( R.drawable.selector_tab_indicator_white );
view2.setBackgroundResource( R.drawable.selector_tab_indicator_blue );
view3.setBackgroundResource( R.drawable.selector_tab_indicator_blue );
break;
}
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
Use these selectors for customising the views
selector_tab_indicator_white.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:radius="50dp"/>
<stroke
android:width="1dp"
android:color="#c4c0c0" />
<solid
android:color="#fafafa" />
selector_tab_indicator_blue.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:radius="0dp"/>
<stroke
android:width="1dp"
android:color="#color/tab_bg" />
<solid
android:color="#color/tab_bg" />
The Result:
You only need those lines
tabLayout.setRotationX(180);
tabListed = ((LinearLayout)tabLayout.getChildAt(0));
for(int position = 0;position<tabListed.getChildCount();position++) {
LinearLayout item=((LinearLayout) tabListed.getChildAt(position));
item.setBackground(getDrawable(R.drawable.square_tab));
item.setRotationX(180);
}
First tab rotation turn tab layout 180º then you will get all tabs and them turn it 180º. So they be good again.
It can't be done by xml attribute, but can be done via setting image in background of tab with filled colour at top and transparent at bottom.
<android.support.design.widget.TabLayout
...
app:tabBackground="#drawable/bg_tab"
...
/>
bg_tab.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/cap" android:state_selected="true" />
</selector>
cap.png
transparent at bottom
I know this question was asked 2 years ago, but I didn't find any simple solution without using any library (smartTabLayout doesn't have SelectedTextColour property).
invert your tabLayout to get the indicator at the top
android:rotationX="180"
now this will cause the text in that tab to be inverted as well, so to counter that
we'll have to create custom Tab view. Make an xml file eg: layout_custom_tab
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/tab.text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:maxLines="1"
android:padding="10dp"
android:rotationX="180"
android:textAllCaps="true"
android:textSize="12sp"
android:textColor="#color/white"
/>
Note: you don't need RelativeLayout or anyting else when there is just one element
create your own TabLayout
and set the customView to it.
public class TabLayoutPlus extends TabLayout {
public TabLayoutPlus(Context context) {
super(context);
}
public TabLayoutPlus(Context context, AttributeSet attrs) {
super(context, attrs);
}
public TabLayoutPlus(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
public void setupWithViewPager(ViewPager viewPager) {
super.setupWithViewPager(viewPager);
this.removeAllTabs();
PagerAdapter adapter = viewPager.getAdapter();
for (int i = 0, count = adapter.getCount(); i < count; i++) {
Tab tab = this.newTab();
View customView = LayoutInflater.from(getContext()).inflate(R.layout.layout_custom_tab, null);
TextViewPlus tv = (TextViewPlus) customView.findViewById(R.id.tab_text);
tv.setText(adapter.getPageTitle(i));
tab.setCustomView(customView);
this.addTab(tab.setText(adapter.getPageTitle(i)));
}
}
}
your TabLayout in your activity will look like this
<TabLayoutPlus
android:id="#+id/tablayout"
android:layout_width="match_parent"
android:layout_height="36dp"
android:layout_above="#+id/camera.buttons.layout"
android:layout_centerHorizontal="true"
android:background="#color/cardscan.background"
android:rotationX="180"
app:tabGravity="center"
app:tabIndicatorColor="#color/colorPrimary"
app:tabMode="fixed"
app:tabSelectedTextColor="#color/colorPrimary"
app:tabTextColor="#color/white"
/>
if you need to highlight Selected tab text colour
private void setSelectedTab(TabLayoutPlus.Tab tab) {
View view = tab.getCustomView();
TextViewPlus tabtext = (TextViewPlus) view.findViewById(R.id.tab_text);
tabtext.setTextColor(ContextCompat.getColor(this, R.color.colorPrimary)); // color you want to highlight your text with
}
private void setUnselectedTab(TabLayoutPlus.Tab tab){
View view = tab.getCustomView();
TextViewPlus tabtext = (TextViewPlus) view.findViewById(R.id.tab_text);
tabtext.setTextColor(ContextCompat.getColor(this, R.color.white)); // color you want to lowlight your text with
}
Now just add OnTabSelectedListener
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
setSelectedTab(tab);
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
setUnselectedTab(tab);
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
setSelectedTab(tab);
}
});
I solved using this method
set scaleY="-1" , this will rotate TabLayout to 180 degrees, as a result tab layout rotated reverse with text and rotate your TextView to Horizontally to 180 degrees, that will solve the problem, see the code below
activity.xml
<RelativeLayout 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="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.view.ViewPager
android:id="#+id/viewpager_exp"
android:layout_above="#+id/tabs_RL"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
<RelativeLayout
android:id="#+id/tabs_RL"
android:layout_alignParentBottom="true"
android:layout_width="match_parent"
android:layout_height="#dimen/footer_height">
<android.support.design.widget.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="#dimen/dimen_60"
android:background="#color/white"
android:clipToPadding="false"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:scaleY="-1"
app:layout_scrollFlags="snap|enterAlways"
app:tabGravity="fill"
app:tabMaxWidth="0dp"
app:tabIndicatorHeight="4dp"
app:tabIndicatorColor="#color/dark_pink1"
app:tabMinWidth="50dp"
app:tabPaddingEnd="0dp"
app:tabPaddingStart="0dp"
app:tabMode="fixed" />
</RelativeLayout>
</RelativeLayout>
</RelativeLayout>
custom_tab.xml
<customviews.CusMediumTextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/tab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:textColor="#000000"
android:textSize="#dimen/dimen_12"
android:rotationX="180"
android:textStyle="bold" />
MainActivity.class
tabLayout.setupWithViewPager(viewPager);
tabOne = (CusMediumTextView) LayoutInflater.from(this).inflate(R.layout.custom_tab, null);
tabOne.setText("Tab1");
tabOne.setTextColor(getResources().getColor(R.color.light_black));
tabOne.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.home_icon, 0, 0);
tabTwo = (CusMediumTextView) LayoutInflater.from(this).inflate(R.layout.custom_tab, null);
tabTwo.setText("Tab2");
tabTwo.setTextColor(getResources().getColor(R.color.light_black));
tabTwo.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.settin_icon, 0, 0);
tabThree = (CusMediumTextView) LayoutInflater.from(this).inflate(R.layout.custom_tab, null);
tabThree.setText("Tab3");
tabThree.setTextColor(getResources().getColor(R.color.light_black));
tabThree.setCompoundDrawablesWithIntrinsicBounds( 0,R.drawable.delete_icon, 0, 0);
tabFour = (CusMediumTextView) LayoutInflater.from(this).inflate(R.layout.custom_tab, null);
tabFour.setText("Tab4");
tabFour.setTextColor(getResources().getColor(R.color.light_black));
tabFour.setCompoundDrawablesWithIntrinsicBounds( 0, R.drawable.msg_icon,0, 0);
tabLayout.getTabAt(0).setCustomView(tabOne);
tabLayout.getTabAt(1).setCustomView(tabTwo);
tabLayout.getTabAt(2).setCustomView(tabThree);
tabLayout.getTabAt(3).setCustomView(tabFour);
I have a ViewPager that contains several instances of the same fragment, this fragment contains an article. The Article view hierarchy is quite simple, a Title, a Banner image, a subtitle and a body; everything but the title is wrapped in a scrollview.
The problem is, when you swipe to a new page, the fragment is presented with the Views at the top, and then it immediately scrolls to the middle of the container. (As a matter of fact it scrolls to the beginning of the TextView with id: article_content)
I have posted the layout at the bottom of the question.
Now, the ViewPager is set with a simple implementation of a FragmentStatePagerAdapter, here's the code:
class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {
Bundle args;
int count;
public ScreenSlidePagerAdapter(FragmentManager fm) {
super(fm);
this.count = 8;
}
#Override
public Fragment getItem(int position) {
ArticleFragment mPrimaryFragment = new ArticleFragment();
args = new Bundle();
args.putString(ArticleFragment.KEY_ARTICLE_URL, mCurArticleLink);
mPrimaryFragment.setArguments(args);
return mPrimaryFragment;
}
#Override
public int getCount() {
return count;
}
}
The Fragment itself is pretty simple too. First, I check during onCreate to see if we have the article cached, the I call on onCreateView
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.apk_article_view, null);
mTitle = (TextView) view.findViewById(R.id.article_title);
mBanner = (ImageView) view.findViewById(R.id.article_banner);
mSubTitle = (TextView) view.findViewById(R.id.article_subtitle);
mContent = (TextView) view.findViewById(R.id.article_content);
if (isArticleCached) {
Constants.logMessage("Article is cached, loading from database");
setApkArticleContent();
}
else {
Constants.logMessage("Article isn't cached, downloading");
HtmlHelper.setApkArticleContent(mContext, mUrl, mTitle, mSubTitle, mContent, mBanner);
setRefreshing(true);
}
return view;
}
It is worth noting that setApkArticleContent is a simple set of Texts, nothing fancy:
private void setApkArticleContent() {
mTitle.setText(Html.fromHtml(mCursor.getString(mCursor.getColumnIndex(DbOpenHelper.TITLE))));
mSubTitle.setText(Html.fromHtml(mCursor.getString(mCursor.getColumnIndex(DbOpenHelper.SUBTITLE))));
mContent.setText(Html.fromHtml(mCursor.getString(mCursor.getColumnIndex(DbOpenHelper.BODY))));
UrlImageViewHelper.setUrlDrawable(mBanner, mCursor.getString(mCursor.getColumnIndex(DbOpenHelper.BANNER)));
}
Also, please know that I did not have a pager before, the fragment was only loaded to an empty activity, and it worked without scrolling to the middle of the scrollview.
I am really not sure what is triggering the scroll, and yes, I know I can programatically set it to scroll back to the top after loading, but then again, that'd be two scroll movements when the fragment is loaded and it would be quite noticeable for the user.
Do you guys have any ideas why it would behave like this? Any ideas on how I can stop that unintentional scroll?
Thanks,
Below is the layout for the ArticleFragment:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/article_title"
style="#style/headerTextBoldNoUnderline"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="left|center_vertical"
android:text="" />
<ScrollView
android:layout_height="match_parent"
android:layout_width="match_parent"
>
<LinearLayout
android:orientation="vertical"
android:layout_height="wrap_content"
android:layout_width="match_parent"
>
<ImageView
android:id="#+id/article_banner"
android:layout_gravity="center_vertical|center_horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="12dp" />
<TextView
android:id="#+id/article_subtitle"
style="#style/HeaderTextItalicNoUnderline"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="left|center_vertical" />
<View
android:layout_width="fill_parent"
android:layout_height="1dp"
android:background="?android:attr/dividerVertical" />
<TextView
android:id="#+id/article_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-light"
android:gravity="left|center_vertical"
android:padding="8dp"
android:textColor="?android:attr/textColorSecondary"
android:textIsSelectable="true"
android:textSize="16sp" />
</LinearLayout>
</ScrollView>
</LinearLayout>
This is likely caused by android:textIsSelectable. You may try adding the following to the ScrollView:
android:focusable="true"
android:focusableInTouchMode="true"
android:descendantFocusability="beforeDescendants"
Add this attribute value android:descendantFocusability="blocksDescendants" to the child of ScrollView, according to this question: How to prevent a scrollview from scrolling to a webview after data is loaded?
I also had this problem. I solved it with setting android:focusable="true" and android:focusableInTouchMode="true" to the first element in the ScrollView's LinearLayout.
i try to add
android:focusable="true"
android:focusableInTouchMode="true"
android:descendantFocusability="beforeDescendants"
in the root viewGroup .
it's work's well.
like below.
<RelativeLayout 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="match_parent"
android:focusable="true"
android:focusableInTouchMode="true"
android:descendantFocusability="beforeDescendants"
android:background="#color/normal_bg">
<ScrollView
android:id="#+id/scroll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#+id/rl_enter"
android:scrollbars="none">
</ScrollView>
</RelativeLayout>
I tried solution:
android:focusable=true
android:focusableInTouchMode=true
android:descendantFocusability=beforeDescendants
And i dont know why but I cant do this with my RelativeLayout which is parent view (this does not work).
I had to wrap my TextView inside FrameLayout and now everything is ok. Maybe this helps somebody.
<FrameLayout
android:id="#+id/detail_description_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/detail_parameters_container"
android:layout_centerInParent="true"
android:descendantFocusability="beforeDescendants"
android:focusable="true"
android:focusableInTouchMode="true" >
<TextView
android:id="#+id/detail_descritpion"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:autoLink="all"
android:padding="10dp"
android:textIsSelectable="true" />
</FrameLayout>
ScrollView inside ViewPager scrolls automatically but does not scrolls in middle..
Check out this.
pager.setOnPageChangeListener(new OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
// TODO Auto-generated method stub
int x=iv.getLeft();
int y=iv.getTop();
scroll.scrollTo(x, y);
}
pager is ViewPager's object and scroll is ScrollView and iv is any View say TextView or ImageView.
When we change page in viewpager, scrollbar automatically scrolls but to the left. If you would have find solution to middle please let me know.. :)