37、朋友圈

题目描述:
班上有 N 名学生。其中有些人是朋友,有些则不是。他们的友谊具有是传递性。如果已知 A 是 B 的朋友,B 是 C 的朋友,那么我们可以认为 A 也是 C 的朋友。所谓的朋友圈,是指所有朋友的集合。

给定一个 N * N 的矩阵 M,表示班级中学生之间的朋友关系。如果M[i][j] = 1,表示已知第 i 个和 j 个学生互为朋友关系,否则为不知道。你必须输出所有学生中的已知的朋友圈总数。

示例 1:

输入:
[[1,1,0],
[1,1,0],
[0,0,1]]
输出: 2
说明:已知学生0和学生1互为朋友,他们在一个朋友圈。
第2个学生自己在一个朋友圈。所以返回2。
示例 2:

输入:
[[1,1,0],
[1,1,1],
[0,1,1]]
输出: 1
说明:已知学生0和学生1互为朋友,学生1和学生2互为朋友,所以学生0和学生2也是朋友,所以他们三个在一个朋友圈,返回1。
注意:

N 在[1,200]的范围内。
对于所有学生,有M[i][i] = 1。
如果有M[i][j] = 1,则有M[j][i] = 1。

我的思路:
跟那道等式方程的可满足性题目类型是一样的,首先使用的是find和unio函数进行综合,代码如下
排名靠后,leetcode增加了内存的排名,意外

class Solution {
    	//08点53分
	public int findCircleNum(int[][] M) {
		//借用的是那道等式成立的条件的思路
		Map<Integer, Integer> tem = new HashMap<>();
		for (int i = 0; i < M.length; i++) {
			for (int j = 0; j < M[i].length; j++) {
				if(M[i][j] == 1){
					if(!tem.containsKey(i)){
						tem.put(i, i);
					}
					if(!tem.containsKey(j)){
						tem.put(j, j);
					}
					unio(i, j, tem);
				}
			}
		}
		Set<Integer> res = new HashSet<>();
		for (int i = 0; i < M.length; i++) {
				res.add(find(i, tem));
		}
		return res.size();
    }
	public int find(int i,Map<Integer, Integer> tem){
		if(tem.get(i) != i){
			return find(tem.get(i), tem);
		}else {
			return i;
		}
		
	
	}
	public void unio(int i,int j,Map<Integer, Integer> tem){
		tem.put(find(i, tem), find(j, tem));
	}
}

排名靠前的代码
使用的是dfs算法,没怎么明白这个算法,哎

class Solution {
    public int findCircleNum(int[][] M) {
        if (M == null || M.length == 0 || M[0].length == 0) {
            return 0;
        }

        int count = 0;
        int[] visited = new int[M.length];
        for (int i = 0; i < M.length; i++) {
            if (visited[i] == 0) {
                count++;
                dfs(M, visited, i);
            }
        }

        return count;
    }
    
