Android实现前后端查询

今天课堂测试实现了springboot与Android前端的模糊查询,并做了一定逻辑实现点击查询到的信息查看详情:
后台数据库:
entity:

package com.vivy.entity;

import java.util.Date;

public class Policy {
    private Long id;

    private String name;

    private String type;

    private String category;

    private String range;

    private String document;

    private String form;

    private String organ;

    private Date viadata;

    private Date pubdata;

    private Date perdata;

    private String field;

    private String theme;

    private String keyword;

    private String superior;

    private String precursor;

    private String succeed;

    private String state;

    private String text;

    private String pdf;

    private String redundancy;

    private String rank;

    private String policykey;

    private String newrank;

    private String year;

    private String newkey;

    private String secondtheme;

    private Integer allsum;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getCategory() {
        return category;
    }

    public void setCategory(String category) {
        this.category = category;
    }

    public String getRange() {
        return range;
    }

    public void setRange(String range) {
        this.range = range;
    }

    public String getDocument() {
        return document;
    }

    public void setDocument(String document) {
        this.document = document;
    }

    public String getForm() {
        return form;
    }

    public void setForm(String form) {
        this.form = form;
    }

    public String getOrgan() {
        return organ;
    }

    public void setOrgan(String organ) {
        this.organ = organ;
    }

    public Date getViadata() {
        return viadata;
    }

    public void setViadata(Date viadata) {
        this.viadata = viadata;
    }

    public Date getPubdata() {
        return pubdata;
    }

    public void setPubdata(Date pubdata) {
        this.pubdata = pubdata;
    }

    public Date getPerdata() {
        return perdata;
    }

    public void setPerdata(Date perdata) {
        this.perdata = perdata;
    }

    public String getField() {
        return field;
    }

    public void setField(String field) {
        this.field = field;
    }

    public String getTheme() {
        return theme;
    }

    public void setTheme(String theme) {
        this.theme = theme;
    }

    public String getKeyword() {
        return keyword;
    }

    public void setKeyword(String keyword) {
        this.keyword = keyword;
    }

    public String getSuperior() {
        return superior;
    }

    public void setSuperior(String superior) {
        this.superior = superior;
    }

    public String getPrecursor() {
        return precursor;
    }

    public void setPrecursor(String precursor) {
        this.precursor = precursor;
    }

    public String getSucceed() {
        return succeed;
    }

    public void setSucceed(String succeed) {
        this.succeed = succeed;
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }

    public String getPdf() {
        return pdf;
    }

    public void setPdf(String pdf) {
        this.pdf = pdf;
    }

    public String getRedundancy() {
        return redundancy;
    }

    public void setRedundancy(String redundancy) {
        this.redundancy = redundancy;
    }

    public String getRank() {
        return rank;
    }

    public void setRank(String rank) {
        this.rank = rank;
    }

    public String getPolicykey() {
        return policykey;
    }

    public void setPolicykey(String policykey) {
        this.policykey = policykey;
    }

    public String getNewrank() {
        return newrank;
    }

    public void setNewrank(String newrank) {
        this.newrank = newrank;
    }

    public String getYear() {
        return year;
    }

    public void setYear(String year) {
        this.year = year;
    }

    public String getNewkey() {
        return newkey;
    }

    public void setNewkey(String newkey) {
        this.newkey = newkey;
    }

    public String getSecondtheme() {
        return secondtheme;
    }

    public void setSecondtheme(String secondtheme) {
        this.secondtheme = secondtheme;
    }

    public Integer getAllsum() {
        return allsum;
    }

    public void setAllsum(Integer allsum) {
        this.allsum = allsum;
    }

