Android入门笔记(界面)

1 控件

Android 提供大量的 UI 控件,合理地使用这些控件,就可以编写出不错的界面。

在每个布局文件中都会使用 xmlns:android 这个属性来指定一个命名空间,这样就可以一直使用 android:idandroid:layout_width 等类似 android:attribute 的写法,那么在布局文件再指定一个 xmlns:app 指定一个新的命名空间,也就可以使用 app:attribute 的写法了。

所有控件都具有 android:layout_widthandroid:layout_height 两个属性,它们分别指定了控件的宽度和高度,可选值有三个:

  • match_parentfill_parent:让当前控件的大小与父布局大小一样
  • wrap_content:表示当前控件的大小能够刚好包含主里面的内容

1.1 TextView

  • 通过 android:text 指定 TextView 中的显示文本内容
  • 使用 android:gravity 指定文本的对齐方式,可选值有:
    • top
    • bottom
    • left
    • right
    • center_vertical
    • center_horizontal
    • center:等同于 center_vertical|center_horizontal
  • android:textSize:文字大小,单位使用 sp
  • android:textColor:文字颜色

1.2 Button

系统会对 Button 中的所有英文字母自动进行大写转换,可以使用以下属性禁用:

android:textAllcaps="false"

1.3 EditText

EditText 允许用户在控件中输入和编辑内容,其实就是 html 的 <input> 标签,而达到 placeholder 属性功能的就是使用 android:hint 属性,比如:

android:hint="输入用户密码"

如果 EditText 的高度设置 wrap_content,所以而随着输入的内容不断变长,EditText 也会不断地拉长,此时可以使用 android:maxLines 属性来解决这个问题,比如:

android:maxLines=2

就表示该 EditText 的高度最高为 2 行。
在代码中获取了对应的 View 对象(比如使用了 findViewById 方法),需要转换为 EditText 对象,它通过 getText() 方法可以获取对应的输入的数值。

1.4 ImageView

ImageView 用于在界面上展示图片,图片资源通常都是放置在 drawable 开头的目录下,它使用 android:src 的属性指定图片,如:

android:src="@drawable/img_1"

在代码中获取到对应的 ImageView 对象,可以使用 setImageResource 方法设置图片,如:

imageView.setImageResource(R.drawable.img_2);

1.5 ProgressBar

ProgressBar 用于在界面显示一个进度条,控件可以通过设置 android:visibility 来指定该控件是否可见,可选值有:

  • visible:默认值,控件可见
  • invisible:控件不可见,但依旧占据位置
  • gone:控件不可见,且不占据位置

以上数值代码可以通过 getVisibility()使用 setVisibility() 方法设置,分别为:

  • View.VISIBLE
  • View.INVISIBLE
  • View.GONE

默认的进度条时一个圆形进度,可以通过设置 style 属性将它指定为水平进度条,如:

style="?android:attr/progressBarStyleHorizontal"

指定水平进度条后,可通过 android:max 属性设置进度条一个最大值,而在代码中可以通过 setProgress 方法传入小于最大值的数值,表示完成进度。

1.6 AlertDialog

AlertDialog 用于显示对话框,这个对话框置顶在所有界面元素之上,能够屏蔽掉其他控件的交互能力
在代码中使用 AlertDialog.Builder 创建 AlertDialog 实例,然后可以为这个对象设置标题、内容、可否使用手机的 Back 键关闭对话框、绑定确定按钮事件、绑定取消按钮事件,设置完之后使用 show 方法将对话框显示出来。
如下:

// 创建 dialog 对象
AlertDialog.Builder dialog = new AlertDialog.Builder(MainActivity.this);
// 设置标题
dialog.setTitle("this is title");
// 设置消息
dialog.setMessage("this is Message");
// 设置是否可使用手机 Back 取消对话框
dialog.setCancelable(false);
// 绑定确定按钮事件
// 第一参数为:显示字符串
// 第二为:事件逻辑
dialog.setPositiveButton("确定", new DialogInterface.OnClickListener() {
    @Override
    public void onClick(DialogInterface dialog, int which) {
        Toast.makeText(MainActivity.this, "点击确定按钮", Toast.LENGTH_SHORT).show();
    }
});
// 绑定取消按钮事件
dialog.setNegativeButton("取消", new DialogInterface.OnClickListener() {
    @Override
    public void onClick(DialogInterface dialog, int which) {
        Toast.makeText(MainActivity.this, "点击取消按钮", Toast.LENGTH_LONG).show();
    }
});
// 最后要调用show
dialog.show();

1.7 ProgressDialog

ProgressDialogAlertDialog 类似,不同在于 ProgressDialog 会在对话框中显示一个进度条,表示当前操作比较耗时,用法如下:

ProgressDialog progressDialog = new ProgressDialog(MainActivity.this);
progressDialog.setMessage("加载中。。。");
// 设置了 Cancelable 为 false 之后,需要调用 dismiss 方法才能将对话框消失
progressDialog.setCancelable(false);
progressDialog.show();

2 布局

为了让控件能有条不紊地摆放在界面中,就需要使用到布局了。Android 有四种基本布局

2.1 线性布局 LinearLayout

线性布局就像名字所描述的一样,这个布局将它包含的控件在 线性方向 上依次排列。

2.1.1 android:orientation

通过设置 android:orientation 属性指定排列方向:

  • vertical:垂直方向
  • horizontal:水平方向

2.1.2 android:layout_gravity

通过设置控件的 android:layout-gravity 属性可以指定控件在布局形式,它的用法与 android:gravity 类似,不过要注意布局的排列方向,比如当排列方向是 horizontal 的时候,只有垂直方向上的对齐方式才生效,此时设置水平方向的 android:layout-gravity 不会生效。

2.1.3 android:layout_weight

android:layout_weight 属性允许使用比例的方式指定控件的大小,系统会先把 LinearLayout 下所有控件指定的 layout_weight 值相加,得到一个总值,然后每个控件所占大小的比例就是该控件的 layout_weight数值除以总值

注:由于每个控件都应该设置 android:layout_width 属性,所以在设置 android:layout_weight 的同时比较规范的写法就是设置 android:width 属性的值为 0

2.2 相对布局 ReletiveLayout

相对布局通过相对定位的方式让控件出现在布局的任何位置。

2.2.1 相对于父布局定位

  • android:layout_alignParentTop="true":位于父布局的顶部
  • android:layout_alignParentRight="true":位于父布局的右部
  • android:layout_alignParentBottom="true":位于父布局的底部
  • android:layout_alignParentLeft="true":位于父布局的左部
  • android:layout_centerInParent="true":位于父布局的中心

2.2.2 相对于控件定位

  • android:layout_above="@id/button3":位于 button3 控件的上方
  • android:layout_toRightOf="@id/button3":位于 button3 控件的右方
  • android:layout_below="@id/button3":位于 button3 控件的下方
  • android:layout_toLeftOf="@id/button3":位于 button3 控件的下方
  • android:layout_alignTop="@id/button3":与 button3 控件的上边缘对齐
  • android:layout_alignRight="@id/button3":与 button3 控件的右边缘对齐
  • android:layout_alignBottom="@id/button3":与 button3 控件的下边缘对齐
  • android:layout_alignLeft="@id/button3":与 button3 控件的左边缘对齐

2.3 帧布局 FrameLayout

在帧布局的所有控件都会默认摆放在布局的左上角,同时还可以使用 android:layout_gravity 属性指定控件在布局中的对齐方式

2.4 百分比布局

在线性布局中可以使用 android:layout_weight 属性达到按比例指定控件大小的功能,那么帧布局和相对定位布局就需要 PercentFrameLayoutPecentRelativeLayout

3 自定义控件

