Flex的TextArea滚动到最下方

本文介绍了在Flex中实现消息框自动滚动至最新消息的方法。通过监听消息框的更新完成事件,确保界面更新后再进行滚动操作,从而解决了异步执行导致的问题。

在一些场合,比如接收到服务器方发来的一些消息需要显示的时候,通常会像一些即时通信工具一样把消息放在一个消息框里并把最后收到的消息放在消息框的底部。在Flex里面消息框首选用TextArea实现,于是有了下面的代码:

txtMessages.htmlText += "Some text goes here...";
txtMessages.verticalScrollPosition = txtMessages.maxVerticalScrollPosition;

但这段代码执行的时候却没有看到预期的效果。看到好多人都在找这个问题的答案,大家找来找去链来链去的好像都没有找到答案。其实这个问题是因为Action Script是异步的方式执行的,当第一句执行后界面还没有来得及更新第二句就紧接着执行了。解决问题的办法就是在更新完成后再执行滚动操作。

txtMessages.addEventListener(Event.UPDATE_COMPLETE, OnMessageBoxUpdateComplete);
......
private function OnMessageBoxUpdateComplete(event:Event):void {
  if (txtMessages.verticalScrollPosition < txtMessages.maxVerticalScrollPosition) {
     txtMessages.verticalScrollPosition = txtMessages.maxVerticalScrollPosition;
  }
}