    @Override
    public String toString() {
        return "Policy{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", type='" + type + '\'' +
                ", category='" + category + '\'' +
                ", range='" + range + '\'' +
                ", document='" + document + '\'' +
                ", form='" + form + '\'' +
                ", organ='" + organ + '\'' +
                ", viadata=" + viadata +
                ", pubdata=" + pubdata +
                ", perdata=" + perdata +
                ", field='" + field + '\'' +
                ", theme='" + theme + '\'' +
                ", keyword='" + keyword + '\'' +
                ", superior='" + superior + '\'' +
                ", precursor='" + precursor + '\'' +
                ", succeed='" + succeed + '\'' +
                ", state='" + state + '\'' +
                ", text='" + text + '\'' +
                ", pdf='" + pdf + '\'' +
                ", redundancy='" + redundancy + '\'' +
                ", rank='" + rank + '\'' +
                ", policykey='" + policykey + '\'' +
                ", newrank='" + newrank + '\'' +
                ", year='" + year + '\'' +
                ", newkey='" + newkey + '\'' +
                ", secondtheme='" + secondtheme + '\'' +
                ", allsum=" + allsum +
                '}';
    }
}

mapper:

package com.vivy.mapper;

import com.vivy.entity.Policy;
import java.util.List;

public interface PolicyMapper {
    List<Policy> selectAll(Policy policy);

}

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.vivy.mapper.PolicyMapper">

    <select id="selectAll" resultType="com.vivy.entity.Policy">
        select * from policy
        <where>
            <if test="name != null">
                name like concat('%', #{name}, '%')
            </if>
        </where>
    </select>

</mapper>

service:

package com.vivy.service;


import com.vivy.entity.Policy;
import com.vivy.entity.User;
import com.vivy.mapper.PolicyMapper;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class PolicyService {
    @Resource
    private PolicyMapper policyMapper;

    public List<Policy> selectAll(Policy policy) {
        return policyMapper.selectAll(policy);
    }
}

android前端:
entity:

package com.app.login.entity

import android.os.Parcel
import android.os.Parcelable

data class Policy(
    val id: Long? = null,
    val name: String? = null,
    val type: String? = null,
    val category: String? = null,
    val range: String? = null,
    val document: String? = null,
    val form: String? = null,
    val organ: String? = null,
    val viadata: String? = null, // 使用 String 类型代替 Date
    val pubdata: String? = null, // 使用 String 类型代替 Date
    val perdata: String? = null, // 使用 String 类型代替 Date
    val field: String? = null,
    val theme: String? = null,
    val keyword: String? = null,
    val superior: String? = null,
    val precursor: String? = null,
    val succeed: String? = null,
    val state: String? = null,
    val text: String? = null,
    val pdf: String? = null,
    val redundancy: String? = null,
    val rank: String? = null,
    val policykey: String? = null,
    val newrank: String? = null,
    val year: String? = null,
    val newkey: String? = null,
    val secondtheme: String? = null,
    val allsum: Int? = null
) : Parcelable {

    constructor(parcel: Parcel) : this(
        parcel.readValue(Long::class.java.classLoader) as? Long,
        parcel.readString(),
        parcel.readString(),
        parcel.readString(),
        parcel.readString(),
        parcel.readString(),
        parcel.readString(),
        parcel.readString(),
        parcel.readString(),
        parcel.readString(),
        parcel.readString(),
        parcel.readString(),
        parcel.readString(),
        parcel.readString(),
        parcel.readString(),
        parcel.readString(),
        parcel.readString(),
        parcel.readString(),
        parcel.readString(),
        parcel.readString(),
        parcel.readString(),
        parcel.readString(),
        parcel.readString(),
        (parcel.readValue(Int::class.java.classLoader) as? Int).toString()
    )

    override fun writeToParcel(parcel: Parcel, flags: Int) {
        parcel.writeValue(id)
        parcel.writeString(name)
        parcel.writeString(type)
        parcel.writeString(category)
        parcel.writeString(range)
        parcel.writeString(document)
        parcel.writeString(form)
        parcel.writeString(organ)
        parcel.writeString(viadata)
        parcel.writeString(pubdata)
        parcel.writeString(perdata)
        parcel.writeString(field)
        parcel.writeString(theme)
        parcel.writeString(keyword)
        parcel.writeString(superior)
        parcel.writeString(precursor)
        parcel.writeString(succeed)
        parcel.writeString(state)
        parcel.writeString(text)
        parcel.writeString(pdf)
        parcel.writeString(redundancy)
        parcel.writeString(rank)
        parcel.writeString(policykey)
        parcel.writeString(newrank)
        parcel.writeString(year)
        parcel.writeString(newkey)
        parcel.writeString(secondtheme)
        parcel.writeValue(allsum)
    }

    override fun describeContents(): Int {
        return 0
    }

    companion object CREATOR : Parcelable.Creator<Policy> {
        override fun createFromParcel(parcel: Parcel): Policy {
            return Policy(parcel)
        }

        override fun newArray(size: Int): Array<Policy?> {
            return arrayOfNulls(size)
        }
    }
}
package com.app.login.entity

// DataHolder.kt
object DataHolder {
    var policyList: List<Policy>? = null
}

Service:

package com.app.login.Service

import com.app.login.entity.Policy
import retrofit2.Call
import retrofit2.http.GET
import retrofit2.http.Query

interface PolicyService {

    /**
     * 查询所有政策(支持模糊匹配)
     * @param name 政策名称(可选,用于模糊匹配)
     * @return 包含政策列表的 Call 对象
     */
    @GET("/policy/selectAll")
    fun selectAll(@Query("name") name: String?): Call<List<Policy>>
}

activity:

package com.app.login

import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.widget.Button
import android.widget.EditText
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import com.app.login.R
import com.app.login.entity.Policy
import com.app.login.Service.PolicyService
import com.app.login.entity.DataHolder
import com.app.login.network.ServiceCreater
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response

class PolicyActivity : AppCompatActivity() {
    lateinit var searchButton: Button
    lateinit var policyNameInput: EditText

    @SuppressWarnings("MissingInflatedId")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContentView(R.layout.activity_policy) // 使用新的布局文件 activity_policy.xml
        searchButton = findViewById(R.id.searchButton)
        policyNameInput = findViewById(R.id.policyNameInput)

        // 创建 PolicyService 实例
        val policyService = ServiceCreater.create<PolicyService>()

        // 设置搜索按钮的点击事件
        searchButton.setOnClickListener {
            val policyName = policyNameInput.text.toString() // 获取用户输入的政策名称
            Log.d("PolicyActivity", "Searching for policy: $policyName")

            // 调用 PolicyService 的 selectAll 方法进行模糊查询
            // PolicyActivity.kt
            policyService.selectAll(policyName).enqueue(object : Callback<List<Policy>> {
                override fun onResponse(call: Call<List<Policy>>, response: Response<List<Policy>>) {
                    if (response.isSuccessful) {
                        val policyList = response.body()
                        if (policyList != null) {
                            Log.d("PolicyActivity", "Received data: ${policyList.size} policies")
                            // 将数据存储到单例类中
                            DataHolder.policyList = policyList
                            // 跳转到 PolicyListActivity
                            val intent = Intent(this@PolicyActivity, PolicyListActivity::class.java)
                            startActivity(intent)
                        } else {
                            Log.e("PolicyActivity", "Response body is null")
                        }
                    } else {
                        Log.e("PolicyActivity", "Request failed: ${response.code()}, ${response.message()}")
                    }
                }

                override fun onFailure(call: Call<List<Policy>>, t: Throwable) {
                    Log.e("PolicyActivity", "Request failed: ${t.message}", t)
                }
            })
        }
    }
}
package com.app.login

