实现Android TextView自适应字体大小的实战技巧

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:在Android开发中,TextView组件需要根据内容自动调整字体大小以适应视图大小。这可以通过TextWatcher监听文本变化、使用Paint测量文本尺寸、设置LayoutParams确定TextView宽度、编写计算逻辑动态调整字体大小、设定字体大小范围限制以及性能优化等关键步骤来实现。此外,创建自定义AutoScaleTextView控件可简化实现过程。开发者可以通过查看示例项目AutoScaleTextViewDemo来学习这些技巧。 android TextView自适应字体大小

1. TextView自适应字体大小的实现

在移动应用开发中,保持界面的美观性和用户的可读性是至关重要的。特别是在设备屏幕尺寸和分辨率日益多样化的今天,如何使文本视图(TextView)中的字体大小能够根据屏幕大小和内容自动调整,成为了一个常见的挑战。这一章将探讨如何实现TextView的自适应字体大小,确保文本内容在不同设备上展示时均能够保持良好的可读性和美观。

我们将从分析TextView的布局参数(LayoutParams)和测量机制(Paint类)开始,然后逐步探索如何利用TextWatcher接口的事件监听功能来动态调整字体大小。这些技术的综合应用将引导我们开发出一个高度自适应的AutoScaleTextView控件,该控件能够根据内容长度和屏幕宽度自动调整字体大小,以最佳方式展示文本。

2. TextWatcher接口的使用与应用

2.1 TextWatcher接口的基本概念

2.1.1 TextWatcher接口的定义和功能

TextWatcher接口是Android开发中用于监听文本变化的一个接口。它提供三个方法: beforeTextChanged() onTextChanged() afterTextChanged() ,分别在文本变化之前、文本正在变化时和文本变化之后触发。通过这三个方法,开发者可以精确地控制文本变化的过程,并根据需要进行各种逻辑处理。

TextWatcher接口的典型应用场景包括实时搜索提示、表单验证、自动保存用户输入等。例如,在一个搜索框中使用TextWatcher接口,可以实时监听用户的输入,并根据输入内容动态过滤搜索结果。

2.1.2 TextWatcher接口在字体自适应中的作用

在字体自适应的场景中,TextWatcher接口可以用来监控文本的变化,并动态调整TextView中的字体大小,以保证文本始终适应其容器的大小。当用户输入文本时,TextWatcher可以监听到这些变化,并触发相应的逻辑来调整字体大小,使其尽可能地填充整个TextView而不溢出。

2.2 TextWatcher接口的事件监听方法

2.2.1 beforeTextChanged方法的触发时机与应用

beforeTextChanged() 方法在文本变化之前被调用,它的参数包括即将改变的文本、改变的位置、改变之前的长度和改变后的长度。这个方法可以用来进行一些准备操作,比如在文本变化之前保存当前状态或者进行逻辑判断。

editText.addTextChangedListener(new TextWatcher() {
    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        // 在文本改变前可以进行的操作
        // 比如记录下文本改变前的字体大小
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        // 文本正在改变时的操作
    }

    @Override
    public void afterTextChanged(Editable s) {
        // 文本改变后可以进行的操作
    }
});

在字体自适应的场景中, beforeTextChanged() 可以用来记录变化前的字体大小,为之后的字体调整提供参考。

2.2.2 onTextChanged方法的触发时机与应用

onTextChanged() 方法在文本变化过程中被调用,其参数与 beforeTextChanged() 相同。由于此方法在文本实际改变时被触发,因此可以用来获取最新的文本内容,从而实现更复杂的逻辑。

editText.addTextChangedListener(new TextWatcher() {
    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        // 可以用来存储当前文本状态
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        // 文本正在改变时的实时操作
        // 比如可以在这里根据文本长度计算新的字体大小
    }

    @Override
    public void afterTextChanged(Editable s) {
        // 文本改变后的操作
    }
});