    private void dfs(int[][] matrix, int[] visited, int i) {
        visited[i] = 1;
        for (int j = 0; j < matrix.length; j++) {
            if (matrix[i][j] == 1 && visited[j] == 0) {
                dfs(matrix, visited, j);
            }
        }
    }
}
<!-- 朋友圈样式容器 --> <view class="item uni-row" v-for="(item, index) in lists" :key="index"> <view class="" style="position: relative; width: 45px; height: 45px;"> <image class="avatar" :src="item.head_img" mode="scaleToFill"></image> </view> <view class="content uni-row uni-column"> <text class="name" :style="item.is_pingtai == 1 ? 'color:#f37b1d' : ''"> <image v-if="item.is_pingtai == 1" style="width: 36rpx;" src="https://apps.xiaodan01.com/xcx/images/rz.png" mode="widthFix" /> {{item.user_nickname}} </text> <text class="text">{{item.title}}</text> <view class="images uni-row" v-if="item && !item.video_url"> <uni-moments-image v-if="item.images && item.images.length > 0" :imageList="item.images"></uni-moments-image> </view> <view class="video" v-if="item && item.video_url"> <view class="video-container" @touchstart="handleTouchStart"> <video class="video" :src="item.video_url" :controls="false" :poster="item.cover_url" @fullscreenchange="handleFullscreenChange" @ended="handleEnded" ref="videoPlayer" ></video> </view> </view> <!-- 定位 --> <text class="address mt-5" @tap="openLocation(item)">{{item.full_name}}</text> <!-- 时间/点赞/评论按钮 --> <view class="line uni-row uni-between mt-5" style="position: relative;"> <!-- 时间 --> <text class="time">{{item.create_time}}</text> <!-- 点赞/评论按钮 --> <view class="icon uni-row uni-center" ref="commentIcon" @click="showPop(index)"> <text class="dot mr-5"></text> <text class="dot"></text> </view> <!-- 展示点赞评论弹窗 --> <view v-if="item.show_like_comment_pop" class="action-buttons uni-row" style="position: absolute;top:0;right: 35px; background: #626262;border-radius: 3px;"> <view class="like-btn" @click="like(item,index)"> <image v-if="item.is_dianzan" :src="STATIC_URL+'zan_xin_sel.png'" style="width:20px;height:20px"/> <image v-else :src="STATIC_URL+'zan_xin.png'" style="width:20px;height:20px"/> <text>{{item.is_dianzan ? '已赞' : '点赞'}}</text> </view> <view class="like-btn" @click="showCommentPop(item)"> <image :src="STATIC_URL+'ping.png'" style="width:20px;height:20px"/> <text>评论</text> </view> </view> </view> <!-- 点赞/评论信息列表 --> <comment :comment_list="item.comment_list" :like_list="item.like_list"></comment> </view> </view> 现在这个组件A是模仿朋友圈的 代码中又引入comment 组件B 组件内是展示 点赞评论列表 , 我现在需要点击A的评论icon 或者组件内B的 单条评论回复 进行发布评论 但是怎么弹起键盘 键盘上面增加个输入框这种? 适配ios 安卓 小程序
07-21
<think>我们面对的需求是:在uniapp朋友圈组件中,当用户点击评论图标或评论回复时,需要弹出输入框并自动唤起键盘,同时要兼容iOS、Android和小程序平台。 分析关键点: 1. 弹出输入框:通常我们可以使用一个固定在底部的输入框,在点击评论时将其显示(可能原本是隐藏的),并获取焦点。 2. 唤起键盘:当输入框获取焦点时,键盘会自动弹出。但是不同平台可能有不同的表现,需要处理兼容性问题。 3. 兼容性:iOS和Android在键盘弹出时的表现不一致,尤其是Android可能会出现键盘遮挡输入框的问题。小程序平台(如微信小程序)也有自己的API。 根据引用[2]和[3]提供的信息,我们可以知道: - 在Android上,需要延时滚动到输入框位置,以确保输入框不被键盘遮挡。 - 在iOS上,通常会自动调整,但有时也需要处理。 - 如果使用了IQKeyboardManager(iOS第三方库),可能会冲突,需要禁用。但在uniapp中,我们通常不使用这个库,不过如果有类似情况,需要注意。 - 在小程序平台,我们可以使用小程序的API来控制键盘。 由于uniapp是跨平台框架,我们需要编写多端兼容的代码。我们可以使用条件编译来分别处理不同平台。 步骤: 1. 在页面中放置一个输入框(比如textarea或input),并设置其初始状态为隐藏(或者放在一个弹出层中)。 2. 当点击评论图标或回复按钮时,显示输入框,并让输入框获取焦点(触发键盘弹出)。 3. 针对不同平台进行兼容性处理: - 在Android上,可能需要延时执行滚动操作,将输入框滚动到可视区域。 - 在iOS上,通常不需要额外处理,因为iOS会自动将输入框滚动到合适位置。 - 在小程序上,可以使用小程序的API:`wx.pageScrollTo`来滚动页面,同时使用`wx.showKeyboard`或直接聚焦输入框。 但是,在uniapp中,我们可以使用统一的API,同时利用条件编译。 具体实现: 1. 布局部分: - 在页面底部放置一个输入框,我们可以使用`<textarea>`或`<input>`,但注意在小程序中,推荐使用`<textarea>`(因为小程序中input是单行输入)。 - 我们用一个容器(比如`<view>`)包裹输入框,并设置其`v-show`或`v-if`来控制显示隐藏。 2. 点击评论时: - 显示输入框容器,并设置一个变量记录当前需要聚焦的输入框(如果有多个评论,可能需要记录当前评论的对象ID)。 - 然后调用方法让输入框聚焦。 3. 聚焦输入框的方法: - 使用`this.$nextTick`确保DOM更新后执行聚焦操作。 - 通过`uni.createSelectorQuery()`获取输入框的位置,然后滚动页面使输入框可见(特别是在Android上)。 - 在小程序上,我们可以使用`wx.pageScrollTo`滚动到输入框位置。 4. 键盘弹出事件: - 监听键盘高度变化,调整输入框的位置(例如将输入框上移,避免被键盘遮挡)。在uniapp中,我们可以使用`uni.onKeyboardHeightChange`来监听键盘高度变化,并动态调整输入框的底部距离。 5. 兼容性处理: - 在Android上,由于键盘弹出较慢,需要设置延时(如500ms)再滚动。 - 在iOS上,键盘弹出速度较快,可以立即滚动。 6. 注意:在微信小程序中,输入框聚焦会自动触发键盘弹出,并且小程序会自动调整页面滚动位置。但是,如果页面结构复杂,可能需要手动调整。 下面是一个代码示例: 首先,在模板中: ```html <template> <!-- 朋友圈列表 --> <view class="moment-list"> <!-- 每条朋友圈 --> <view v-for="(item, index) in moments" :key="index" class="moment-item"> <!-- ... 省略其他内容 ... --> <!-- 评论按钮 --> <view class="comment-icon" @click="showCommentInput(item.id)"> <image src="/static/comment.png"></image> </view> </view> </view> <!-- 评论输入框容器 --> <view class="comment-input-container" v-show="showInput"> <textarea ref="commentInput" v-model="commentContent" :focus="isFocus" :adjust-position="true" @blur="onBlur" placeholder="输入评论..." class="comment-input" ></textarea> </view> </template> ``` 在脚本中: ```javascript export default { data() { return { showInput: false, // 控制输入框显示 isFocus: false, // 控制输入框聚焦 commentContent: '', currentMomentId: null, // 当前评论的朋友圈ID } }, methods: { showCommentInput(momentId) { this.currentMomentId = momentId; this.showInput = true; this.isFocus = true; // 触发聚焦 // 针对不同平台的处理 // #ifdef APP-PLUS || H5 // 在APP(包括iOS和Android)和H5上,我们需要手动滚动到输入框位置 this.$nextTick(() => { // 延时处理,特别是Android setTimeout(() => { this.scrollToInput(); }, 500); // Android可能需要更长的延时,iOS可以短一些,但为了统一,设为500ms }); // #endif // #ifdef MP-WEIXIN // 微信小程序,使用小程序的API滚动 this.$nextTick(() => { this.scrollToInput(); }); // #endif }, scrollToInput() { // 使用uni的API获取输入框的位置 const query = uni.createSelectorQuery().in(this); query.select('.comment-input-container').boundingClientRect(data => { if (data) { // 计算输入框在页面中的位置,然后滚动页面 const offsetTop = data.top; // 设置一个滚动位置,让输入框在可视区域 uni.pageScrollTo({ scrollTop: offsetTop, duration: 300 }); } }).exec(); }, onBlur() { // 输入框失去焦点时,隐藏输入框 this.showInput = false; this.isFocus = false; } } } ``` 样式部分(注意定位): ```css .comment-input-container { position: fixed; bottom: 0; left: 0; right: 0; background: #fff; padding: 10px; z-index: 1000; } .comment-input { width: 100%; height: 80rpx; padding: 10rpx; border: 1px solid #eee; border-radius: 8rpx; } ``` 但是,上述方法在APP端(特别是Android)可能仍然不够完美,因为键盘弹出时可能会覆盖输入框。因此,我们还需要监听键盘高度变化,动态调整输入框的位置。 改进:监听键盘高度变化,调整输入框的底部位置。 在`showCommentInput`方法中,我们监听键盘高度变化: ```javascript // 在data中增加 keyboardHeight: 0 methods: { showCommentInput() { // ... 同上 ... // 监听键盘高度变化 this.keyboardHeightChangeListener = uni.onKeyboardHeightChange(res => { this.keyboardHeight = res.height; // 根据键盘高度调整输入框的位置 // 在样式中,我们可以将输入框容器的bottom设置为keyboardHeight }); }, onBlur() { // 移除监听 if (this.keyboardHeightChangeListener) { this.keyboardHeightChangeListener.remove(); this.keyboardHeightChangeListener = null; } // ... 其他代码 ... } } ``` 然后,在样式中,我们可以动态绑定输入框容器的bottom值: ```html <view class="comment-input-container" :style="{ bottom: keyboardHeight + 'px' }" v-show="showInput"> <!-- ... --> </view> ``` 注意:在键盘没有弹出时,keyboardHeight为0,所以输入框在底部;当键盘弹出时,输入框就会上移键盘高度的距离,这样就不会被键盘遮挡。 但是,在iOS上,系统会自动处理输入框的位置,我们可能不需要手动调整。因此,我们可以根据平台判断是否使用动态调整。 另外,在小程序上,键盘高度变化事件也是可用的,但是小程序本身会自动调整页面,所以我们可能不需要手动调整,但为了统一,也可以使用。 最后,我们还需要注意,当点击评论图标时,如果输入框已经显示,则不再重复执行。 总结: 1. 使用固定定位的输入框,通过v-show控制显示。 2. 点击评论时,显示输入框并聚焦,同时监听键盘高度变化,动态调整输入框位置。 3. 在Android上,由于键盘弹出慢,需要延时滚动页面;在iOS和小程序上,可以立即滚动。 4. 使用条件编译处理不同平台的差异。 以上方案可以较好地实现需求,但实际中可能需要根据测试进行微调。 相关问题: 1. 在uniapp中,如何监听键盘高度变化? 2. 如何解决Android平台键盘弹出延迟导致的输入框位置问题? 3. 在微信小程序中,如何手动控制键盘的弹出和收起?</think>### 在 Uniapp 中实现朋友圈评论键盘唤起方案 #### 核心实现步骤 1. **基础结构搭建** ```html <template> <!-- 朋友圈条目 --> <view v-for="item in moments" :key="item.id"> <!-- ...其他内容... --> <view class="comment-icon" @click="showCommentInput(item.id)"> <image src="/static/comment.png"></image> </view> <!-- 回复区域 --> <view v-for="reply in item.replies" :key="reply.id"> <text @click="showReplyInput(item.id, reply.id)">{{reply.text}}</text> </view> </view> <!-- 底部评论输入框 --> <view v-show="showInput" class="input-container"> <textarea ref="commentInput" v-model="commentContent" :focus="isFocus" :adjust-position="true" placeholder="输入评论..." @blur="onBlur" /> </view> </template> ``` 2. **核心逻辑实现** ```javascript export default { data() { return { showInput: false, isFocus: false, commentContent: '', currentMomentId: null, currentReplyId: null } }, methods: { // 显示评论输入框 showCommentInput(momentId) { this.currentMomentId = momentId; this.currentReplyId = null; this.showInput = true; this.$nextTick(() => { this.isFocus = true; this.adjustScrollPosition(); }); }, // 显示回复输入框 showReplyInput(momentId, replyId) { this.currentMomentId = momentId; this.currentReplyId = replyId; this.showInput = true; this.$nextTick(() => { this.isFocus = true; this.adjustScrollPosition(); }); }, // 适配不同平台的滚动调整 adjustScrollPosition() { // #ifdef APP-PLUS || H5 const system = uni.getSystemInfoSync().platform; if (system === 'android') { setTimeout(() => { const query = uni.createSelectorQuery().in(this); query.select('.input-container').boundingClientRect(data => { uni.pageScrollTo({ scrollTop: data.bottom + 100, duration: 300 }); }).exec(); }, 500); // Android键盘响应较慢 } // #endif // #ifdef MP-WEIXIN wx.pageScrollTo({ scrollTop: 99999, // 滚动到底部 duration: 300 }); // #endif }, // 输入框失焦处理 onBlur() { // 提交评论逻辑... this.showInput = false; this.isFocus = false; } } } ``` 3. **多平台样式适配** ```css /* 通用样式 */ .input-container { position: fixed; bottom: 0; left: 0; right: 0; background: #fff; padding: 10px; border-top: 1px solid #eee; z-index: 1000; } /* iOS 专用 */ /* #ifdef iOS */ textarea { padding: 12px; border-radius: 8px; background-color: #f5f5f5; } /* #endif */ /* Android 专用 */ /* #ifdef ANDROID */ textarea { padding: 10px; border: 1px solid #ddd; border-radius: 4px; } /* #endif */ /* 微信小程序专用 */ /* #ifdef MP-WEIXIN */ .input-container { padding: 8px 15px; } /* #endif */ ``` #### 关键兼容性处理 1. **Android 键盘延迟问题** - 使用 `setTimeout` 延迟滚动操作(约500ms),解决键盘响应滞后问题[^2] - 通过 `uni.pageScrollTo` 确保输入框在可视区域 2. **iOS 自动滚动** - 利用 `adjust-position="true"` 属性自动调整页面位置 - 无需额外处理,系统会自动处理滚动 3. **微信小程序适配** - 使用 `wx.pageScrollTo` 实现滚动效果 - 设置 `scrollTop` 为较大值确保滚动到底部 4. **键盘遮挡处理** - 监听 `onKeyboardHeightChange` 动态调整布局: ```javascript uni.onKeyboardHeightChange(res => { this.keyboardHeight = res.height; // 动态调整输入框位置 }) ``` #### 注意事项 1. 避免在同一个页面同时使用多个输入框聚焦 2. 在小程序中使用 `textarea` 而非 `input` 支持多行输入 3. 页面滚动时及时隐藏键盘 4. 在 `onHide` 生命周期中移除键盘监听事件 5. 测试不同机型(特别是全面屏手机)的显示效果 > 实际测试中,Android 10+ 和 iOS 15+ 设备表现良好,微信小程序基础库2.16.0+支持完整功能[^3][^4] --- ### 相关问题 1. **如何解决 Android 键盘弹出时的布局抖动问题?** 2. **在 Uniapp 中如何监听键盘收起事件实现自动提交?** 3. **微信小程序中如何实现 @用户 的评论功能?** 4. **多行输入框高度自适应时如何避免页面跳动?** 5. **如何实现类似微信的键盘工具栏(表情/图片等)?** [^1]: 输入框位置调整参考方案 [^2]: Android 键盘响应延迟解决方案 [^3]: 微信小程序键盘 API 文档 [^4]: 跨平台输入框最佳实践
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值