import android.os.Bundle
import android.util.Log
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import com.app.login.entity.Policy

class PolicyDetailActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_policy_detail)

        // 获取传递的 Policy 对象
        val policy = intent.getParcelableExtra<Policy>("policy")
        if (policy != null) {
            // 绑定数据到视图
            bindPolicyData(policy)
        } else {
            Log.e("PolicyDetailActivity", "No policy data received")
        }
    }

    /**
     * 将 Policy 数据绑定到布局中的 TextView
     */
    private fun bindPolicyData(policy: Policy) {
        // 政策名称
        findViewById<TextView>(R.id.policyName).text = policy.name ?: "N/A"

        // 政策类型
        findViewById<TextView>(R.id.policyType).text = "类型: ${policy.type ?: "N/A"}"

        // 发布日期
        findViewById<TextView>(R.id.policyPubDate).text = "发布日期: ${policy.pubdata ?: "N/A"}"

        // 政策内容
        findViewById<TextView>(R.id.policyText).text = "内容: ${policy.text ?: "N/A"}"

        // 政策分类
        findViewById<TextView>(R.id.policyCategory).text = "分类: ${policy.category ?: "N/A"}"

        // 施行范围
        findViewById<TextView>(R.id.policyRange).text = "施行范围: ${policy.range ?: "N/A"}"

        // 发文字号
        findViewById<TextView>(R.id.policyDocument).text = "发文字号: ${policy.document ?: "N/A"}"

        // 颁布形式
        findViewById<TextView>(R.id.policyForm).text = "颁布形式: ${policy.form ?: "N/A"}"

        // 制定机关
        findViewById<TextView>(R.id.policyOrgan).text = "制定机关: ${policy.organ ?: "N/A"}"

        // PDF 链接
        findViewById<TextView>(R.id.policyPdf).text = "PDF: ${policy.pdf ?: "N/A"}"

        // 冗余字段
        findViewById<TextView>(R.id.policyRedundancy).text = "冗余字段: ${policy.redundancy ?: "N/A"}"

        // 排名
        findViewById<TextView>(R.id.policyRank).text = "排名: ${policy.rank ?: "N/A"}"

        // 政策关键字
        findViewById<TextView>(R.id.policyKey).text = "关键字: ${policy.policykey ?: "N/A"}"

        // 新排名
        findViewById<TextView>(R.id.policyNewRank).text = "新排名: ${policy.newrank ?: "N/A"}"

        // 年份
        findViewById<TextView>(R.id.policyYear).text = "年份: ${policy.year ?: "N/A"}"

        // 新关键字
        findViewById<TextView>(R.id.policyNewKey).text = "新关键字: ${policy.newkey ?: "N/A"}"

        // 次主题
        findViewById<TextView>(R.id.policySecondTheme).text = "次主题: ${policy.secondtheme ?: "N/A"}"

        // 总数
        findViewById<TextView>(R.id.policyAllSum).text = "总数: ${policy.allsum ?: "N/A"}"
    }
}
package com.app.login