在这里插入图片描述
上图是控件和布局的继承结构,可以看到所有的控件都直接或间接地继承自 View,而布局直接或间接地继承自 ViewGroup,而 ViewGroup 又继承自 ViewViewGroup 可以包含很多子 View 和子 ViewGroup,这是一个用于放置控件和布局的控件。
View 是 Android 中最基本的一种 UI 组件,它可以在屏幕上绘制一个矩形区域,并能响应这个区域的各种事件,因此,我们使用的各种控件其实就是在 View 的基础上添加各自特有的功能。

3.1 引入布局

有些布局的重复度很高,就可以将它提取出来,作为公共布局引入需要的布局文件。
引入布局的做法很简单,只需编写一个布局文件,在需要引用的布局文件调用 <include> 标签即可,如:

<include layout="@layout/title" />

表示导入 title.xml 布局文件的布局,此时在代码中,也可以使用 findViewById 方法获取到 title.xml 布局文件中对应 id 的控件。

3.2 创建自定义控件

引入布局可以消除很多重复的代码,但它对应控件事件都需要在使用引用布局的活动中重新声明,如果事件都是重复,就可以创建自定义控件,比如创建一个标题栏,它有个返回键,用于返回上一个活动。

public class TitleLayout extends LinearLayout {

    public TitleLayout(final Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        // 通过 LayoutInflater 的 from 方法获取 LayoutInflater 对象
        // LayoutInflater 对象调用 inflate 方法可以加载一个布局文件
        // 第一个参数是控件35·布局文件Id
        // 第二个参数是给加载好的的布局再添一个父布局,这里用 this 指定 TitleLayout 作为父布局
        LayoutInflater.from(context).inflate(R.layout.title, this);

        Button button = (Button) findViewById(R.id.backBtn);
        button.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
            	// 通过 getContext 可以获取当前的上下文,可以强制转化为 Activity
            	((Activity) getContext()).finish();
            }
        });

    }
}

参考文章:《Android LayoutInflater简介和使用》

上面代码用于创建一个公共标题栏控件,LayoutInflaterfrom() 方法可以构建一个 LayoutInflater 对象,然后调用 inflate() 方法可以动态地加载一个布局文件,它接受两个参数,分别是:

  • 需要加载的布局 ID
  • 给加载好的布局再添上一个父布局

使用自定义控件和使用普通控件的方式基本一样,在添加自定义控件的时候需要 指明控件的完整类名,包名在这里是不可以忽略的。如:

<top.seiei.aboutactivity.component.TitleLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"></top.seiei.aboutactivity.component.TitleLayout>

此时在使用了自定义控件的控件活动类中无法使用 findViewById 的形式获取对应的自定义控件 View

4 滚动控件

4.1 ListView

不同于网页设置滚动只需设置样式 overflow:scroll,Android 设置滚动有点麻烦。

其中 ListView 控件可以达到竖直方向下的滚动效果,而一般的数组类型的数据无法直接传递给 ListView,它需要接受 适配器 类型的数据。
适配器(Adapter)在 Android 中是数据和视图(View)之间的一个桥梁,通过适配器以便于数据在 View 视图上显示,它的 getView 方法可以指定如何布局、显示数据

ListView 的基本用法是:

  • 在对应的布局文件添加 ListView 标签
  • 声明数据源
  • 初始化对应适配器
  • 对应的 ListView 对象绑定适配器

4.1.1 布局中 ListView 控件的创建

布局文件中创建 ListView 控件很简单,如下

<ListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"></ListView>

4.1.2 适配器的建立

Android 定义了很多适配器的实现类,这里采用最常用的 ArrayAdapter,它可以通过泛型来指定要适配的数据类型(即将导入数组的数据类型),然后通过构造函数把要适配的数据传入。
ArrayAdapter 的构造函数也有多个重载,这里也采用最常用的构造函数,它依次传入的参数是:

  • 当前上下文
  • 用于设置展示 ListView 子项的布局文件 id
  • 需要适配的数据(即数据源数组)

下面代码,就是一个继承 ArrayAdapter 的自定义适配器,同时重写了 getView 方法用于定制 ListView 的界面:

public class TestAboutAdapter extends ArrayAdapter<Map<String, String>> {