在字体自适应的实现中, onTextChanged() 可以实时获取文本的长度变化,根据预设的逻辑调整字体大小。

2.2.3 afterTextChanged方法的触发时机与应用

afterTextChanged() 方法在文本变化完全结束后被调用,其参数为文本改变后的内容。在该方法中,我们通常执行一些收尾工作,比如更新UI、调整相关控件的布局等。

editText.addTextChangedListener(new TextWatcher() {
    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        // 文本改变前的操作
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        // 文本正在改变时的操作
    }

    @Override
    public void afterTextChanged(Editable s) {
        // 文本改变后的操作
        // 例如,可以在这里根据文本的最终长度调整字体大小
    }
});

对于字体自适应功能, afterTextChanged() 方法可以用来进行最终的字体大小调整,并且确保所有的调整都是基于文本改变后的最终状态。例如,可以在这里应用算法来计算最适合当前文本长度和TextView宽度的字体大小。

通过上述方法的综合运用,TextWatcher接口能够为开发者提供一种强大而灵活的方式来对文本变化进行监控和响应,特别是在需要动态调整文本显示效果的应用场景中,例如字体自适应显示。

3. Paint类的测量文本功能详解

3.1 Paint类的作用和重要属性

3.1.1 Paint类在文本绘制中的角色

在Android的绘图体系中, Paint 类扮演着至关重要的角色。它为开发者提供了一系列用于描述和处理文本、图形及图像绘制的属性和方法。文本的绘制,特别是自适应字体大小,离不开 Paint 的测量和渲染功能。 Paint 类控制了文本的样式、颜色、字体大小以及抗锯齿等多种属性。它的存在,使得文本的展示更加丰富、灵活。

3.1.2 Paint类的文本测量属性

Paint 类提供多个方法用于测量文本,它们是 measureText() , getTextBounds() , getTextPath() 等。 measureText() 方法可以测量字符串的宽度,而 getTextBounds() 方法不仅可以测量字符串的宽度,还可以获取字符串的边界矩形,这对于定位文本在视图中的位置非常有帮助。 getTextPath() 方法则用于获取文本的路径信息,这对于创建自定义文本效果非常有用。

3.2 Paint类测量文本的方法与实践

3.2.1 使用Paint类测量单行文本大小

测量单行文本的宽度,使用 measureText() 方法非常方便。只需将目标字符串作为参数传入,返回值为字符串的宽度,单位是像素。例如:

Paint paint = new Paint();
paint.setTextSize(16); // 设置文本大小
float width = paint.measureText("Hello, World!"); // 测量字符串宽度

在上述代码中,我们首先创建了一个 Paint 实例并设置了文本大小。然后使用 measureText() 方法测量了"Hello, World!"字符串的宽度。这个宽度值可以在布局和字体大小自适应中起到关键作用。

3.2.2 使用Paint类测量多行文本大小

对于多行文本,我们可以循环测量每一行,然后累加每一行的宽度,以此获得整体文本的宽度。需要注意的是,在测量前需要设置 Paint TextAlign 属性为左对齐,以确保测量结果的准确性:

float totalWidth = 0;
String text = "这是多行文本。\n这是一行很长的文本。";
String[] lines = text.split("\n");
paint.setTextAlign(Paint.Align.LEFT);
for (String line : lines) {
    totalWidth += paint.measureText(line);
}

在上述代码中,我们首先通过 split("\n") 将文本分割成多行,然后循环测量每一行的宽度并累加到 totalWidth 变量中。最终得到的 totalWidth 即为文本框的总宽度。

3.2.3 结合TextWatcher与Paint类动态测量文本

结合 TextWatcher 接口和 Paint 类,我们可以实现文本输入时动态测量文本的大小变化。下面展示一个简单的例子:

