Android UI 优化 [ 类别:Layout ] #3

单独将<merge />标签做个介绍,是因为它在优化UI结构时起到很重要的作用。目的是通过删减多余或者额外的层级,从而优化整个Android Layout的结构。

将通过一个例子来了解这个标签实际所产生的作用,这样可以更直观的了解<merge/>的用法。

建立一个简单的Layout,其中包含两个Views元素:ImageViewTextView默认状态下我们将这两个元素放在FrameLayout中。其效果是在主视图中全屏显示一张图片,之后将标题显示在图片上,并位于视图的下方。以下是xml代码:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent">

  <ImageView
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" 

    android:scaleType="center"
    android:src="@drawable/golden_gate" />

  <TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginBottom="20dip"
    android:layout_gravity="center_horizontal|bottom"

    android:padding="12dip"

    android:background="#AA000000"
    android:textColor="#ffffffff"

    android:text="Golden Gate" />

</FrameLayout>

应用上边的Layout运行的视图为:

layouttutorial_merge_01

启动 tools>hierarchyviewer.bat工具查看当前UI结构视图:

layouttutorial_merge_02

我们可以很明显的看到由红色线框所包含的结构出现了两个framelayout节点,很明显这两个完全意义相同的节点造成了资源浪费(这里可以提醒大家在开发工程中可以习惯性的通过hierarchyViewer查看当前UI资源的分配情况),那么如何才能解决这种问题呢(就当前例子是如何去掉多余的frameLayout节点)?这时候就要用到<merge />标签来处理类似的问题了。我们将上边xml代码中的framLayout替换成merge:

<!-- Easy AdSenser V2.37 --><!-- Post[count: 2] -->

<merge xmlns:android="http://schemas.android.com/apk/res/android">

  <ImageView
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" 

    android:scaleType="center"
    android:src="@drawable/golden_gate" />

  <TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginBottom="20dip"
    android:layout_gravity="center_horizontal|bottom"

    android:padding="12dip"

    android:background="#AA000000"
    android:textColor="#ffffffff"

    android:text="Golden Gate" />

</merge>

运行程序后在Emulator中显示的效果是一样的,可是通过hierarchyviewer查看的UI结构是有变化的,当初多余的FrameLayout节点被合并在一起了,或者可以理解为将merge标签中的子集直接加到Activity的FrameLayout跟节点下(这里需要提醒大家注意:所有的Activity视图的根节点都是frameLayout)。如果你所创建的Layout并不是用framLayout作为根节点(而是应用LinerLayout等定义root标签),就不能应用上边的例子通过merge来优化UI结构。

layouttutorial_merge_03

除了上边的例子外,meger还有另外一个用法

当应用Include或者ViewStub标签从外部导入xml结构时,可以将被导入的xml用merge作为根节点表示,这样当被嵌入父级结构中后可以很好的将它所包含的子集融合到父级结构中,而不会出现冗余的节点。

另外有两点需要特别注意:

  • <merge />只可以作为xml layout的根节点。
  • 当需要扩充的xml layout本身是由merge作为根节点的话,需要将被导入的xml layout置于 viewGroup中,同时需要设置attachToRoot为True。(更多说明请参见inflate()文档)

