spinner添加分割线和改变右侧箭头

本文介绍如何为Android中的Spinner组件添加分割线及更改下拉箭头样式。通过定义自定义样式和使用Drawable资源,可以轻松实现所需的视觉效果。

spinner添加分割线和改变右侧箭头

默认的spinner是没有分割线的,时间仓促就直接进入主题了。

1.首先说添加分割线
第一步:在style.xml中定义一个style ,应该不用解释每个的意思吧,看单词也能理解。
 <style name="XSpinnerStyle" parent="android:Widget.ListView.DropDown">
        <!-- 分隔线颜色 -->
        <item name="android:divider">#DFDFDF</item>
        <item name="android:dividerHeight">1dp</item>
    </style>
第二步:在AppTheme中吧自定义的style添加进来,注意是android:dropDownListViewStyle
<!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <item name="android:dropDownListViewStyle">@style/XSpinnerStyle</item>

    </style>

只需要两部就可以为spinner添加分割线,是不是很简单呢?

2.改变箭头
1.自定义style
<style name="spinner_style" parent="Base.Widget.AppCompat.Spinner">
        <item name="android:background">@drawable/spinner_raow_selector</item>
    </style>
2.创建spinner_raow_selector,代码如下:
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:state_window_focused="true">
        <layer-list>
            <item>
                <shape>
                    <padding android:right="10dp"/>
                </shape>
            </item>
            <item>
                <bitmap android:gravity="center_vertical|right" android:src="@drawable/ic_pack_up" />
            </item>
        </layer-list>
    </item>

    <item>
        <layer-list>
            <item>
                <shape>
                    <padding android:right="10dp"/>
                </shape>
            </item>
            <item>
                <bitmap android:gravity="center_vertical|right" android:src="@drawable/ic_pack_down" />
            </item>
        </layer-list>
    </item>
</selector>
3.在spinner中引用
 <android.support.v7.widget.AppCompatSpinner
                android:id="@+id/AppCompatSpinner"
                style="@style/spinner_style"//这里
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:dropDownVerticalOffset="40dp"
                android:spinnerMode="dropdown"
                android:textColorHint="#000000"
                android:textSize="12sp" />

oK啦,两张图样式如下
这里写图片描述