TextView textView = findViewById(R.id.my_text_view);
final Paint paint = new Paint();
textView.addTextChangedListener(new TextWatcher() {
    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        // 在文本改变之前可以进行相关操作
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        // 在文本改变时动态调整字体大小或布局
        float currentWidth = paint.measureText(s.toString());
        // 根据currentWidth与视图宽度的关系进行字体大小的调整
        // ...
    }

    @Override
    public void afterTextChanged(Editable s) {
        // 文本改变后可以进行相关操作
    }
});

在这个示例中, onTextChanged 方法被触发时,我们会获取当前文本内容,并使用 measureText() 方法测量其宽度。这个宽度值可以用来判断是否需要调整字体大小以适应新的文本长度。这里的调整逻辑可以参考 TextView 的内部实现逻辑,或者根据具体需求进行自定义调整。

深入探索 Paint 类测量文本功能

Paint 类方法对文本样式的影响

Paint 类提供了多种方法可以测量文本,这些方法对不同的文本样式有不同的反应。例如, measureText() 可以返回使用当前文本样式渲染时的文本宽度。而 getTextBounds() 会返回一个矩形,这个矩形包含了文本的最小矩形边界。

考虑字体样式和抗锯齿因素

在使用 Paint 测量文本时,文本的字体样式(如字体家族和样式)和抗锯齿设置( setAntiAlias )也会影响到测量结果。因为抗锯齿可以平滑字体边缘,减少锯齿现象,因此它可能会轻微影响文本的测量宽度。同样的,不同的字体样式和大小在渲染时所占用的空间也各不相同,会影响到整体文本的布局。

实际应用场景与注意事项

在实际开发中,结合 TextWatcher 使用 Paint 类测量文本时,需要特别注意避免频繁触发文本测量操作,因为它会消耗大量CPU资源,可能会造成性能问题。为了优化性能,我们可以采用节流(Throttling)或防抖(Debouncing)技术来减少测量次数,或者在非UI线程中进行测量计算。

在下一章中,我们将探索 LayoutParams 类与 TextView 尺寸调整之间的关系,进而实现动态调整字体大小,达到更优的用户界面体验。

4. LayoutParams类的应用与字体自适应实践

4.1 LayoutParams类的基本原理

4.1.1 LayoutParams类的作用和重要性

LayoutParams是Android布局参数的抽象类,它为各种视图组件提供具体的布局参数。这些参数定义了视图的宽度、高度、边距等属性,它们直接影响到视图在屏幕上的显示效果。在实现字体自适应布局时,LayoutParams类尤为关键,因为它允许动态地调整视图大小,以适应不同屏幕尺寸和内容变化。

当字体大小变化时,TextView的尺寸需要相应地进行调整,才能保证内容的完整显示而不被截断或溢出。通过动态调整LayoutParams,可以实现这种自适应效果,同时避免使用硬编码的尺寸值,提高布局的灵活性和可维护性。

4.1.2 LayoutParams与TextView尺寸的关系

为了使TextView能够自适应字体大小,我们常常需要在字体大小变化时更新其LayoutParams。LayoutParams中的宽度(width)和高度(height)属性可以设置为WRAP_CONTENT或MATCH_PARENT,或者具体的数值。在字体自适应的场景中,通常使用WRAP_CONTENT,让TextView的尺寸能够根据内容自动调整。

在字体大小动态变化时,我们可以通过设置LayoutParams的宽度和高度为WRAP_CONTENT,让TextView的尺寸跟随字体大小变化。此外,还可以根据具体的布局需求,调整边距(margin)属性,以确保文本在视图中的合理布局。

4.2 LayoutParams类在字体自适应中的实践

4.2.1 通过LayoutParams调整TextView尺寸

当需要根据字体大小调整TextView的尺寸时,可以通过编程方式动态修改其LayoutParams。以下是一个简单的示例代码:

// 获取TextView的LayoutParams
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) textView.getLayoutParams();

// 设置新的宽度和高度为WRAP_CONTENT,让TextView包裹内容
params.width = LayoutParams.WRAP_CONTENT;
params.height = LayoutParams.WRAP_CONTENT;

// 应用新的LayoutParams
textView.setLayoutParams(params);

