微信小程序设置超出行显示 ... 与展开更多按钮

微信小程序设置超出行显示 ... 与展开更多按钮

问题描述

业务开发中会有一些场景,超出一行显示 … 与展开更多按钮,展开更多按钮能够切换显示一行仍是所有内容,少于一行正常显示;web

解决方案

分析下问题: 通常这种需求很差实现的缘由是,在移动端,每行显示的字数的有可能在不一样机型会有差别,因此就使开发者没法知道这些内容是否超过一行,是否该显示展开更多按钮。小程序

绕开上述缘由,曲线救国,咱们在每次页面渲染完成以后再去获取承载内容的元素宽度,和承载内容的元素的外层父级盒子的宽度相对比,若是宽度之差小于半个字体的大小(是为了防止一点偏差),则显示 … 的样式,显示展开更多按钮,相反,则隐藏更多按钮。微信小程序

最终效果以下:微信

image

主要代码以下app

<view class="coupon-remark-wrapper">
    <!--id = toggle-warpper 为包裹内容的父级元素-->
    <view class="coupon-remark-content" id="toggle-wrapper">
        <!--id = toggle-content 为内容的容器,控制显示所有内容仍是显示超出一行... -->
        <view id="toggle-content" class="{{toggleParams.toggleFlag === 1?'ellipsis':''}}" hidden="{{toggleParams.toggleFlag === 0}}">
            {{couponData.limitRemark}}
        </view>
        <!--class = toggle-icon 为展开更多按钮-->
        <image class="toggle-icon {{toggleParams.toggleFlag === 1?'hide':'show'}}" wx:if="{{toggleParams.toggleShow}}" bindtap="toggleHandler" src="https://img.dmallcdn.com//dshop/201904/b1c5af14-f29a-494c-9e3b-899f1a2cf218"></image>
    </view>
</view>
.coupon-remark-wrapper {
  padding: 20rpx;
  padding-top: 33rpx;
  padding-right: 60rpx;
  margin-top: -20rpx;
  line-height: 1;
  box-sizing: border-box;
  color: #666666;
  background-color: #fff;
  position: relative;
  z-index: 1;
}
.coupon-remark-content {
  width: 100%;
  view {
    font-size: 22rpx;
    line-height: 1.5;
    word-break: break-all;
    display: inline-block;
    max-width: 100%;
  }
  .ellipsis{
    text-overflow:ellipsis;
    white-space: nowrap;
    overflow: hidden;
  }
  .toggle-icon {
    width: 30rpx;
    height: 30rpx;
    position: absolute;
    right: 20rpx;
    top: 35rpx;
    transition: all 0.2s linear;
    &.show {
      transform: rotate(180deg);
    }
  }
}
const couponItemBehavior = Behavior({
	data: {
		// 控制说明文案收起/展开
		toggleParams: {
			toggleFlag: 1, //0收起1展开
			toggleShow: false, //默认不显示toggleIcon
		},
	},
	ready() {
		this._checkRemarkToggle();
	},
	methods: {
		// 获取指定元素实际宽度
		_getElementWidth(id = "") {
			let _query = this.createSelectorQuery();
			return new Promise(resolve => {
				_query.select(id).fields({
					size: true,
				}, (res) => {
					resolve(res.width)
					_query = null;
				}).exec();
			});
		},

		// 说明文字收起/隐藏事件
		toggleHandler() {
			const {toggleFlag} = this.data.toggleParams;

			this.setData({
				toggleParams: {
					toggleFlag: toggleFlag === 0 ? 1 : 0,
					toggleShow: true
				}
			})
		},
		/*
		* 检测说明文字是否须要隐藏/收起操做
		* 对比文字外层固定宽度容器元素宽度wrapperWidth与当前文字元素宽度contentWidth
		* 若相差小于10则说明超出一行
		* */
		_checkRemarkToggle() {
			Promise.all([
				this._getElementWidth('#toggle-wrapper'),
				this._getElementWidth('#toggle-content')]
			).then(res => {
				const wrapperWidth = res[0];
				const contentWidth = res[1];

				const {limitRemark, startDate, endDate, statusCode} = this.properties.couponData;

				if (wrapperWidth - contentWidth < 10) {
					this.setData({
						toggleParams: {
							toggleFlag: 1,
							toggleShow: true
						},
						timeArea: `${startDate}-${endDate}`,
						unableImageSrc: UNABLE_IMAGE[statusCode]
					})
				}
			})
		}
	}
});

总结:
在这里只是个抛砖引玉提供一个思路,小程序中能够这样实现,在 H5 中也能够这样实现,若是有更好的方案,欢迎讨论提供!ide