<template> <view class="distribution-list"> <!-- 导航栏 --> <wd-navbar :showBack="true" title="业绩明细" background="#ffffff" border-bottom="true" title-style="font-weight: 600; color: #303133;" /> <!-- 数据统计卡片 --> <view class="stats-card" v-if="stats.totalUsers > 0"> <view class="stat-item"> <view class="stat-value">{{ stats.totalUsers }}</view> <view class="stat-label">总用户数</view> </view> <view class="stat-item"> <view class="stat-value">{{ stats.totalAmount }}</view> <view class="stat-label">累计业绩(元)</view> </view> <view class="stat-item"> <view class="stat-value">{{ stats.averageAmount }}</view> <view class="stat-label">平均业绩(元)</view> </view> </view> <!-- 列表内容 --> <scroll-view class="list-container" scroll-y @scrolltolower="onReachBottom" @refresherpulling="onPulling" @refresherrefresh="onRefresh" refresher-enabled="true" refresher-threshold="80" refresher-default-style="black" > <!-- 列表项 --> <view class="list-item" v-for="(user, index) in list" :key="user.myselfId || index" @click="handleItemClick(user)" > <view class="user-info"> <!-- 用户头像基本信息 --> <view class="user-avatar-basic"> <view class="user-avatar"> <uni-icons type="person" size="60" color="#409eff" class="avatar-icon" /> </view> <view class="user-basic"> <view class="user-main"> <view class="user-nickname"> {{ user.nickname || '未知用户' }} <view class="user-level" :class="getLevelClass(user.level)"> {{ getLevelText(user.level) }} </view> </view> <view class="user-id">ID: {{ user.myselfId || '未知' }}</view> </view> </view> </view> <!-- 用户业绩箭头 --> <view class="user-performance"> <view class="performance-amount"> ¥{{ user.totalAmount ? parseFloat(user.totalAmount).toFixed(2) : '0.00' }} </view> <uni-icons type="right" size="28" color="#ccc" /> </view> </view> <!-- 用户电话记录数 --> <view class="user-extra"> <view class="user-phone"> {{ formatPhone(user.mobile) }} </view> <view class="record-count"> 业绩记录: {{ user.recordCount || 0 }} 条 </view> </view> <!-- 分割线 --> <view class="divider" v-if="index !== list.length - 1"></view> </view> <!-- 空状态 --> <view v-if="list.length === 0 && !isLoading" class="empty-state"> <uni-icons type="contact" size="80" color="#ccc"></uni-icons> <view class="empty-text">暂无分销用户</view> <view class="empty-desc">邀请用户加入分销计划,业绩数据将展示在这里</view> </view> <!-- 加载状态 --> <view v-if="isLoading && list.length > 0" class="loading-more"> <uni-icons type="spinner" size="24" color="#409eff" animation="spin" /> <text class="loading-text">加载更多...</text> </view> </scroll-view> <!-- 初始加载状态 --> <view v-if="isLoading && list.length === 0" class="initial-loading"> <uni-icons type="spinner" size="40" color="#409eff" animation="spin" /> <view class="loading-text">加载中...</view> </view> </view> </template> <script lang="ts" setup> import { getPageUserList, getPageUserListByparentId } from '@/api/business/mobile/appApi' import { getPageUsers } from '@/api/business/mobile/homeApi' import { ref, computed } from 'vue' import { onLoad, onReachBottom as onReachBottomUni } from '@dcloudio/uni-app' // 响应式数据 const list = ref([]) const page = ref(1) const limit = ref(20) // 调整为更合理的分页大小 const isLoading = ref(true) const isRefreshing = ref(false) const pageUsers = ref({}) const hasMore = ref(true) // 统计数据 const stats = ref({ totalUsers: 0, totalAmount: '0.00', averageAmount: '0.00' }) // 格式化电话号码(中间四位用*代替) const formatPhone = (phone) => { if (!phone) return '未绑定手机'; return phone.replace(/(\d{3})(\d{4})(\d{4})/, '$1****$3'); }; // 列表项点击事件处理函数 const handleItemClick = (user) => { if (!user.myselfId) { uni.showToast({ title: '用户ID不存在', icon: 'none' }) return } // 跳转到业绩详情页,并携带myselfId参数 uni.navigateTo({ url: `/pages/center/distributionDetail?targetUserId=${user.myselfId}` }) } // 获取用户等级文本 const getLevelText = (level) => { const levelMap = { 0: '一级', 1: '二级', 2: '三级', default: '普通' } return levelMap[level] || levelMap.default } // 获取用户等级样式 const getLevelClass = (level) => { const classMap = { 0: 'level-primary', 1: 'level-secondary', 2: 'level-tertiary', default: 'level-default' } return classMap[level] || classMap.default } // 更新统计数据 const updateStats = () => { if (list.value.length === 0) { stats.value = { totalUsers: 0, totalAmount: '0.00', averageAmount: '0.00' } return } // 计算总用户数 stats.value.totalUsers = list.value.length // 计算总业绩 const totalAmount = list.value.reduce((sum, user) => { return sum + (parseFloat(user.totalAmount) || 0) }, 0) stats.value.totalAmount = totalAmount.toFixed(2) // 计算平均业绩 stats.value.averageAmount = (totalAmount / list.value.length).toFixed(2) } // 获取列表数据 const getList = async (init: boolean) => { // 如果正在加载或没有更多数据,直接返回 if (isLoading.value && !init) return if (!hasMore.value && !init) return if (init) { page.value = 1 list.value = [] hasMore.value = true } isLoading.value = true try { const userId = uni.getStorageSync('userId') if (!userId) { uni.showToast({ title: '用户信息获取失败', icon: 'none' }) isLoading.value = false return } // 第一步:获取父级用户列表 const res = await getPageUserListByparentId(page.value, limit.value, userId) const resList = res[1] || {} if (!resList.records || resList.records.length === 0) { if (init) list.value = [] hasMore.value = false isLoading.value = false updateStats() return } // 第二步:获取用户详情 const currentMyselfId = resList.records[0]?.myselfId if (!currentMyselfId) { hasMore.value = false isLoading.value = false updateStats() return } const res2 = await getPageUserList(page.value, limit.value, currentMyselfId) const resList2 = res2[1] || {} if (resList2.records && resList2.records.length > 0) { // 合并数据并去重 const newRecords = resList2.records.filter(newItem => !list.value.some(existingItem => existingItem.myselfId === newItem.myselfId) ) list.value = init ? newRecords : [...list.value, ...newRecords] // 判断是否还有更多数据 hasMore.value = resList2.current < resList2.pages if (hasMore.value) { page.value++ } } else { hasMore.value = false } // 更新统计数据 updateStats() } catch (err) { console.error('获取数据失败', err) uni.showToast({ title: '数据加载失败', icon: 'none' }) } finally { isLoading.value = false isRefreshing.value = false } }; // 页面加载时初始化 onLoad(() => { const userId = uni.getStorageSync('userId') if (userId) { getPageUsers(userId) .then(res => { pageUsers.value = res[1]?.records?.[0] || {} getList(true) }) .catch(err => { console.error('获取用户信息失败', err) getList(true) // 即使失败也尝试加载列表 }) } else { uni.showToast({ title: '请先登录', icon: 'none' }) isLoading.value = false } }) // 下拉刷新相关方法 const onPulling = () => { // 下拉过程中可以添加动画效果 } const onRefresh = () => { if (isRefreshing.value) return isRefreshing.value = true // 延迟一点时间,让用户看到刷新效果 setTimeout(() => { getList(true) }, 500) } // 触底加载更多 const onReachBottom = () => { if (!isLoading.value && hasMore.value) { getList(false) } } </script> <style scoped> .distribution-list { min-height: 100vh; background-color: #f7f8fa; } /* 统计卡片样式 */ .stats-card { background-color: #ffffff; margin: 20rpx 30rpx; border-radius: 16rpx; padding: 30rpx; display: flex; justify-content: space-around; box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05); } .stat-item { display: flex; flex-direction: column; align-items: center; flex: 1; } .stat-value { font-size: 36rpx; font-weight: 600; color: #303133; margin-bottom: 10rpx; } .stat-label { font-size: 24rpx; color: #909399; } /* 列表容器 */ .list-container { height: calc(100vh - 340rpx); padding-bottom: 20rpx; } /* 列表项样式 */ .list-item { background-color: #ffffff; margin: 0 30rpx 20rpx; border-radius: 16rpx; padding: 25rpx 30rpx; cursor: pointer; transition: background-color 0.2s; box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.03); } .list-item:active { background-color: #f5f5f5; } .user-info { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20rpx; } .user-avatar-basic { display: flex; align-items: center; } .user-avatar { width: 80rpx; height: 80rpx; border-radius: 50%; background-color: #e6f7ff; display: flex; align-items: center; justify-content: center; margin-right: 20rpx; } .user-basic { display: flex; align-items: center; } .user-main { display: flex; flex-direction: column; } .user-nickname { font-size: 32rpx; color: #333; margin-bottom: 5rpx; display: flex; align-items: center; } .user-level { font-size: 22rpx; padding: 2rpx 12rpx; border-radius: 12rpx; margin-left: 12rpx; height: 30rpx; line-height: 30rpx; } .level-primary { background-color: #e6f7ff; color: #1890ff; } .level-secondary { background-color: #fff7e6; color: #faad14; } .level-tertiary { background-color: #f6ffed; color: #52c41a; } .level-default { background-color: #f5f5f5; color: #8c8c8c; } .user-id { font-size: 26rpx; color: #888; } .user-performance { display: flex; align-items: center; } .performance-amount { font-size: 30rpx; color: #e63946; font-weight: 500; margin-right: 10rpx; } .user-extra { display: flex; justify-content: space-between; align-items: center; } .user-phone { font-size: 28rpx; color: #555; } .record-count { font-size: 26rpx; color: #888; } /* 分割线 */ .divider { height: 1px; background-color: #f5f5f5; margin-top: 25rpx; } /* 空状态样式 */ .empty-state { display: flex; flex-direction: column; align-items: center; justify-content: center; padding-top: 200rpx; gap: 20rpx; } .empty-text { font-size: 32rpx; color: #888; font-weight: 500; } .empty-desc { font-size: 26rpx; color: #aaa; margin-top: 10rpx; } /* 加载状态样式 */ .initial-loading { display: flex; flex-direction: column; align-items: center; justify-content: center; height: calc(100vh - 200rpx); gap: 20rpx; } .loading-more { display: flex; align-items: center; justify-content: center; padding: 30rpx 0; gap: 10rpx; } .loading-text { font-size: 28rpx; color: #888; } </style> 只展示getPageUserListByparentId查询出来的信息,展示amountappId
最新发布
09-16
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值