在这段代码中,我们首先获取了TextView当前的LayoutParams实例,然后将宽度和高度属性设置为WRAP_CONTENT。最后,通过setLayoutParams方法将更新后的LayoutParams应用到TextView上,从而实现了尺寸的动态调整。

4.2.2 实现字体大小的动态调整

字体大小的动态调整通常与文本长度或视图的可用空间相关。在实际应用中,可能需要根据字体大小的变化来调整TextView的边距或其它相关视图的尺寸,以保持整体布局的协调性。

例如,当TextView内部的文本内容变多,导致宽度超出屏幕可显示范围时,可以通过增加TextView的宽度或减小其周围的边距来适应这种变化。动态调整可以结合TextWatcher监听文本变化,从而触发LayoutParams的调整:

textView.addTextChangedListener(new TextWatcher() {
    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        // 这里可以检测文本变化后的长度,并计算新的LayoutParams
        int textLength = textView.getText().toString().length();
        // 根据textLength计算新的LayoutParams...
        // ...
    }

    @Override
    public void afterTextChanged(Editable s) {
    }
});
4.2.3 优化字体自适应过程中的布局更新

为了优化字体自适应过程中的布局更新,可以采取一系列措施。首先,在调整LayoutParams时,应尽量避免全局的布局重新计算,这可以通过只修改受影响的视图属性来实现。其次,在实际的字体调整操作中,可以考虑只在特定的条件下进行更新,如字体大小变化超过一定的阈值,或者在非交互性的时刻(如用户输入后)进行布局更新。

下面是优化布局更新的一个示例:

// 假设有一个阈值变量TEXT_SIZE_THRESHOLD用于确定何时更新布局
final int TEXT_SIZE_THRESHOLD = 10;

// 更新字体大小前的检查
float newFontSize = calculateNewFontSize();
if (Math.abs(newFontSize - textView.getTextSize()) > TEXT_SIZE_THRESHOLD) {
    textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, newFontSize);
    // 仅在字体大小变化超过阈值时更新LayoutParams
    updateLayoutParams(textView);
}

在这个例子中, calculateNewFontSize 函数负责计算新的字体大小, updateLayoutParams 函数则负责根据需要更新TextView的LayoutParams。通过设置一个阈值,只有当字体大小变化达到一定程度时,才会进行布局的调整,从而提高了性能。

结语

本章节介绍了LayoutParams类在字体自适应实践中的应用。我们首先解释了LayoutParams类的基本原理,包括它的作用和重要性,以及它如何与TextView的尺寸关系紧密相连。接着,通过具体的代码实例演示了如何通过LayoutParams调整TextView尺寸,并展示了如何结合TextWatcher接口来动态调整字体大小。最后,我们探讨了优化字体自适应过程中布局更新的策略,以提高性能和响应速度。通过这些方法,可以实现一个既美观又实用的字体自适应布局。

5. 动态调整字体大小的计算逻辑

字体大小的动态调整是提升用户界面适应性的重要技术。通过适当的计算逻辑,应用程序可以确保文本在不同的设备和屏幕尺寸上保持可读性和美观性。

5.1 计算逻辑的基本要求和方法

5.1.1 动态调整字体大小的基本原理

动态调整字体大小的基本原理是基于视图尺寸和文本内容的测量来计算合适的字体尺寸。这一过程涉及到多个因素,包括屏幕尺寸、屏幕密度、视图的可用空间以及用户的阅读偏好。字体大小应当随着可用空间的变化而变化,以保持文本的清晰度和布局的整洁性。

5.1.2 计算逻辑的实现步骤和关键因素