<template> <view class="order-container"> <!-- 顶部标题栏 --> <view class="header"> <view class="back-icon-container" @tap="goBack"> <uni-icons type="back" size="24" color="#fff" class="back-icon" /> </view> <view class="title-container"> <text class="title">货物信息查询</text> </view> </view> <!-- 表单内容区 --> <scroll-view scroll-y class="form-content"> <!-- 基本信息卡片 --> <view class="form-card"> <view class="card-title">基本信息</view> <!-- 序号 --> <view class="form-item"> <text class="label">序号</text> <input class="input" v-model="queryParams.serialNumber" placeholder="请输入序号" placeholder-style="color: #c0c4cc;" /> </view> <!-- 物品名称 --> <view class="form-item"> <text class="label">物品名称</text> <input class="input" v-model="queryParams.itemName" placeholder="请输入物品名称" placeholder-style="color: #c0c4cc;" /> </view> <!-- 货物类型 --> <view class="form-item"> <text class="label">货物类型</text> <input type="text" class="input" placeholder="请输入货物类型" v-model="currentGoods.goodsType" placeholder-style="color: #c0c4cc;" > </view> <!-- 客户代码 --> <view class="form-item"> <text class="label">客户代码</text> <input class="input" v-model="queryParams.customerCode" placeholder="请输入客户代码" placeholder-style="color: #c0c4cc;" /> </view> </view> <!-- 规格参数卡片 --> <view class="form-card"> <view class="card-title">规格参数</view> <!-- 单号 --> <view class="form-item"> <text class="label">单号</text> <view class="input-group"> <input class="input" v-model="queryParams.orderNumber" placeholder="请输入或扫描单号" placeholder-style="color: #c0c4cc;" /> <view class="scan-btn-container"> <button class="scan-btn" @click="scanBarcode"> <uni-icons type="scan" size="18" color="#fff"></uni-icons> </button> </view> </view> </view> <!-- 数量范围 --> <view class="form-row"> <view class="form-item half"> <text class="label">数量(小)</text> <input class="input" type="number" v-model="queryParams.minQuantity" placeholder="小数量" placeholder-style="color: #c0c4cc;" /> </view> <view class="form-item half"> <text class="label">数量(大)</text> <input class="input" type="number" v-model="queryParams.maxQuantity" placeholder="大数量" placeholder-style="color: #c0c4cc;" /> </view> </view> <!-- 重量范围 --> <view class="form-row"> <view class="form-item half"> <text class="label">重量(小/kg)</text> <input class="input" type="number" v-model="queryParams.minWeight" placeholder="小重量" placeholder-style="color: #c0c4cc;" /> </view> <view class="form-item half"> <text class="label">重量(大/kg)</text> <input class="input" type="number" v-model="queryParams.maxWeight" placeholder="大重量" placeholder-style="color: #c0c4cc;" /> </view> </view> <!-- 尺寸 --> <view class="form-item"> <text class="label">尺寸(长×宽×高 cm)</text> <input class="input" v-model="queryParams.dimensions" placeholder="例如: 30×20×15" placeholder-style="color: #c0c4cc;" /> </view> </view> <!-- 时间信息卡片 --> <view class="form-card"> <view class="card-title">时间信息</view> <!-- 入库日期区间 --> <view class="form-item"> <text class="label">入库日期区间</text> <view class="form-row"> <view class="form-item half"> <picker mode="date" @change="(e) => queryParams.entryStartDate = e.detail.value"> <view class="picker"> {{ queryParams.entryStartDate || '开始日期' }} </view> </picker> </view> <view class="form-item half"> <picker mode="date" @change="(e) => queryParams.entryEndDate = e.detail.value"> <view class="picker"> {{ queryParams.entryEndDate || '结束日期' }} </view> </picker> </view> </view> </view> <!-- 出库日期区间 --> <view class="form-item"> <text class="label">出库日期区间</text> <view class="form-row"> <view class="form-item half"> <picker mode="date" @change="(e) => queryParams.exitStartDate = e.detail.value"> <view class="picker"> {{ queryParams.exitStartDate || '开始日期' }} </view> </picker> </view> <view class="form-item half"> <picker mode="date" @change="(e) => queryParams.exitEndDate = e.detail.value"> <view class="picker"> {{ queryParams.exitEndDate || '结束日期' }} </view> </picker> </view> </view> </view> <!-- 渠道 --> <view class="form-item"> <text class="label">渠道</text> <input class="input" type="number" v-model="queryParams.channel" placeholder="请输入渠道" placeholder-style="color: #c0c4cc;" /> </view> <!-- 备注 --> <view class="form-item"> <text class="label">备注</text> <textarea class="textarea" v-model="queryParams.remark" placeholder="请输入备注信息" placeholder-style="color: #c0c4cc;" auto-height /> </view> </view> <!-- 操作按钮 --> <view class="action-buttons"> <button class="reset-btn" @click="resetForm">重置</button> <button class="submit-btn" @click="submitQuery">查询信息</button> </view> </scroll-view> </view> </template> <script> export default { data() { return { queryParams: { serialNumber: '', itemName: '', goodsType: '', customerCode: '', orderNumber: '', minQuantity: '', maxQuantity: '', minWeight: '', maxWeight: '', dimensions: '', entryStartDate: '', // 入库开始日期 entryEndDate: '', // 入库结束日期 exitStartDate: '', // 出库开始日期 exitEndDate: '', // 出库结束日期 channel: '', remark: '' }, goodsTypes: ['普通货物', '易碎品', '危险品', '温控品', '大件物品'], channels: ['海运', '空运', '陆运', '快递', '自提'] } }, methods: { goBack() { uni.navigateBack(); }, // 扫码功能 scanBarcode() { // #ifdef APP-PLUS || MP-WEIXIN uni.scanCode({ onlyFromCamera: true, scanType: ['barCode', 'qrCode'], success: (res) => { if (res.result) { this.queryParams.orderNumber = res.result; uni.showToast({ title: '扫码成功', icon: 'success' }); } }, fail: (err) => { console.error('扫码失败:', err); uni.showToast({ title: '扫码失败', icon: 'none' }); } }); // #endif // #ifdef H5 uni.showToast({ title: '当前环境不支持扫码', icon: 'none' }); // #endif }, resetForm() { this.queryParams = { serialNumber: '', itemName: '', goodsType: '', customerCode: '', orderNumber: '', minQuantity: '', maxQuantity: '', minWeight: '', maxWeight: '', dimensions: '', entryStartDate: '', entryEndDate: '', exitStartDate: '', exitEndDate: '', channel: '', remark: '' }; uni.showToast({ title: '查询条件已重置', icon: 'success' }); }, submitQuery() { // 构建查询参数 const params = {...this.queryParams}; // 移除空值参数 Object.keys(params).forEach(key => { if (params[key] === '') { delete params[key]; } }); // 验证日期区间 if (params.entryStartDate && params.entryEndDate && params.entryStartDate > params.entryEndDate) { uni.showToast({ title: '入库开始日期不能晚于结束日期', icon: 'none' }); return; } if (params.exitStartDate && params.exitEndDate && params.exitStartDate > params.exitEndDate) { uni.showToast({ title: '出库开始日期不能晚于结束日期', icon: 'none' }); return; } uni.showLoading({ title: '查询中...' }); // 模拟查询请求 setTimeout(() => { uni.hideLoading(); // 这里实际应调用API接口 console.log('查询参数:', params); // 跳转到查询结果页 uni.navigateTo({ url: '/pages/tabbar/storageManagement/OrderList' }); }, 1500); } } } </script> <style> /* 全局适配样式 */ * { box-sizing: border-box; margin: 0; padding: 0; } .order-container { display: flex; flex-direction: column; height: 100vh; background-color: #f5f7fa; } /* 顶部标题栏 - 适配APP和小程序 */ .header { background: linear-gradient(135deg, #5e8fff, #6b7de9); display: flex; align-items: center; color: #fff; box-shadow: 0 2px 10px rgba(94, 143, 255, 0.3); position: relative; padding: 15px 20px; } /* 小程序顶部适配 */ /* #ifdef MP-WEIXIN */ .header { padding-top: 10px; padding-bottom: 10px; } /* #endif */ /* APP顶部适配 - 避开状态栏 */ /* #ifdef APP-PLUS */ .header { padding-top: var(--status-bar-height); padding-bottom: 15px; } /* #endif */ .back-icon-container { padding: 5px; margin-right: 10px; z-index: 10; } .title-container { position: absolute; left: 50%; transform: translateX(-50%); width: 100%; text-align: center; } .title { font-size: 18px; font-weight: bold; } /* 表单内容区 - 增加左右内边距 */ .form-content { flex: 1; padding: 15px; overflow-y: auto; /* 适配小程序滚动区域 */ box-sizing: border-box; } /* 表单卡片 - 增加左右外边距 */ .form-card { background: #fff; border-radius: 12px; box-shadow: 0 3px 10px rgba(0, 0, 0, 0.08); margin-bottom: 20px; padding: 20px; box-sizing: border-box; /* 适配不同平台 */ /* #ifdef MP-WEIXIN */ margin: 0 10px 20px; /* #endif */ /* #ifdef APP-PLUS */ margin: 0 15px 20px; /* #endif */ } .card-title { display: flex; align-items: center; margin-bottom: 20px; font-weight: bold; color: #333; font-size: 16px; padding-bottom: 10px; border-bottom: 1px solid #eee; } /* 表单项 */ .form-item { margin-bottom: 20px; } .label { display: block; margin-bottom: 8px; font-size: 14px; color: #666; } .input, .textarea, .picker { width: 100%; height: 44px; padding: 0 15px; border: 1px solid #dcdfe6; border-radius: 8px; font-size: 15px; background: #fff; line-height: 44px; box-sizing: border-box; } .textarea { height: auto; min-height: 100px; padding: 10px 15px; line-height: 1.5; } .input:focus, .textarea:focus { border-color: #5e8fff; outline: none; } /* 表单行布局 */ .form-row { display: flex; margin: 0 -8px; box-sizing: border-box; } .form-item.half { flex: 1; padding: 0 8px; box-sizing: border-box; } /* 输入组 */ .input-group { display: flex; box-sizing: border-box; } .input-group .input { flex: 1; border-top-right-radius: 0; border-bottom-right-radius: 0; } .scan-btn-container { display: flex; align-items: center; } .scan-btn { background: #5e8fff; color: white; border: none; padding: 0; width: 44px; height: 44px; border-radius: 0 8px 8px 0; display: flex; align-items: center; justify-content: center; } /* 操作按钮 */ .action-buttons { display: flex; margin-top: 20px; padding: 0 10px; box-sizing: border-box; /* 适配小程序按钮 */ /* #ifdef MP-WEIXIN */ padding-bottom: 20px; /* #endif */ } .reset-btn, .submit-btn { flex: 1; height: 48px; border-radius: 10px; font-size: 16px; font-weight: 500; display: flex; align-items: center; justify-content: center; margin: 0 10px; border: none; /* 适配小程序按钮 */ /* #ifdef MP-WEIXIN */ line-height: 48px; /* #endif */ } .reset-btn { background: #f0f2f5; color: #606266; } .submit-btn { background: linear-gradient(135deg, #5e8fff, #6b7de9); color: white; box-shadow: 0 4px 12px rgba(94, 143, 255, 0.4); } /* 平台适配 */ /* 小程序适配 - 优化输入框和按钮 */ /* #ifdef MP-WEIXIN */ .header { padding-top: 10px; padding-bottom: 10px; } .form-content { padding: 10px 15px; } .form-card { padding: 15px 20px; margin: 0 5px 15px; } .input, .textarea, .picker { height: 42px; font-size: 14px; line-height: 42px; } .scan-btn { width: 42px; height: 42px; } .action-buttons { margin-bottom: 10px; } /* #endif */ /* APP适配 - 优化顶部安全区域 */ /* #ifdef APP-PLUS */ .header { padding-top: var(--status-bar-height); padding-bottom: 15px; } .form-content { padding-top: 20px; } .form-card { margin: 0 20px 25px; } .input, .textarea, .picker { font-size: 16px; } /* #endif */ /* 平板适配 */ @media (min-width: 768px) { .form-content { padding: 20px; } .form-card { max-width: 600px; margin: 0 auto 20px; } .action-buttons { max-width: 600px; margin: 20px auto; } } /* 小屏幕设备适配 */ @media (max-width: 360px) { .form-content { padding: 10px; } .form-card { padding: 15px; } .input, .textarea, .picker { padding: 0 10px; font-size: 14px; } .scan-btn { width: 38px; height: 38px; } .form-row { flex-direction: column; margin: 0; } .form-item.half { padding: 0; margin-bottom: 15px; } /* 小屏幕上的按钮 */ .reset-btn, .submit-btn { height: 45px; font-size: 15px; } } </style> 添加入库和出库时间判定,如果选择了起始时间,结束时间就不能选择比起始时间更早的时间,加上提示,在选择框下方以红色标明
11-20
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值