    // 记录展示子项布局文件id
    private int resourceId;

    public TestAboutAdapter(@NonNull Context context, int textViewResourceId, @NonNull List<Map<String, String>> objects) {
        super(context, textViewResourceId, objects);
        resourceId = textViewResourceId;
    }

    /**
     * getView 方法在每个子项被滚动到屏幕内时,被调用
     * @param position 用于获取数据源对应的子项数据
     * @param convertView 用于将之前加载好的布局进行缓存
     * @param parent 父布局
     * @return
     */
    @NonNull
    @Override
    public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent)
    {
        // 获取数组当前项的数据
        Map<String, String> item = getItem(position);
        // 获取 ListView 子项布局的 view
        // View 一旦有了父布局,就不能添加到 ListView 中,所以第三个参数要设置为 false
        View view = LayoutInflater.from(getContext()).inflate(resourceId, parent, false);
        TextView textView1 = (TextView) view.findViewById(R.id.title);
        TextView textView2 = (TextView) view.findViewById(R.id.value);
        textView1.setText("标题");
        textView2.setText(item.get("内容"));
        return view;
    }
}

4.1.3 绑定适配器

获取对应的 ListView 对象后,通过调用 setAdapter 方法传入对应的适配器即可完成绑定。

public class AboutListViewActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_about_list_view);

        // 准备数据
        List<Map<String, String>> data = new ArrayList<>();
        for (int i=0; i<100; i++) {
            Map<String, String> obj = new HashMap<>();
            obj.put("内容", i + "");
            data.add(obj);
        }
        
        // 创建适配器
        ArrayAdapter<Map<String, String>> adapter = new TestAboutAdapter(AboutListViewActivity.this, R.layout.listview_item, data);

        // 获取 ListView,导入 adapter 数据
        ListView listView = (ListView) findViewById(R.id.listView);
        listView.setAdapter(adapter);
    }
}

上面代码中配置适配器时,传入的 R.layout.listview_item 即是用于显示子项的布局文件 id

4.1.4 ListView 的点击事件

ListView 中有一个 setOnItemClickListenter 方法为 ListView 注册一个监听器,当用户点击 ListView 中的任何子项时,就会回调 onItemClick 方法,如:

listView.setOnItemClickListener(new AdapterView.OnItemClickListener(){
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        Map<String, String> obj = data.get(position);
        Toast.makeText(AboutListViewActivity.this, obj.get("value"), Toast.LENGTH_LONG).show();
    }
});

4.1.5 ListView 的优化

上述自定义适配器的代码中,getView 方法每次调用都会加载一次子项布局,当 ListView 快速滚动的时候,这就会成为性能的瓶颈。
此时可以使用 getView 方法中的第二个参数 converView 进行布局的缓存,代码修改后如下:

@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent)
{
    // 获取数组当前项的数据
    Map<String, String> item = getItem(position);

    View view;
    // 缓存布局
    if (convertView != null) {
        view = convertView;
    } else {
        // 获取 ListView 子项布局的 view
        // View 一旦有了父布局,就不能添加到 ListView 中,所以第三个参数要设置为 false
        view = LayoutInflater.from(getContext()).inflate(resourceId, parent, false);
    }
        
    TextView textView1 = (TextView) view.findViewById(R.id.title);
    TextView textView2 = (TextView) view.findViewById(R.id.value);
    textView1.setText("标题");
    textView2.setText(item.get("内容"));
    return view;
}

但此时代码也还有可以改进的地方,那就是尽管缓存了布局,但每次 getView 的调用还是会调用 findViewById 方法获取控件实例,此时就需要使用到 ViewsetTaggetTag 方法了。

参考文章:《Android View中setTag的二三事》

创建一个内部类用于存储 TextView 控件,并将该内部类通过 setTag 的形式传入到 convertView 中,然后在使用的时候通过 getTag 的形式获取出来即可,所以上面的代码就演变成:

public class TestAboutAdapter extends ArrayAdapter<Map<String, String>> {