实现字体动态调整的计算逻辑涉及以下步骤:

  1. 获取视图尺寸和屏幕尺寸 :通过编程接口获取当前视图和屏幕的尺寸。
  2. 测量文本内容 :使用 Paint 类测量给定文本内容所需的空间大小。
  3. 计算字体大小 :根据测量结果和视图剩余空间计算字体大小。通常,需要设置字体大小的上限和下限,以保证阅读体验。
  4. 设置字体大小 :将计算出的字体大小设置到 TextView 中。
  5. 考虑边界条件 :当文本内容非常短或非常长时,需要特别处理,以避免字体大小过于极端。

关键因素包括:

  • 屏幕分辨率和密度 :不同设备屏幕的密度和分辨率对字体的显示效果有极大影响,需要适当考虑。
  • 文本长度 :文本越短,可容纳的字体越大;反之亦然。
  • 视图的可用空间 :视图的实际可用空间对于确定字体大小至关重要。
  • 用户偏好 :允许用户设置字体大小偏好也是提升用户体验的好方法。

5.2 实现自适应字体大小的算法

5.2.1 字体大小与视图空间的平衡算法

为了实现字体大小与视图空间的平衡,可以使用以下算法:

  1. 初始化字体大小 :设置一个合理的初始字体大小。
  2. 测量文本宽度 :使用 Paint measureText 方法获取文本宽度。
  3. 计算视图剩余空间 :从 TextView 的宽度中减去文本宽度,得到剩余空间。
  4. 调整字体大小 :根据剩余空间和字体大小的关系调整字体大小,使其尽可能充满可用空间,但不超过最大或最小限制。
  5. 循环和细化 :重复步骤2-4直到字体大小稳定。

5.2.2 算法的优化和调整方法

优化自适应字体大小算法的关键在于减少字体大小调整的迭代次数,同时确保算法的执行效率和结果的平滑性。以下是一些优化方法:

  • 智能缩放因子 :使用智能缩放因子,每次根据当前字体大小和剩余空间计算出一个合适的缩放比例,快速逼近理想字体大小。
  • 缓存机制 :对于常用字体大小范围内的文本,可以使用缓存机制存储计算结果,避免重复计算。
  • 并发处理 :在可能的情况下,可以将文本测量和字体大小计算过程并行处理,以减少用户等待时间。

5.2.3 字体自适应的边界条件处理

处理边界条件时,需要特别关注极端情况:

  • 极短文本 :对于极短的文本,应限制字体大小的增长,避免单个字符占用过多空间。
  • 极长文本 :对于极长的文本,应设定最小字体大小限制,保证文本的可读性。
  • 极小或极大屏幕 :对于屏幕尺寸远小于或远大于普通手机的设备,需要特别考虑用户可接受的阅读范围,并作出相应调整。

通过以上步骤和优化方法,可以实现一个既快速又平滑的动态字体大小调整算法。在实现过程中,代码的精炼和效率的提升至关重要,下面是一个示例代码,展示了动态调整字体大小的实现:

public void adjustFontSize(TextView textView, String text) {
    Paint paint = textView.getPaint();
    Rect bounds = new Rect();
    float textViewWidth = textView.getWidth() - textView.getPaddingLeft() - textView.getPaddingRight();
    float currentTextSize = textView.getTextSize();
    float minTextSize = textView.getTextSize() * 0.5f;
    float maxTextSize = textView.getTextSize() * 2.0f;

    paint.getTextBounds(text, 0, text.length(), bounds);
    float textWidth = bounds.width();
    float ratio = textViewWidth / textWidth;
    float newFontSize = currentTextSize * ratio;

    if (newFontSize > maxTextSize) {
        newFontSize = maxTextSize;
    } else if (newFontSize < minTextSize) {
        newFontSize = minTextSize;
    }

    textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, newFontSize);
}

在上述代码中,首先创建 Paint 对象,并通过 getTextBounds 方法获取文本的边界,从而计算出文本所需的空间。然后,根据视图宽度和文本宽度计算出一个缩放比例,并相应地调整字体大小,同时确保调整后的字体大小在指定的最小和最大值之间。

以上是动态调整字体大小计算逻辑的详细探讨,通过合理的计算和算法优化,可以确保应用在不同设备上提供良好的阅读体验。在自定义 AutoScaleTextView 控件时,这些技术将发挥核心作用。