查看原文(Via Proxy)

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:id="@+id/show_pictures" android:layout_width="match_parent" android:layout_height="match_parent"/> </RelativeLayout> <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <androidx.viewpager.widget.ViewPager android:id="@+id/change_page" android:layout_width="wrap_content" android:layout_height="wrap_content"> </androidx.viewpager.widget.ViewPager> </RelativeLayout> <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <TextureView android:id="@+id/textureView" android:layout_width="match_parent" android:layout_height="match_parent" /> <ImageButton android:id="@+id/recording" android:layout_width="50dp" android:layout_height="50dp" android:src="@drawable/ic_launcher_background" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:layout_marginBottom="50dp" /> <ImageView android:id="@+id/image_show" android:layout_width="50dp" android:layout_height="50dp" android:layout_alignParentBottom="true" android:layout_marginBottom="50dp" android:layout_marginStart="50dp" /> <ImageButton android:id="@+id/change" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_marginEnd="50dp" android:layout_marginBottom="50dp" android:layout_alignParentEnd="true" /> <Chronometer android:id="@+id/timer" android:textColor="#f00" android:layout_width="match_parent" android:layout_height="wrap_content" android:format="%s" android:gravity="center" android:textSize="40sp" /> </RelativeLayout> <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="pemission" /> <TextureView android:id="@+id/textureView" android:layout_width="match_parent" android:layout_height="match_parent" /> <ImageButton android:id="@+id/takePicture" android:layout_width="50dp" android:layout_height="50dp" android:src="@drawable/ic_launcher_foreground" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:layout_marginBottom="50dp" /> <ImageView android:id="@+id/image_show" android:layout_width="50dp" android:layout_height="50dp" android:layout_alignParentBottom="true" android:layout_marginLeft="50dp" android:layout_marginBottom="50dp" /> <ImageButton android:id="@+id/change" android:layout_width="30dp" android:layout_height="30dp" android:layout_alignParentRight="true" android:layout_alignParentBottom="true" android:layout_marginRight="50dp" android:layout_marginBottom="50dp" android:src="@drawable/ic_launcher_foreground" /> </RelativeLayout> 可以分析
最新发布
11-27
将fragment_map.xml修改为<?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=".ui.map.MapFragment"> <TextView android:id="@+id/text_map" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginStart="8dp" android:layout_marginEnd="8dp" android:textAlignment="center" android:textSize="11sp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.5" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.85" /> <EditText android:id="@+id/map_input1" android:layout_width="0dp" android:layout_height="wrap_content" android:hint="请输入起点" android:minHeight="48dp" android:textSize="16sp" android:layout_marginLeft="10dp" android:layout_marginRight="110dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.1" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0" /> <EditText android:id="@+id/map_input2" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_marginRight="110dp" android:hint="请输入终点" android:minHeight="48dp" android:textSize="16sp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.008" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.07" /> <Button android:id="@+id/map_search" android:layout_width="wrap_content" android:layout_height="80dp" android:text="搜索" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.95" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.01" /> </androidx.constraintlayout.widget.ConstraintLayout> fragment_home.xml修改为<?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=".ui.home.HomeFragment"> <TextView android:id="@+id/text_home" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginStart="8dp" android:layout_marginEnd="8dp" android:textAlignment="center" android:textSize="11sp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.5" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.85" /> <ImageView android:layout_width="match_parent" android:layout_height="wrap_content" android:src="@drawable/bus" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.45"/> <EditText android:id="@+id/home_input" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_marginRight="110dp" android:hint="请输入需要查询的公交线路或站点" android:minHeight="48dp" android:textSize="16sp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.1" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.05" /> <Button android:id="@+id/home_search" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="搜索" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.95" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.05" /> </androidx.constraintlayout.widget.ConstraintLayout>
10-13
你给的代码本身是这样的:package com.example.bus; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.ProgressBar; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.amap.api.maps.AMap; import com.amap.api.maps.CameraUpdateFactory; import com.amap.api.maps.MapView; import com.amap.api.maps.UiSettings; import com.amap.api.maps.model.LatLng; import com.amap.api.maps.model.Marker; import com.amap.api.maps.model.MarkerOptions; import com.amap.api.services.core.LatLonPoint; import com.amap.api.services.core.PoiItem; import com.amap.api.services.poisearch.PoiResult; import com.amap.api.services.poisearch.PoiSearch; import java.util.ArrayList; import java.util.List; public class SearchResultActivity extends AppCompatActivity implements PoiSearch.OnPoiSearchListener { private static final String TAG = "SearchResultActivity"; private static final long SEARCH_DEBOUNCE_DELAY = 800; // 防抖时间 ms private EditText searchInput; private Button searchBtn, goToBtn; private RecyclerView resultListView; private ProgressBar progressBar; private List<PoiItem> poiList = new ArrayList<>(); private ResultAdapter adapter; private PoiSearch poiSearch; // 地图相关 private MapView mapView; private AMap aMap; private Marker selectedMarker; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_search_result); // 设置 ActionBar 返回按钮 if (getSupportActionBar() != null) { getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setTitle("搜索地点"); } initViews(); setupMap(savedInstanceState); setupSearch(); } private void initViews() { searchInput = findViewById(R.id.search_input); searchBtn = findViewById(R.id.search_btn); resultListView = findViewById(R.id.result_list); goToBtn = findViewById(R.id.btn_go_to); progressBar = findViewById(R.id.progress_bar); goToBtn.setEnabled(false); } private void setupMap(Bundle savedInstanceState) { mapView = findViewById(R.id.map_view); mapView.onCreate(savedInstanceState); if (aMap == null) { aMap = mapView.getMap(); UiSettings uiSettings = aMap.getUiSettings(); uiSettings.setZoomControlsEnabled(true); uiSettings.setCompassEnabled(true); uiSettings.setScrollGesturesEnabled(true); aMap.setOnMapClickListener(latLng -> { if (selectedMarker != null) selectedMarker.remove(); selectedMarker = aMap.addMarker(new MarkerOptions() .position(latLng) .title("选中位置")); goToBtn.setEnabled(true); }); // 默认定位到北京 aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(39.909186, 116.397411), 10f)); } } private void setupSearch() { String keyword = getIntent().getStringExtra("keyword"); if (keyword != null && !keyword.isEmpty()) { searchInput.setText(keyword); performSearch(keyword); } searchBtn.setOnClickListener(v -> { String text = searchInput.getText().toString().trim(); if (!text.isEmpty()) { performSearch(text); } else { Toast.makeText(this, "请输入关键词", Toast.LENGTH_SHORT).show(); } }); goToBtn.setOnClickListener(v -> { if (selectedMarker != null) { LatLng pos = selectedMarker.getPosition(); navigateToRoute(pos.latitude, pos.longitude, "地图选点"); } else if (!poiList.isEmpty()) { PoiItem item = poiList.get(0); LatLonPoint p = item.getLatLonPoint(); navigateToRoute(p.getLatitude(), p.getLongitude(), item.getTitle()); } else { Toast.makeText(this, "暂无目标位置", Toast.LENGTH_SHORT).show(); } }); } private void navigateToRoute(double lat, double lng, String title) { Intent intent = new Intent(this, RoutePlanActivity.class); intent.putExtra("start_mode", "my_location"); intent.putExtra("target_lat", lat); intent.putExtra("target_lng", lng); intent.putExtra("target_title", title); startActivity(intent); } private long lastSearchTime = 0; /** * 执行搜索(带防抖和取消旧请求机制) */ private void performSearch(String keyword) { long now = System.currentTimeMillis(); if (now - lastSearchTime < SEARCH_DEBOUNCE_DELAY) { Log.d(TAG, "防抖:忽略过于频繁的搜索请求"); return; } lastSearchTime = now; // 取消上一次搜索任务 if (poiSearch != null) { poiSearch.cancel(); poiSearch.setOnPoiSearchListener(null); // 解绑防止内存泄露 } // 显示加载状态 progressBar.setVisibility(View.VISIBLE); goToBtn.setEnabled(false); // 构建查询:关键词、类型(空=所有类别)、城市/范围 PoiSearch.Query query = new PoiSearch.Query(keyword, "", "全国"); // 关键修复:"15" → "" query.setPageSize(20); // 每页数量 query.setPageNum(0); // 第一页 try { poiSearch = new PoiSearch(this, query); poiSearch.setOnPoiSearchListener(this); poiSearch.searchPOIAsyn(); // 异步执行 } catch (Exception e) { Log.e(TAG, "启动搜索失败", e); progressBar.setVisibility(View.GONE); Toast.makeText(this, "搜索启动失败,请检查网络或高德Key", Toast.LENGTH_LONG).show(); } } @Override public void onPoiSearched(PoiResult result, int rCode) { progressBar.setVisibility(View.GONE); // 隐藏加载条 if (rCode == 1000) { if (result != null && result.getPois() != null) { List<PoiItem> pois = result.getPois(); poiList.clear(); poiList.addAll(pois); // 更新UI if (adapter == null) { adapter = new ResultAdapter(poiList, item -> { if (selectedMarker != null) { selectedMarker.remove(); } LatLng latLng = new LatLng(item.getLatLonPoint().getLatitude(), item.getLatLonPoint().getLongitude()); selectedMarker = aMap.addMarker(new MarkerOptions() .position(latLng) .title(item.getTitle())); aMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 14f)); goToBtn.setEnabled(true); }); resultListView.setLayoutManager(new LinearLayoutManager(this)); resultListView.setAdapter(adapter); } else { adapter.notifyDataSetChanged(); } // 提示空结果 if (pois.isEmpty()) { Toast.makeText(this, "未找到匹配的结果", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(this, "找到 " + pois.size() + " 个结果", Toast.LENGTH_SHORT).show(); } goToBtn.setEnabled(!pois.isEmpty()); } else { Toast.makeText(this, "搜索结果为空", Toast.LENGTH_SHORT).show(); } } else { String errorMsg; switch (rCode) { case 17: errorMsg = "高德Key校验失败,请检查AndroidManifest.xml中的key或SHA1绑定"; break; case 27: case 28: errorMsg = "网络连接失败,请检查网络"; break; default: errorMsg = "搜索失败,错误码: " + rCode; break; } Log.e(TAG, "POI搜索错误码: " + rCode); Toast.makeText(this, errorMsg, Toast.LENGTH_LONG).show(); } } @Override public void onPoiItemSearched(PoiItem item, int rCode) { // 单个POI详情回调,此处不需要使用 } // 生命周期方法 @Override protected void onResume() { super.onResume(); mapView.onResume(); } @Override protected void onPause() { super.onPause(); mapView.onPause(); } @Override protected void onDestroy() { super.onDestroy(); mapView.onDestroy(); if (poiSearch != null) { poiSearch.setOnPoiSearchListener(null); // 解绑监听器 } if (selectedMarker != null) { selectedMarker.remove(); } } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); mapView.onSaveInstanceState(outState); } @Override public boolean onSupportNavigateUp() { onBackPressed(); return true; } } 我暂时先用这个,如果还有问题我再让你改。现在就是我的activity_search_result.xml代码如下:<?xml version="1.0" encoding="utf-8"?> <androidx.core.widget.NestedScrollView 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" android:fillViewport="true" android:fitsSystemWindows="true" android:layout_marginTop="?attr/actionBarSize"> <!-- 根布局:ConstraintLayout 必须 match_parent 高度才能被 NestedScrollView 正确测量 --> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent"> <!-- 🔵 垂直指南线:5%、95% --> <androidx.constraintlayout.widget.Guideline android:id="@+id/guideline_05" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" app:layout_constraintGuide_percent="0.05" /> <androidx.constraintlayout.widget.Guideline android:id="@+id/guideline_15" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" app:layout_constraintGuide_percent="0.15" /> <androidx.constraintlayout.widget.Guideline android:id="@+id/guideline_95" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" app:layout_constraintGuide_percent="0.95" /> <!-- 🔍 输入框 --> <EditText android:id="@+id/search_input" android:layout_width="0dp" android:layout_height="wrap_content" android:hint="请输入需要查询的公交线路或站点" android:textColorHint="#777777" android:textColor="@color/black" android:background="@drawable/rounded_edittext" android:minHeight="48dp" android:textSize="16sp" android:padding="12dp" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toStartOf="@id/search_btn" app:layout_constraintHorizontal_chainStyle="packed" app:layout_constraintTop_toTopOf="@id/guideline_05" app:layout_constraintBottom_toTopOf="@id/space_after_search" android:layout_marginStart="16dp" android:layout_marginEnd="8dp" /> <!-- 🔎 搜索按钮 --> <Button android:id="@+id/search_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="搜索" app:layout_constraintTop_toTopOf="@id/guideline_05" app:layout_constraintBottom_toTopOf="@id/space_after_search" app:layout_constraintStart_toEndOf="@id/search_input" app:layout_constraintEnd_toEndOf="parent" android:layout_marginEnd="16dp" /> <!-- ⬛ Space: 搜索栏下方留出 5% 屏幕高度作为间隔 --> <Space android:id="@+id/space_after_search" android:layout_width="match_parent" android:layout_height="0dp" app:layout_constraintTop_toBottomOf="@id/guideline_15" app:layout_constraintBottom_toTopOf="@id/map_view" app:layout_constraintHeight_percent="0.05" /> <!-- 🗺️ 地图视图:占页面 40% 高度 --> <com.amap.api.maps.MapView android:id="@+id/map_view" android:layout_width="0dp" android:layout_height="0dp" app:layout_constraintTop_toBottomOf="@id/space_after_search" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHeight_percent="0.4" /> <!-- ⬛ Space: 地图到列表之间的空白 --> <Space android:id="@+id/space_after_map" android:layout_width="match_parent" android:layout_height="0dp" app:layout_constraintTop_toBottomOf="@id/map_view" app:layout_constraintBottom_toTopOf="@id/result_list" app:layout_constraintHeight_percent="0.03" /> <!-- 🔽 RecyclerView:结果列表,占据剩余空间 --> <androidx.recyclerview.widget.RecyclerView android:id="@+id/result_list" android:layout_width="0dp" android:layout_height="wrap_content" android:textColorHint="#777777" android:textColor="@color/black" android:background="@drawable/rounded_edittext" app:layout_constraintTop_toBottomOf="@id/space_after_map" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintBottom_toTopOf="@id/btn_go_to" android:layout_marginHorizontal="16dp" /> <!-- “到这去”按钮 --> <Button android:id="@+id/btn_go_to" android:layout_width="0dp" android:layout_height="wrap_content" android:text="到这去" android:layout_margin="16dp" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintBottom_toBottomOf="@id/guideline_95" /> </androidx.constraintlayout.widget.ConstraintLayout> </androidx.core.widget.NestedScrollView> 你让我添加 <ProgressBar android:id="@+id/progress_bar" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:visibility="gone" />我应该加到哪个位置呢,我希望原本的界面不改变
11-08
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值