import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.app.login.adapter.PolicyAdapter
import com.app.login.entity.DataHolder
import com.app.login.entity.Policy

// PolicyListActivity.kt
class PolicyListActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_policy_list)
        Log.d("PolicyListActivity", "Activity created")

        // 从单例类中获取数据
        val policyList = DataHolder.policyList
        if (policyList != null) {
            Log.d("PolicyListActivity", "Received data: ${policyList.size} policies")
        } else {
            Log.e("PolicyListActivity", "No data received")
        }

        // 初始化 RecyclerView
        val policyRecyclerView = findViewById<RecyclerView>(R.id.policyRecyclerView)
        policyRecyclerView.layoutManager = LinearLayoutManager(this)
        val policyAdapter = PolicyAdapter(policyList ?: emptyList())
        policyRecyclerView.adapter = policyAdapter
    }
}

network:

package com.app.login.network

import com.google.gson.GsonBuilder
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory

object ServiceCreater {
    val gson = GsonBuilder().setLenient().create()
    //    换网修改IP地址
    private const val BASE_URL="http://192.168.215.43:9090/"
    private val retrofit=Retrofit.Builder()
        .baseUrl(BASE_URL)
        .addConverterFactory(GsonConverterFactory.create(gson))
        .build()
    fun <T> create(serviceClass: Class<T>): T= retrofit.create(serviceClass)
    inline fun<reified T> create(): T= create(T::class.java)
}

页面:

