Android 开发 TabLayout 自定义指标长度
最编程
2024-10-17 07:08:13
...
前言
原生 TabLayout 的指示器长度是充满整个屏幕的,但在实际开发中 UI 会设计成 指示器的长度等于或者小于标题字体长度,如图
如果设置成跟字体长度一样即使用 API:
mTabLayout.setTabIndicatorFullWidth(false);
或者在 xml 布局文件中的TabLayout标签设置:
app:tabIndicatorFullWidth=“false”
但如果想要指示器长度小于字体长度(如上图),API并未提供相关方法,此时就需要我们自定义一个CustomTabLayout 继承 TabLayout,允许开发者自定义选项卡的颜色、字体以及背景等属性。
二、自定义 View
public class CustomTabLayout extends TabLayout {
private List<String> titles;
private int mSelectColor = getResources().getColor(R.color.white);
private int mUnSelectColor = getResources().getColor(R.color.c_80ffffff);
public CustomTabLayout(Context context) {
this(context,null);
}
public CustomTabLayout(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public CustomTabLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.CustomTabLayout);
mSelectColor = array.getColor(R.styleable.CustomTabLayout_select_color, mSelectColor);
mUnSelectColor = array.getColor(R.styleable.CustomTabLayout_unselect_color, mUnSelectColor);
array.recycle();
init();
}
private void init() {
titles = new ArrayList<>();
this.addOnTabSelectedListener(new OnTabSelectedListener() {
@Override
public void onTabSelected(Tab tab) {
/**
* 设置当前选中的Tab为特殊高亮样式。
*/
if (tab != null && tab.getCustomView() != null) {
TextView tab_layout_text = tab.getCustomView().findViewById(R.id.tv_tab_layout);
View vIndicator = tab.getCustomView().findViewById(R.id.v_indicator);
vIndicator.setVisibility(VISIBLE);
vIndicator.setBackgroundColor(mSelectColor);
tab_layout_text.setTextColor(mSelectColor);
}
}
@Override
public void onTabUnselected(Tab tab) {
/**
* 重置所有未选中的Tab颜色、字体、背景恢复常态(未选中状态)。
*/
if (tab != null && tab.getCustomView() != null) {
TextView tab_layout_text = tab.getCustomView().findViewById(R.id.tv_tab_layout);
View vIndicator = tab.getCustomView().findViewById(R.id.v_indicator);
vIndicator.setVisibility(INVISIBLE);
tab_layout_text.setTextColor(mUnSelectColor);
}
}
@Override
public void onTabReselected(Tab tab) {
}
});
}
public void setTitle(List<String> titles) {
this.titles = titles;
/**
* 开始添加切换的Tab。
*/
for (String title : this.titles) {
Tab tab = newTab();
tab.setCustomView(R.layout.item_custom_tablayout);
if (tab.getCustomView() != null) {
TextView text = tab.getCustomView().findViewById(R.id.tv_tab_layout);
text.setText(title);
text.setTextColor(mUnSelectColor);
}
this.addTab(tab);
}
}
}
相关属性
styleable
<declare-styleable name="CustomTabLayout">
<attr name="select_color" format="color"/>
<attr name="unselect_color" format="color"/>
</declare-styleable>
item_custom_tablayout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingBottom="@dimen/dimen_5"
android:gravity="center_horizontal">
<TextView
android:id="@+id/tv_tab_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
android:textColor="@color/c_80ffffff"
android:textSize="@dimen/textsize_16"/>
<View
android:id="@+id/v_indicator"
android:layout_width="@dimen/dimen_30"
android:layout_height="@dimen/dimen_3"
android:visibility="invisible"
android:layout_marginTop="@dimen/dimen_6"
android:background="@color/white"/>
</LinearLayout>
使用方法
List<String> titles = new ArrayList<>();
titles.add("待签收");
titles.add("已签收");
List<Fragment> mFragments = initFragments();
adapter = new ViewPaperAdapter(getSupportFragmentManager(), mFragments, titles);
mViewPager.setAdapter(adapter);
mTabLayout.setTitle(titles);
//Tablayout自定义view绑定ViewPager
mViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(mTabLayout));
mTabLayout.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(mViewPager));
总结
如果对你有所帮助的话,不妨 点赞收藏
如果你有什么疑问的话,不妨 评论私信
青山不改,绿水长流 ,有缘江湖再见 ~
推荐阅读
-
Android 开发 TabLayout 自定义指标长度
-
最全Android第三方ROM开发教程及原理阐述:自定义定制化开发
-
Android 开发自定义视图,实现联系人列表 A ~ Z 字母提示效果 [附演示源代码下载]。
-
Android 自定义视图路径动画-1.获取路径上长度的位置以及该位置的正切值
-
Android Goldmap 开发(四)自定义离线地图下载
-
Android 开发中 nodpi、xhdpi、hdpi、mdpi、ldpi 的概念 - 术语和概念 屏幕尺寸 屏幕的物理尺寸,基于屏幕的对角线长度(如 2.8 英寸、3.5 英寸)。 简而言之,安卓系统将所有屏幕尺寸简化为三大类:大、普通和小。 程序可以为这三种屏幕尺寸提供三种不同的布局选项,然后系统会以合适的方式将布局选项呈现到相应的屏幕上,这个过程不需要程序员用代码进行干预。 屏幕纵横比 屏幕的物理长度与物理宽度之比。程序只需使用系统提供的资源分类器 long(长)和 notlong(不长),就能为具有特定长宽比的屏幕提供配制材料。 分辨率 屏幕的像素总数。请注意,分辨率并不意味着长宽比,尽管在大多数情况下,分辨率表示为 "宽度 x 长度"。在安卓系统中,程序一般不直接处理分辨率。 密度 根据屏幕分辨率,沿屏幕宽度和长度排列的像素数量。 密度较低的屏幕在长度和宽度方向上的像素都相对较少,而密度较高的屏幕通常会在同一区域内排列很多甚至非常非常多的像素。屏幕的密度非常重要;例如,一个界面元素(如按钮)的长度和宽度以像素为单位,在低密度屏幕上会显得很大,但在高密度屏幕上就会显得很小。 独立于密度的像素(DIP)是指程序用来定义界面元素的抽象意义上的像素。它作为一个与实际密度无关的单位,帮助程序员构建布局方案(界面元素的宽度、高度和位置)。 与密度无关的像素在逻辑上与像素密度为 160 DPI 的屏幕上的像素大小相同,而 160 DPI 是安卓平台默认的显示设备。在运行时,平台会以目标屏幕的密度为基准,"透明 "地处理所有所需的 DIP 缩放操作。要将与密度无关的像素转换为屏幕像素,可以使用一个简单的公式:像素 = DIP * (密度 / 160)。例如,在 240 DPI 的屏幕上,1 个 DIP 等于 1.5 个物理像素。强烈建议使用 DIP 来定义程序界面的布局,因为这样可以确保用户界面在所有分辨率的屏幕上都能正常显示。 为了简化程序员在面对各种分辨率时的麻烦,也为了让各种分辨率的平台都能直接运行这些程序,Android 平台将所有屏幕以密度和分辨率作为分类方式,分别分为三类:- 三大尺寸:大、普通、小;- 三种不同密度:高(hdpi)、中(mdpi)和低(ldpi)。DPI 表示 "每英寸点数",即每英寸的像素数。如果需要,程序可以为不同的屏幕尺寸提供不同的资源(主要是布局),为不同的屏幕密度提供不同的资源(主要是位图)。除此之外,程序无需对屏幕尺寸或密度进行任何额外处理。执行时,平台会根据屏幕本身的尺寸和密度特性自动加载相应的资源,并将其从逻辑像素(DIP,用于定义界面布局)转换为屏幕上的物理像素。
-
玩转Java底层:JMX详解 - jconsole与自定义MBean监控工具的实际应用与区别" 在日常JVM调优中,我们熟知的jconsole工具通过JMX包装的bean以图形化形式展示管理数据,而像jstat和jmap这类内建监控工具则由JVM直接支持。本文将以jconsole为例,深入讲解其实质——基于JMX的MBean功能,包括可视化界面上的bean属性查看和操作调用。 MBeans在jconsole中的体现是那些可观察的组件属性和方法,如上图所示,通过名为"Verbose"的属性能看到其值为false,同时还能直接操作该bean的方法,例如"closeJerryMBean"。 尽管jconsole给我们提供了直观的可视化界面,但请注意,这里的MBean并非固定不变,开发者可根据JMX提供的接口将自己的自定义bean展示到jconsole。以下步骤展示了如何创建并注册一个名为"StudyJavaMBean"的自定义MBean: 1. 首先定义接口`StudyJavaMBean`,接口需遵循MBean规范,即后缀为"MBean"且包含getter方法代表属性,如`getApplicationName`,和无返回值的setter方法代表操作,如`closeJerryMBean`。 ```java public interface StudyJavaMBean { String getApplicationName(); void closeJerryMBean(); } ``` 2. 编写接口的实现类`StudyJavaMBeanImpl`,实现接口中的方法: ```java public class StudyJavaMBeanImpl implements StudyJavaMBean { @Override public String getApplicationName() { return "每天学Java"; } @Override public void closeJerryMBean() { System.out.println("关闭Jerry应用"); } } ``` 3. 在代码中注册自定义MBean,涉及的关键步骤包括: - 获取平台MBeanServer - 定义ObjectName,指定唯一的MBean标识符 - 注册MBean到服务器 - 启动RMI连接器服务,以便jconsole能够访问 ```java public void registerMBean() throws Exception { // ... 具体实现省略 ... } ``` 实际运行注册后的MBean,您将在jconsole中发现并查看自定义bean的属性和调用相关方法。然而,这种方式相较于传统的属性/日志查看和HTTP接口,实用性相对有限,可能存在潜在的安全风险。但不可否认的是,JMX及其MBean机制对于获取操作系统信息、内存状态等关键性能指标仍然具有重要价值。例如: 1. **获取操作系统信息**:通过JMX MBean,可以直接获取到诸如CPU使用率、操作系统版本等系统级信息,这对于资源管理和优化工作具有显著帮助。