    // 记录展示子项布局文件id
    private int resourceId;

    public TestAboutAdapter(@NonNull Context context, int textViewResourceId, @NonNull List<Map<String, String>> objects) {
        super(context, textViewResourceId, objects);
        resourceId = textViewResourceId;
    }

    /**
     * getView 方法在每个子项被滚动到屏幕内时,被调用
     * @param position
     * @param convertView
     * @param parent
     * @return
     */
    @NonNull
    @Override
    public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
        // 获取数组当前项的数据
        Map<String, String> item = getItem(position);

        View view;
        Msg msg;
        // 缓存布局
        if (convertView != null) {
            view = convertView;
            msg = (Msg) view.getTag();
        } else {
            // 获取 ListView 子项布局的 view
            // View 一旦有了父布局,就不能添加到 ListView 中,所以第三个参数要设置为 false
            view = LayoutInflater.from(getContext()).inflate(resourceId, parent, false);
            msg = new Msg();
            viewHolder.setTextView1((TextView) msg.findViewById(R.id.title));
            viewHolder.setTextView2((TextView) msg.findViewById(R.id.value));
            view.setTag(msg);
        }

        TextView textView1 = msg.getTextView1();
        TextView textView2 = msg.getTextView2();
        textView1.setText("标题");
        textView2.setText(item.get("内容"));
        return view;
    }

	// 用于存储信息的内部类
    class Msg {
        private TextView textView1;
        private TextView textView2;

        public TextView getTextView1() {
            return textView1;
        }

        public void setTextView1(TextView textView1) {
            this.textView1 = textView1;
        }

        public TextView getTextView2() {
            return textView2;
        }

        public void setTextView2(TextView textView2) {
            this.textView2 = textView2;
        }
    }
}

4.2 RecyclerView

ListView 控件只能实现数据纵向滚动的效果,并不能做到横向滚动,同时不优化的话,性能也非常差。
为此 Android 推出了 RecyclerView 控件。
RecyclerView 的基本用法:

  • 在对应的布局文件添加 RecyclerView 标签
  • 声明数据源
  • 设定 RecyclerView 的布局方式
  • 初始化对应适配器
  • 对应的 RecyclerView 对象绑定适配器

RecyclerView 控件属于新增的控件,因此想要使用,就需要在 build.gradle 中添加相关的依赖库:

implementation 'androidx.recyclerview:recyclerview:1.0.0'

4.2.1 布局中 RecyclerView 控件的创建

由于 RecyclerView 并不是内置在系统 SDK 中,所以需要把完整的包路径写出来,如:

<androidx.recyclerview.widget.RecyclerView
    android:id="@+id/recyler"
    android:layout_width="match_parent"
    android:layout_height="match_parent"></androidx.recyclerview.widget.RecyclerView>

4.2.2 适配器的建立

RecyclerView 的适配器需要继承自 RecyclerView.Adapter,要注意一下两点:

  • 它需要指定泛型,该泛型需要继承自 Recycler.ViewHolder 类(view 支架),其主要作用是存储自定义的子项布局文件里控件的实例,以便向其填充数据。这个 ViewHolder 类一般在类的内部声明即可。
  • 继承自 RecyclerView.Adapter 类需要重写三个方法,分别是:
    • onCreateViewHolder:实例化 ViewHolder 类的地方
    • onBindViewHolder:每个子项被滚动到屏幕内的时候执行,在这里,可以获取 ViewHolder 实例,并将数据设置到布局文件中
    • getItemCount:获取源数据的长度
  • 创建用于设置源数据的构造函数

一般的做法是。先设置 ViewHolder 内部类,然后创建构造方法,接着实现三个方法,例子代码如下:

public class TestAboutRecyclerViewAdapter extends RecyclerView.Adapter<TestAboutRecyclerViewAdapter.ViewHolder> {

    private List<Map<String, String>> objList;

	// 接受数据源的构造函数
    public TestAboutRecyclerViewAdapter(List<Map<String, String>> args) {
        objList = args;
    }