6. 自定义AutoScaleTextView控件与示例分析

在现代移动应用开发中,对UI组件的自定义与优化是一个不可或缺的部分。特别是在Android平台上,为了提供更好的用户体验,开发者经常会遇到需要根据内容长度、屏幕大小或用户偏好来动态调整文本大小的需求。本章节将介绍自定义AutoScaleTextView控件的必要性、优势以及创建过程,并分析一个示例项目AutoScaleTextViewDemo来深化理解。

6.1 自定义控件的必要性和优势

6.1.1 Android自定义控件的概述

Android提供了一整套丰富的UI组件,例如Button、TextView等,但这些标准控件在某些情况下并不能完全满足特定的需求。例如,你可能需要一个可以在特定条件下自动调整字体大小的TextView来提升可读性。这时,就需要通过继承现有的控件类或自定义新的控件来实现这些特定的功能。自定义控件给了我们更多的灵活性和控制权,使得我们可以创建出更加贴近应用需求的UI组件。

6.1.2 AutoScaleTextView控件的需求分析

想象这样一个场景:在一个聊天应用中,由于消息内容长度不一,传统的TextView无法很好地适应屏幕。若消息内容过长,它可能会溢出屏幕边界,而内容过短则会导致大量的空白区域,影响用户的阅读体验。为了优化这一问题,我们可以设计一个AutoScaleTextView控件,它可以自动调整其内部文本的大小,使得无论文本长度如何,都能够优雅地适应屏幕。

6.2 创建自定义AutoScaleTextView控件

6.2.1 控件的设计和实现

创建自定义AutoScaleTextView控件首先需要继承原有的TextView类,并重写其测量文本和绘制文本的方法。这涉及到对布局参数的动态调整和文本绘制属性的精细控制。

public class AutoScaleTextView extends TextView {
    // 构造方法
    public AutoScaleTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        // 初始化工作
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        // 重写测量方法以调整尺寸
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // 重写绘制方法以动态调整字体大小
    }
    // 实现自适应逻辑
    private void adjustTextSize() {
        // 根据实际需求调整字体大小的代码逻辑
    }
}

6.2.2 控件的封装和可用性测试

在完成控件的初步实现后,要进行充分的单元测试和UI测试来验证其功能正确性和稳定性。同时,良好的封装可以帮助控件在不同的应用场景中被复用,并简化使用者的集成过程。

6.3 示例项目AutoScaleTextViewDemo分析

6.3.1 项目结构和运行原理

示例项目AutoScaleTextViewDemo的结构应该简洁明了,包含一个主Activity、布局文件以及自定义的AutoScaleTextView控件。在运行时,该控件会根据接收到的消息内容长度动态调整其字体大小,保证文本始终能够适应屏幕宽度。

6.3.2 关键代码的解读与分析

关键的实现代码应该包括在AutoScaleTextView类中,特别是测量和绘制过程中字体大小的调整逻辑。此外,还需要展示如何在布局文件中使用该控件以及如何通过代码设置参数。

6.3.3 性能优化和最佳实践

在AutoScaleTextView的实现和使用过程中,需要注意性能和内存管理的问题。例如,应当避免在高频的布局调整中造成不必要的性能开销,同时保证在调整过程中文本的清晰度不受影响。最佳实践包括使用硬件加速、避免频繁的布局更新和内存泄漏。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:在Android开发中,TextView组件需要根据内容自动调整字体大小以适应视图大小。这可以通过TextWatcher监听文本变化、使用Paint测量文本尺寸、设置LayoutParams确定TextView宽度、编写计算逻辑动态调整字体大小、设定字体大小范围限制以及性能优化等关键步骤来实现。此外,创建自定义AutoScaleTextView控件可简化实现过程。开发者可以通过查看示例项目AutoScaleTextViewDemo来学习这些技巧。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值