<?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="match_parent"
    android:layout_height="match_parent"
    tools:context=".PolicyActivity">

    <!-- 政策名称输入框 -->
    <EditText
        android:id="@+id/policyNameInput"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginEnd="16dp"
        android:hint="请输入政策名称"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintBottom_toTopOf="@+id/searchButton"
        app:layout_constraintVertical_bias="0.3" />

    <!-- 搜索按钮 -->
    <Button
        android:id="@+id/searchButton"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="16dp"
        android:text="搜索政策"
        app:layout_constraintTop_toBottomOf="@+id/policyNameInput"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="16dp">

    <!-- 政策名称 -->
    <TextView
        android:id="@+id/policyName"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="24sp"
        android:textStyle="bold"
        android:layout_marginBottom="16dp"/>

    <!-- 政策类型 -->
    <TextView
        android:id="@+id/policyType"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="18sp"
        android:layout_marginBottom="8dp"/>

    <!-- 发布日期 -->
    <TextView
        android:id="@+id/policyPubDate"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="18sp"
        android:layout_marginBottom="8dp"/>

    <!-- 政策内容 -->
    <TextView
        android:id="@+id/policyText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="16sp"
        android:layout_marginBottom="8dp"/>

    <!-- 其他字段 -->
    <TextView
        android:id="@+id/policyCategory"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="16sp"
        android:layout_marginBottom="8dp"/>

    <TextView
        android:id="@+id/policyRange"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="16sp"
        android:layout_marginBottom="8dp"/>

    <TextView
        android:id="@+id/policyDocument"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="16sp"
        android:layout_marginBottom="8dp"/>

    <TextView
        android:id="@+id/policyForm"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="16sp"
        android:layout_marginBottom="8dp"/>

    <TextView
        android:id="@+id/policyOrgan"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="16sp"
        android:layout_marginBottom="8dp"/>

    <TextView
        android:id="@+id/policyPdf"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="16sp"
        android:layout_marginBottom="8dp"/>

    <TextView
        android:id="@+id/policyRedundancy"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="16sp"
        android:layout_marginBottom="8dp"/>

    <TextView
        android:id="@+id/policyRank"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="16sp"
        android:layout_marginBottom="8dp"/>

    <TextView
        android:id="@+id/policyKey"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="16sp"
        android:layout_marginBottom="8dp"/>

    <TextView
        android:id="@+id/policyNewRank"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="16sp"
        android:layout_marginBottom="8dp"/>

    <TextView
        android:id="@+id/policyYear"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="16sp"
        android:layout_marginBottom="8dp"/>

    <TextView
        android:id="@+id/policyNewKey"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="16sp"
        android:layout_marginBottom="8dp"/>

    <TextView
        android:id="@+id/policySecondTheme"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="16sp"
        android:layout_marginBottom="8dp"/>

    <TextView
        android:id="@+id/policyAllSum"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="16sp"
        android:layout_marginBottom="8dp"/>

</LinearLayout>
<?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="match_parent"
    android:layout_height="match_parent"
    tools:context=".PolicyListActivity">

    <!-- 使用 RecyclerView 显示政策列表 -->
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/policyRecyclerView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginStart="16dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="16dp"
        android:layout_marginBottom="16dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        tools:listitem="@layout/item_policy" />

</androidx.constraintlayout.widget.ConstraintLayout>

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="16dp">

    <!-- 政策名称 -->
    <TextView
        android:id="@+id/policyName"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="政策名称"
        android:textSize="18sp"
        android:textStyle="bold" />

    <!-- 政策类型 -->
    <TextView
        android:id="@+id/policyType"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="政策类型"
        android:textSize="14sp"
        android:layout_marginTop="4dp" />

    <!-- 政策发布日期 -->
    <TextView
        android:id="@+id/policyPubDate"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="发布日期"
        android:textSize="14sp"
        android:layout_marginTop="4dp" />

</LinearLayout>
posted @ 2025-03-21 19:51  vivi_vimi  阅读(18)  评论(0)    收藏  举报