	// 重写 onCreateViewHolder 方法
    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.listview_item, parent, false);
        ViewHolder viewHolder = new ViewHolder(view);
        return viewHolder;
    }

	// 重写 onBindViewHolder
    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        Map<String, String> obj = objList.get(position);
        holder.textView1.setText("标题");
        holder.textView2.setText(obj.get("内容"));
    }

	// 获取数据源的长度
    @Override
    public int getItemCount() {
        return objList.size();
    }

	// viewHolder 内部类
    static class ViewHolder extends RecyclerView.ViewHolder {
        TextView textView1;
        TextView textView2;
        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            textView1 = itemView.findViewById(R.id.title);
            textView2 = itemView.findViewById(R.id.value);
        }
    }
}

4.2.3 绑定适配器

获取对应的 RecyclerView 对象后,通过调用 setAdapter 方法传入对应的适配器即可完成绑定。其中 LayoutManager 用于指定 RecyclerView 的布局方式,LinearLayoutManager 表示线性布局,同样的还有 实现网格布局的 GridLayoutManager 和实现瀑布流布局的 StaggerderGridLayoutManager

public class AboutRecyclerViewActivity extends AppCompatActivity {

    private List<Map<String, String>> data = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_about_recycler_view);
        // 获取 RecyclerView 控件
        RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerview);
        // LayoutManager 用于指定 RecyclerView 的布局方式,LinearLayoutManager 表示线性布局
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
        // 以下设置为水平方向滚动,注意此时子项的布局文件也做响应的修改
        // linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
        recyclerView.setLayoutManager(linearLayoutManager);

        // 准备数据
        data = new ArrayList<>();
        for (int i=0; i<100; i++) {
            Map<String, String> obj = new HashMap<>();
            obj.put("内容", i + "");
            data.add(obj);
        }

        // 创建适配器
        TestAboutRecyclerViewAdapter testAboutRecyclerViewAdapter = new TestAboutRecyclerViewAdapter(data);
        recyclerView.setAdapter(testAboutRecyclerViewAdapter);
    }
}

4.2.4 RecyclerView 的点击事件

RecyclerView 没有提供类似于 setOnItemClickListener 这样的注册监听器方法,而是需要我们给 子项 具体的 View 去注册点击事件,这里的绑定事件声明应写在 onCreateViewHolder 重写方法中。

@NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.listview_item, parent, false);
        // 绑定事件
        viewHolder.textView1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // ViewHolder 透过 getAdapterPosition 获取对应的数据源数组 索引
                int position = viewHolder.getAdapterPosition();
                Map<String, String> obj = objList.get(position);
                Toast.makeText(v.getContext(), obj.get("内容"), Toast.LENGTH_LONG).show();
            }
        });
        ViewHolder viewHolder = new ViewHolder(view);
        return viewHolder;
    }

4.2.5 刷新列表数据

有时候需要刷新滚动布局里的列表数据,这里的刷新逻辑应该写在 适配器 中,通过修改适配器内用于存储列表数据的变量,再调用 notifyDataSetChanged 方法达到刷新列表数据的效果,代码如下,在所属的活动中调用适配器的 refresh 方法即可:

class NewsContentAdapter extends RecyclerView.Adapter<NewsContentAdapter.ViewHolder> {

    private String content;

    NewsContentAdapter(String arg) {
        content = arg;
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.news_content_item, parent, false);
        ViewHolder viewHolder = new ViewHolder(view);
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        TextView newsContent = holder.newsContent;
        newsContent.setText(content);
    }

    @Override
    public int getItemCount() {
        return 1;
    }

    /**
     * 刷新数据
     * @param args
     */
    public void refresh(String args) {
        content = args;
        notifyDataSetChanged(); // 用于提醒数据刷新
    }
    
    class ViewHolder extends RecyclerView.ViewHolder {
        TextView newsContent;
        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            newsContent = itemView.findViewById(R.id.news_content);
        }
    }
}
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值