AndroidUI组件SlidingTabLayout实现ViewPager页滑动效果
程序员文章站
2024-03-03 19:47:28
使用slidingtablayout需要准备2个类,分别是 slidingtablayout,与slidingtabstrip,,放进项目中时只用修改下包名即可。...
使用slidingtablayout需要准备2个类,分别是 slidingtablayout,与slidingtabstrip,,放进项目中时只用修改下包名即可。
效果制作的不是很好。
这篇文章,也是在网上搜了很多资源参考,对 slidingtablayout.java和slidingtabstrip.java进行了修改。大家可以更改他的格式字体大小、选中状态,分割线调整等等。先上传这两个文件,改动支出都做了注释。
slidingtablayout.java
/* * copyright (c) 2013 the android open source project * * licensed under the apache license, version 2.0 (the "license"); * you may not use this file except in compliance with the license. * you may obtain a copy of the license at * * http://www.apache.org/licenses/license-2.0 * * unless required by applicable law or agreed to in writing, software * distributed under the license is distributed on an "as is" basis, * without warranties or conditions of any kind, either express or implied. * see the license for the specific language governing permissions and * limitations under the license. */ package com.example.my.slidingtablayout; import android.content.context; import android.content.res.typedarray; import android.graphics.color; import android.graphics.typeface; import android.os.build; import android.support.v4.view.pageradapter; import android.support.v4.view.viewpager; import android.util.attributeset; import android.util.typedvalue; import android.view.gravity; import android.view.layoutinflater; import android.view.view; import android.widget.horizontalscrollview; import android.widget.linearlayout; import android.widget.textview; /** * to be used with viewpager to provide a tab indicator component which give constant feedback as to * the user's scroll progress. * <p> * to use the component, simply add it to your view hierarchy. then in your * {@link android.app.activity} or {@link android.support.v4.app.fragment} call * {@link #setviewpager(viewpager)} providing it the viewpager this layout is being used for. * <p> * the colors can be customized in two ways. the first and simplest is to provide an array of colors * via {@link #setselectedindicatorcolors(int...)} and {@link #setdividercolors(int...)}. the * alternative is via the {@link tabcolorizer} interface which provides you complete control over * which color is used for any individual position. * <p> * the views used as tabs can be customized by calling {@link #setcustomtabview(int, int)}, * providing the layout id of your custom layout. */ public class slidingtablayout extends horizontalscrollview { /** * allows complete control over the colors drawn in the tab layout. set with * {@link #setcustomtabcolorizer(tabcolorizer)}. */ public interface tabcolorizer { /** * @return return the color of the indicator used when {@code position} is selected. */ int getindicatorcolor(int position); /** * @return return the color of the divider drawn to the right of {@code position}. */ int getdividercolor(int position); } private static final int title_offset_dips = 24; private static final int tab_view_padding_dips = 16; //内边距 private static int tab_view_text_size_sp = 16; //字体大小 private int mtitleoffset; private int mtabviewlayoutid; private int mtabviewtextviewid; // 定义两种需要添加的选项卡颜色 private int mdefaulttextcolor; private int mselectedtextcolor; private viewpager mviewpager; 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); // 获取选项卡颜色,如果未定义的话,则使用主题默认的颜色 typedarray a = context.obtainstyledattributes(attrs, r.styleable.slidingtablayout); int defaulttextcolor = a.getcolor( r.styleable.slidingtablayout_android_textcolorprimary, 0); mdefaulttextcolor = a.getcolor( r.styleable.slidingtablayout_textcolortabdefault, defaulttextcolor); mselectedtextcolor = a.getcolor( r.styleable.slidingtablayout_textcolortabselected ,defaulttextcolor); a.recycle(); // 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); } // 在每次选项改变时更新选项卡文本颜色的新方法 private void updateselectedtitle(int position) { final pageradapter adapter = mviewpager.getadapter(); for (int i = 0; i < adapter.getcount(); i++) { final view tabview = mtabstrip.getchildat(i); if (textview.class.isinstance(tabview)) { textview titleview = (textview)tabview; boolean isselected = i == position; titleview.settextcolor(isselected ? mselectedtextcolor : mdefaulttextcolor); } } } /** * set the custom {@link tabcolorizer} to be used. * <p> * if you only require simple custmisation then you can use * {@link #setselectedindicatorcolors(int...)} and {@link #setdividercolors(int...)} to achieve * similar effects. */ public void setcustomtabcolorizer(tabcolorizer tabcolorizer) { mtabstrip.setcustomtabcolorizer(tabcolorizer); } /** * 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); } /** * sets the colors to be used for tab dividers. these colors are treated as a circular array. * providing one color will mean that all tabs are indicated with the same color. */ public void setdividercolors(int... colors) { mtabstrip.setdividercolors(colors); } //...设置字体大小 public void settitlesize(int size) { this.tab_view_text_size_sp = size; } /** * 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(typedvalue.complex_unit_sp, tab_view_text_size_sp); textview.settypeface(typeface.default_bold); //...这会移除 holo 的默认背景强调以及选项卡的粗体文本 if (build.version.sdk_int >= build.version_codes.honeycomb) { // if we're running on honeycomb or newer, then we can use the theme's // selectableitembackground to ensure that the view has a pressed state typedvalue outvalue = new typedvalue(); getcontext().gettheme().resolveattribute(android.r.attr.selectableitembackground, outvalue, true); textview.setbackgroundresource(outvalue.resourceid); } if (build.version.sdk_int >= build.version_codes.ice_cream_sandwich) { // if we're running on ics or newer, enable all-caps to match the action bar tab style 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 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; } tabtitleview.settext(adapter.getpagetitle(i)); //... 设置头部均分 linearlayout.layoutparams layoutparams = new linearlayout.layoutparams(0, layoutparams.wrap_content, 1.0f); tabview.setlayoutparams(layoutparams); tabview.setonclicklistener(tabclicklistener); mtabstrip.addview(tabview); } } @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) { // 调用在每次选项改变时更新文本颜色的新方案 updateselectedtitle(tabindex); 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); } if (mviewpagerpagechangelistener != null) { mviewpagerpagechangelistener.onpageselected(position); } } } private class tabclicklistener implements 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.java
/* * copyright (c) 2013 the android open source project * * licensed under the apache license, version 2.0 (the "license"); * you may not use this file except in compliance with the license. * you may obtain a copy of the license at * * http://www.apache.org/licenses/license-2.0 * * unless required by applicable law or agreed to in writing, software * distributed under the license is distributed on an "as is" basis, * without warranties or conditions of any kind, either express or implied. * see the license for the specific language governing permissions and * limitations under the license. */ package com.example.my.slidingtablayout; import android.r; import android.content.context; import android.graphics.canvas; import android.graphics.color; import android.graphics.paint; import android.util.attributeset; import android.util.typedvalue; import android.view.view; import android.widget.linearlayout; 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 = 4; //设置滚动条的高度 private static final int default_selected_indicator_color = 0xff33b5e5; private static final int default_divider_thickness_dips = 1; private static final byte default_divider_color_alpha = 0x20; private static final float default_divider_height = 0.5f; private final int mbottomborderthickness; private final paint mbottomborderpaint; private final int mselectedindicatorthickness; private final paint mselectedindicatorpaint; private final int mdefaultbottombordercolor; private final paint mdividerpaint; private final float mdividerheight; 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(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); mdefaulttabcolorizer.setdividercolors(setcoloralpha(themeforegroundcolor, default_divider_color_alpha)); mbottomborderthickness = (int) (default_bottom_border_thickness_dips * density); mbottomborderpaint = new paint(); mbottomborderpaint.setcolor(mdefaultbottombordercolor); mselectedindicatorthickness = (int) (selected_indicator_thickness_dips * density); mselectedindicatorpaint = new paint(); mdividerheight = default_divider_height; mdividerpaint = new paint(); mdividerpaint.setstrokewidth((int) (default_divider_thickness_dips * density)); } 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 setdividercolors(int... colors) { // make sure that the custom colorizer is removed mcustomtabcolorizer = null; mdefaulttabcolorizer.setdividercolors(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 int dividerheightpx = (int) (math.min(math.max(0f, mdividerheight), 1f) * height); 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); // vertical separators between the titles int separatortop = (height - dividerheightpx) / 2; for (int i = 0; i < childcount - 1; i++) { view child = getchildat(i); mdividerpaint.setcolor(tabcolorizer.getdividercolor(i)); canvas.drawline(child.getright(), separatortop, child.getright(), separatortop + dividerheightpx, mdividerpaint); } } /** * 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; // private int[] mdividercolors; // @override public final int getindicatorcolor(int position) { return mindicatorcolors[position % mindicatorcolors.length]; } @override public final int getdividercolor(int position) { return mdividercolors[position % mdividercolors.length]; } void setindicatorcolors(int... colors) { mindicatorcolors = colors; } void setdividercolors(int... colors) { mdividercolors = colors; } } }
上边因为使用了自定义的颜色,所以这里要在attrs.xml声明一下,不然找不到:
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="slidingtablayout"> <attr name="android:textcolorprimary" /> <attr name="textcolortabdefault" format="color" /> <attr name="textcolortabselected" format="color" /> </declare-styleable> </resources>
布局文件也要用到自定义:
<?xml version="1.0" encoding="utf-8"?> <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.example.my.slidingtablayout.mainactivity"> <!-- 在上方就在上面,在下方就在下面(tab栏) --> <com.example.my.slidingtablayout.slidingtablayout android:id="@+id/sliding" android:layout_width="match_parent" android:layout_height="wrap_content" app:textcolortabdefault="#000000" app:textcolortabselected="@color/coloraccent" /> <android.support.v4.view.viewpager android:id="@+id/view_pager" android:layout_width="match_parent" android:layout_height="match_parent" /> </linearlayout>
最后一道就是在你的activity运用这种开源:可以调整之处也做了说明
package com.example.my.slidingtablayout; import android.graphics.color; import android.os.bundle; import android.support.v4.view.pageradapter; import android.support.v4.view.viewpager; import android.support.v7.app.appcompatactivity; import android.view.view; import android.view.viewgroup; import android.widget.linearlayout; import java.util.arraylist; public class mainactivity extends appcompatactivity { //创建 颜色数组 用来做viewpager的背景 @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); viewpager pager = (viewpager) findviewbyid(r.id.view_pager); slidingtablayout tab = (slidingtablayout) findviewbyid(r.id.sliding); tab.setdividercolors(color.transparent); //设置标题的分割线 tab.setselectedindicatorcolors(color.rgb(51, 181, 229)); //设置滚动条的颜色 tab.settitlesize(18); //...设置字体的颜色,默认16 myadapte adapter = new myadapte(); pager.setadapter(adapter); tab.setviewpager(pager); } int[] colors = {0xff123456, 0xff654321, 0xff336699}; class myadapte extends pageradapter { //可以考虑把这个数组添加到集合里面 string[] titles = {"aa", "bb", "cc"}; arraylist<linearlayout> layouts = new arraylist<linearlayout>(); myadapte() { for (int i = 0; i < 3; i++) { linearlayout l = new linearlayout(mainactivity.this); l.setbackgroundcolor(colors[i]); l.setlayoutparams(new viewgroup.layoutparams(viewgroup.layoutparams.match_parent, viewgroup.layoutparams.match_parent)); layouts.add(l); } } @override public int getcount() { return layouts.size(); } @override public boolean isviewfromobject(view view, object o) { return view == o; } @override public object instantiateitem(viewgroup container, int position) { linearlayout l = layouts.get(position); container.addview(l); return l; } @override public void destroyitem(viewgroup container, int position, object object) { container.removeview(layouts.get(position)); } @override public charsequence getpagetitle(int position) { //...可以返回集合list.get(position); return titles[position]; } } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: PHP中获取文件创建日期、修改日期、访问时间的方法
下一篇: java计算百分比值的方法