当前位置: 首页 > news >正文

android之TextView自由选择复制

文章目录

  • 前言
  • 一、效果图
  • 二、实现步骤
    • 1.OnSelectListener
    • 2.SelectionInfo类
    • 3.TextLayoutUtil类
    • 4.复制弹框的xml布局
    • 5.弹框背景Drawable
    • 6.倒三角Drawable
    • 7.复制工具类
    • 8.调用
  • 总结


前言

根据时代进步,那些干产品的也叼砖起来了,今天就遇到一个需求,需要对TextView的文案进行自由选择复制,不怕,我们是勇敢牛牛。


一、效果图

在这里插入图片描述

二、实现步骤

1.OnSelectListener

public interface OnSelectListener {void onTextSelected(CharSequence content);
}

2.SelectionInfo类

代码如下(示例):

public class SelectionInfo {public int mStart;public int mEnd;public String mSelectionContent;
}

3.TextLayoutUtil类

package com.example.merchant.utils;import android.content.Context;
import android.text.Layout;
import android.widget.TextView;public class TextLayoutUtil {public static int getScreenWidth(Context context) {return context.getResources().getDisplayMetrics().widthPixels;}public static int getPreciseOffset(TextView textView, int x, int y) {Layout layout = textView.getLayout();if (layout != null) {int topVisibleLine = layout.getLineForVertical(y);int offset = layout.getOffsetForHorizontal(topVisibleLine, x);int offsetX = (int) layout.getPrimaryHorizontal(offset);if (offsetX > x) {return layout.getOffsetToLeftOf(offset);} else {return offset;}} else {return -1;}}public static int getHysteresisOffset(TextView textView, int x, int y, int previousOffset) {final Layout layout = textView.getLayout();if (layout == null) return -1;int line = layout.getLineForVertical(y);if (isEndOfLineOffset(layout, previousOffset)) {// we have to minus one from the offset so that the code below to find// the previous line can work correctly.int left = (int) layout.getPrimaryHorizontal(previousOffset - 1);int right = (int) layout.getLineRight(line);int threshold = (right - left) / 2; // half the width of the last characterif (x > right - threshold) {previousOffset -= 1;}}final int previousLine = layout.getLineForOffset(previousOffset);final int previousLineTop = layout.getLineTop(previousLine);final int previousLineBottom = layout.getLineBottom(previousLine);final int hysteresisThreshold = (previousLineBottom - previousLineTop) / 2;if (((line == previousLine + 1) && ((y - previousLineBottom) < hysteresisThreshold)) || ((line == previousLine - 1) && ((previousLineTop- y) < hysteresisThreshold))) {line = previousLine;}int offset = layout.getOffsetForHorizontal(line, x);if (offset < textView.getText().length() - 1) {if (isEndOfLineOffset(layout, offset + 1)) {int left = (int) layout.getPrimaryHorizontal(offset);int right = (int) layout.getLineRight(line);int threshold = (right - left) / 2; // half the width of the last characterif (x > right - threshold) {offset += 1;}}}return offset;}private static boolean isEndOfLineOffset(Layout layout, int offset) {return offset > 0 && layout.getLineForOffset(offset) == layout.getLineForOffset(offset - 1) + 1;}public static int dp2px(Context context, float dpValue) {final float scale = context.getResources().getDisplayMetrics().density;return (int) (dpValue * scale + 0.5f);}
}

4.复制弹框的xml布局

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="wrap_content"android:layout_height="match_parent"><LinearLayoutandroid:id="@+id/linearLayout"android:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/bg_operate_window"android:orientation="horizontal"android:paddingLeft="5dp"android:paddingRight="5dp"><TextViewandroid:id="@+id/tv_copy"style="@style/OperateTextView"android:text="@string/Copy" /><TextViewandroid:id="@+id/tv_select_all"style="@style/OperateTextView"android:text="@string/SelectAll" /></LinearLayout><ImageViewandroid:id="@+id/iv_triangle"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_below="@+id/linearLayout"android:layout_centerHorizontal="true"android:src="@drawable/triangle_down" />
</RelativeLayout>

5.弹框背景Drawable

<?xml version="1.0" encoding="utf-8"?><shape xmlns:android="http://schemas.android.com/apk/res/android"android:shape="rectangle"><corners android:radius="5dp" /><solid android:color="#454545" /></shape>

6.倒三角Drawable

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"><item><rotateandroid:fromDegrees="45"android:pivotX="135%"android:pivotY="15%"><shape android:shape="rectangle"><sizeandroid:width="16dp"android:height="16dp" /><solid android:color="#454545" /></shape></rotate></item>
</layer-list>

7.复制工具类

package com.example.merchant.utils;import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Build;
import android.text.Layout;
import android.text.Spannable;
import android.text.Spanned;
import android.text.style.BackgroundColorSpan;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.PopupWindow;
import android.widget.TextView;import androidx.annotation.ColorInt;import com.example.merchant.R;/*** 复制utils*/
public class SelectableTextHelper {private final static int DEFAULT_SELECTION_LENGTH = 1;private static final int DEFAULT_SHOW_DURATION = 100;private CursorHandle mStartHandle;private CursorHandle mEndHandle;private OperateWindow mOperateWindow;private SelectionInfo mSelectionInfo = new SelectionInfo();private OnSelectListener mSelectListener;private Context mContext;private TextView mTextView;private Spannable mSpannable;private int mTouchX;private int mTouchY;private int mSelectedColor;private int mCursorHandleColor;private int mCursorHandleSize;private BackgroundColorSpan mSpan;private boolean isHideWhenScroll;private boolean isHide = true;private ViewTreeObserver.OnPreDrawListener mOnPreDrawListener;ViewTreeObserver.OnScrollChangedListener mOnScrollChangedListener;public SelectableTextHelper(Builder builder) {mTextView = builder.mTextView;mContext = mTextView.getContext();mSelectedColor = builder.mSelectedColor;mCursorHandleColor = builder.mCursorHandleColor;mCursorHandleSize = TextLayoutUtil.dp2px(mContext, builder.mCursorHandleSizeInDp);init();}private void init() {mTextView.setText(mTextView.getText(), TextView.BufferType.SPANNABLE);mTextView.setOnLongClickListener(new View.OnLongClickListener() {@Overridepublic boolean onLongClick(View v) {showSelectView(mTouchX, mTouchY);return true;}});mTextView.setOnTouchListener(new View.OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {mTouchX = (int) event.getX();mTouchY = (int) event.getY();return false;}});mTextView.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {resetSelectionInfo();hideSelectView();}});mTextView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {@Overridepublic void onViewAttachedToWindow(View v) {}@Overridepublic void onViewDetachedFromWindow(View v) {destroy();}});mOnPreDrawListener = new ViewTreeObserver.OnPreDrawListener() {@Overridepublic boolean onPreDraw() {if (isHideWhenScroll) {isHideWhenScroll = false;postShowSelectView(DEFAULT_SHOW_DURATION);}return true;}};mTextView.getViewTreeObserver().addOnPreDrawListener(mOnPreDrawListener);mOnScrollChangedListener = new ViewTreeObserver.OnScrollChangedListener() {@Overridepublic void onScrollChanged() {if (!isHideWhenScroll && !isHide) {isHideWhenScroll = true;if (mOperateWindow != null) {mOperateWindow.dismiss();}if (mStartHandle != null) {mStartHandle.dismiss();}if (mEndHandle != null) {mEndHandle.dismiss();}}}};mTextView.getViewTreeObserver().addOnScrollChangedListener(mOnScrollChangedListener);mOperateWindow = new OperateWindow(mContext);}private void postShowSelectView(int duration) {mTextView.removeCallbacks(mShowSelectViewRunnable);if (duration <= 0) {mShowSelectViewRunnable.run();} else {mTextView.postDelayed(mShowSelectViewRunnable, duration);}}private final Runnable mShowSelectViewRunnable = new Runnable() {@Overridepublic void run() {if (isHide) return;if (mOperateWindow != null) {mOperateWindow.show();}if (mStartHandle != null) {showCursorHandle(mStartHandle);}if (mEndHandle != null) {showCursorHandle(mEndHandle);}}};private void hideSelectView() {isHide = true;if (mStartHandle != null) {mStartHandle.dismiss();}if (mEndHandle != null) {mEndHandle.dismiss();}if (mOperateWindow != null) {mOperateWindow.dismiss();}}private void resetSelectionInfo() {mSelectionInfo.mSelectionContent = null;if (mSpannable != null && mSpan != null) {mSpannable.removeSpan(mSpan);mSpan = null;}}private void showSelectView(int x, int y) {hideSelectView();resetSelectionInfo();isHide = false;if (mStartHandle == null) mStartHandle = new CursorHandle(true);if (mEndHandle == null) mEndHandle = new CursorHandle(false);int startOffset = TextLayoutUtil.getPreciseOffset(mTextView, x, y);int endOffset = startOffset + DEFAULT_SELECTION_LENGTH;if (mTextView.getText() instanceof Spannable) {mSpannable = (Spannable) mTextView.getText();}if (mSpannable == null || startOffset >= mTextView.getText().length()) {return;}selectText(startOffset, endOffset);showCursorHandle(mStartHandle);showCursorHandle(mEndHandle);mOperateWindow.show();}private void showCursorHandle(CursorHandle cursorHandle) {Layout layout = mTextView.getLayout();int offset = cursorHandle.isLeft ? mSelectionInfo.mStart : mSelectionInfo.mEnd;cursorHandle.show((int) layout.getPrimaryHorizontal(offset), layout.getLineBottom(layout.getLineForOffset(offset)));}private void selectText(int startPos, int endPos) {if (startPos != -1) {mSelectionInfo.mStart = startPos;}if (endPos != -1) {mSelectionInfo.mEnd = endPos;}if (mSelectionInfo.mStart > mSelectionInfo.mEnd) {int temp = mSelectionInfo.mStart;mSelectionInfo.mStart = mSelectionInfo.mEnd;mSelectionInfo.mEnd = temp;}if (mSpannable != null) {if (mSpan == null) {mSpan = new BackgroundColorSpan(mSelectedColor);}mSelectionInfo.mSelectionContent = mSpannable.subSequence(mSelectionInfo.mStart, mSelectionInfo.mEnd).toString();mSpannable.setSpan(mSpan, mSelectionInfo.mStart, mSelectionInfo.mEnd, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);if (mSelectListener != null) {mSelectListener.onTextSelected(mSelectionInfo.mSelectionContent);}}}public void setSelectListener(OnSelectListener selectListener) {mSelectListener = selectListener;}public void destroy() {mTextView.getViewTreeObserver().removeOnScrollChangedListener(mOnScrollChangedListener);mTextView.getViewTreeObserver().removeOnPreDrawListener(mOnPreDrawListener);resetSelectionInfo();hideSelectView();mStartHandle = null;mEndHandle = null;mOperateWindow = null;}/*** Operate windows : copy, select all*/private class OperateWindow {private PopupWindow mWindow;private int[] mTempCoors = new int[2];private int mWidth;private int mHeight;public OperateWindow(final Context context) {View contentView = LayoutInflater.from(context).inflate(R.layout.layout_operate_windows2, null);contentView.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));mWidth = contentView.getMeasuredWidth();mHeight = contentView.getMeasuredHeight();mWindow =new PopupWindow(contentView, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, false);mWindow.setClippingEnabled(false);TextView tv_copy = contentView.findViewById(R.id.tv_copy);TextView tv_select_all = contentView.findViewById(R.id.tv_select_all);tv_copy.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {//复制点击实现功能AppTk.Companion.showTimeDailog(mSelectionInfo.mSelectionContent, mContext);if (mSelectListener != null) {mSelectListener.onTextSelected(mSelectionInfo.mSelectionContent);}SelectableTextHelper.this.resetSelectionInfo();SelectableTextHelper.this.hideSelectView();}});tv_select_all.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {hideSelectView();selectText(0, mTextView.getText().length());isHide = false;showCursorHandle(mStartHandle);showCursorHandle(mEndHandle);mOperateWindow.show();}});}public void show() {mTextView.getLocationInWindow(mTempCoors);Layout layout = mTextView.getLayout();int posX = (int) layout.getPrimaryHorizontal(mSelectionInfo.mStart) + mTempCoors[0];int posY = layout.getLineTop(layout.getLineForOffset(mSelectionInfo.mStart)) + mTempCoors[1] - mHeight - 16;if (posX <= 0) posX = 16;if (posY < 0) posY = 16;if (posX + mWidth > TextLayoutUtil.getScreenWidth(mContext)) {posX = TextLayoutUtil.getScreenWidth(mContext) - mWidth - 16;}if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {mWindow.setElevation(8f);}mWindow.showAtLocation(mTextView, Gravity.NO_GRAVITY, posX, posY);}public void dismiss() {mWindow.dismiss();}public boolean isShowing() {return mWindow.isShowing();}}private class CursorHandle extends View {private PopupWindow mPopupWindow;private Paint mPaint;private int mCircleRadius = mCursorHandleSize / 2;private int mWidth = mCircleRadius * 2;private int mHeight = mCircleRadius * 2;private int mPadding = 25;private boolean isLeft;public CursorHandle(boolean isLeft) {super(mContext);this.isLeft = isLeft;mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);mPaint.setColor(mCursorHandleColor);mPopupWindow = new PopupWindow(this);mPopupWindow.setClippingEnabled(false);mPopupWindow.setWidth(mWidth + mPadding * 2);mPopupWindow.setHeight(mHeight + mPadding / 2);invalidate();}@Overrideprotected void onDraw(Canvas canvas) {canvas.drawCircle(mCircleRadius + mPadding, mCircleRadius, mCircleRadius, mPaint);if (isLeft) {canvas.drawRect(mCircleRadius + mPadding, 0, mCircleRadius * 2 + mPadding, mCircleRadius, mPaint);} else {canvas.drawRect(mPadding, 0, mCircleRadius + mPadding, mCircleRadius, mPaint);}}private int mAdjustX;private int mAdjustY;private int mBeforeDragStart;private int mBeforeDragEnd;@Overridepublic boolean onTouchEvent(MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:mBeforeDragStart = mSelectionInfo.mStart;mBeforeDragEnd = mSelectionInfo.mEnd;mAdjustX = (int) event.getX();mAdjustY = (int) event.getY();break;case MotionEvent.ACTION_UP:case MotionEvent.ACTION_CANCEL:mOperateWindow.show();break;case MotionEvent.ACTION_MOVE:mOperateWindow.dismiss();int rawX = (int) event.getRawX();int rawY = (int) event.getRawY();update(rawX + mAdjustX - mWidth, rawY + mAdjustY - mHeight);break;}return true;}private void changeDirection() {isLeft = !isLeft;invalidate();}public void dismiss() {mPopupWindow.dismiss();}private int[] mTempCoors = new int[2];public void update(int x, int y) {mTextView.getLocationInWindow(mTempCoors);int oldOffset;if (isLeft) {oldOffset = mSelectionInfo.mStart;} else {oldOffset = mSelectionInfo.mEnd;}y -= mTempCoors[1];int offset = TextLayoutUtil.getHysteresisOffset(mTextView, x, y, oldOffset);if (offset != oldOffset) {resetSelectionInfo();if (isLeft) {if (offset > mBeforeDragEnd) {CursorHandle handle = getCursorHandle(false);changeDirection();handle.changeDirection();mBeforeDragStart = mBeforeDragEnd;selectText(mBeforeDragEnd, offset);handle.updateCursorHandle();} else {selectText(offset, -1);}updateCursorHandle();} else {if (offset < mBeforeDragStart) {CursorHandle handle = getCursorHandle(true);handle.changeDirection();changeDirection();mBeforeDragEnd = mBeforeDragStart;selectText(offset, mBeforeDragStart);handle.updateCursorHandle();} else {selectText(mBeforeDragStart, offset);}updateCursorHandle();}}}private void updateCursorHandle() {mTextView.getLocationInWindow(mTempCoors);Layout layout = mTextView.getLayout();if (isLeft) {mPopupWindow.update((int) layout.getPrimaryHorizontal(mSelectionInfo.mStart) - mWidth + getExtraX(),layout.getLineBottom(layout.getLineForOffset(mSelectionInfo.mStart)) + getExtraY(), -1, -1);} else {mPopupWindow.update((int) layout.getPrimaryHorizontal(mSelectionInfo.mEnd) + getExtraX(),layout.getLineBottom(layout.getLineForOffset(mSelectionInfo.mEnd)) + getExtraY(), -1, -1);}}public void show(int x, int y) {mTextView.getLocationInWindow(mTempCoors);int offset = isLeft ? mWidth : 0;mPopupWindow.showAtLocation(mTextView, Gravity.NO_GRAVITY, x - offset + getExtraX(), y + getExtraY());}public int getExtraX() {return mTempCoors[0] - mPadding + mTextView.getPaddingLeft();}public int getExtraY() {return mTempCoors[1] + mTextView.getPaddingTop();}}private CursorHandle getCursorHandle(boolean isLeft) {if (mStartHandle.isLeft == isLeft) {return mStartHandle;} else {return mEndHandle;}}public static class Builder {private TextView mTextView;private int mCursorHandleColor = 0xFF1379D6;private int mSelectedColor = 0xFFAFE1F4;private float mCursorHandleSizeInDp = 24;public Builder(TextView textView) {mTextView = textView;}public Builder setCursorHandleColor(@ColorInt int cursorHandleColor) {mCursorHandleColor = cursorHandleColor;return this;}public Builder setCursorHandleSizeInDp(float cursorHandleSizeInDp) {mCursorHandleSizeInDp = cursorHandleSizeInDp;return this;}public Builder setSelectedColor(@ColorInt int selectedBgColor) {mSelectedColor = selectedBgColor;return this;}public SelectableTextHelper build() {return new SelectableTextHelper(this);}}
}

8.调用

private var mSelectableTextHelper: SelectableTextHelper? = null//实例化
//text为文案
mSelectableTextHelper = SelectableTextHelper.Builder(text).setSelectedColor(Color.parseColor("#afe1f4")).setCursorHandleSizeInDp(20f).setCursorHandleColor(Color.parseColor("#0d7aff")).build()

总结

感觉东西是有点多,但比较实用,而且直接复制去就可以用,自己写主要费大脑不是。

相关文章:

android之TextView自由选择复制

文章目录 前言一、效果图二、实现步骤1.OnSelectListener2.SelectionInfo类3.TextLayoutUtil类4.复制弹框的xml布局5.弹框背景Drawable6.倒三角Drawable7.复制工具类8.调用 总结 前言 根据时代进步&#xff0c;那些干产品的也叼砖起来了&#xff0c;今天就遇到一个需求&#x…...

【mysql】 bash: mysql: command not found

在linux 服务器上安装了mysql 也可以正常运行。 但是执行命令&#xff0c;系统提示&#xff1a;bash: mysql: command not found bash:mysql:找不到命令 执行的命令是&#xff1a; mysql -u root -h 127.0.0.1 -p由于系统默认会查找的 /usr/bin/ 中下的命令&#xff0c;如…...

鲲山科技:引入和鲸 ModelWhale,实现量化策略的高效迭代

量化投资是数据科学在金融行业的应用。 2023 年&#xff0c;量化行业的超额收益开始收敛&#xff0c;量化私募如何形成自身核心竞争力&#xff1f; 和鲸拜访客户鲲山科技&#xff08;深圳&#xff09;&#xff0c;揭示其“弯道超车”的独家秘诀。 群体作战 年初至今&#xff…...

PFSK152 3BSE018877R1 有源滤波器的定义

PFSK152 3BSE018877R1 有源滤波器的定义 有源滤波器是以晶体管和运算放大器为基本元件设计的滤波电路。除了这些元件&#xff0c;有源滤波器的电路还包含电阻和电容&#xff0c;但不包含电感。 我们知道滤波器具有频率选择性。因此&#xff0c;有源滤波器电路使用晶体管和运算…...

WebDAV之π-Disk派盘 + 恒星播放器

想要拥有一款万能视频播放器,全能解码播放器,无需转码,支持所有格式的视频和音频,直接播放的播放器?那就选恒星播放器。 恒星播放器支持视频投屏,倍速播放,后台播放等功能,还能一键截图和录制gif动图。支持全格式超高清真4K解码,蓝光HDR低占用,支持ISO文件直出的播放…...

亚马逊,速卖通,敦煌产品测评补单攻略:低成本、高安全实操指南

随着电商平台的发展和消费者对产品质量的要求提升&#xff0c;测评补单成为了商家们提升销售和用户口碑的关键环节。然而&#xff0c;如何在保持成本低廉的同时确保操作安全&#xff0c;一直是卖家们面临的挑战。今天林哥分享一些实用的技巧和策略&#xff0c;帮助卖家们产品的…...

常用linux解压命令

1. 超过4g的zip文件在linux下unzip失败。需要用7z压缩&#xff0c;然后用p7zip命令解压。 p7zip -d x.7z 2. gzip解压.gz文件 gzip -d a11.txt.gz 和 gunzip a1.txt.gz gunzip –c filename.gz > filename #解压缩保留源文件, 上述命令非常容易写错&#xff0c;最后导…...

TensorFlow入门(二十二、梯度下降)

梯度下降的定义及作用 梯度下降本身是一个最优化算法,通常也被称为最速下降法。常被用于机器学习和人工智能中递归性地逼近最小偏差模型,也就是使用它找到一个函数的局部极小值。 使用过程中,梯度下降算法以函数上当前点对于梯度(或者是近似梯度)反方向的规定步长距离点进行迭代…...

WPF中的多重绑定

MultiBinding 将会给后端传回一个数组, 其顺序为绑定的顺序. 例如: <DataGridMargin"10"AutoGenerateColumns"False"ItemsSource"{Binding Stu}"><DataGrid.Columns><DataGridTextColumn Binding"{Binding Id}" Header…...

区块链在游戏行业的应用

区块链技术在游戏行业有许多潜在的应用&#xff0c;它可以改变游戏开发、发行和玩家交互的方式。以下是区块链技术在游戏行业的一些主要应用&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 1.游戏资产…...

uniapp快速入门系列(4)- 微信小程序开发

第四章 微信小程序开发 4.1 微信小程序开发与uniapp的融合4.2 微信小程序API在uniapp中的使用4.3 微信小程序常见问题的解决方法问题1: 如何获取用户信息&#xff1f;问题2: 如何获取当前位置&#xff1f;问题3: 如何发送网络请求&#xff1f; 在本章中&#xff0c;我们将学习如…...

Kafka保证消息幂等以及解决方案

1、幂等的基本概念 幂等简单点讲&#xff0c;就是用户对于同一操作发起的一次请求或者多次请求的结果是一致的&#xff0c;不会产生任何副作用。幂等分很多种&#xff0c;比如接口的幂等、消息的幂等&#xff0c;它是分布式系统设计时必须要考虑的一个方面。 查询操作(天然幂等…...

接口测试用例设计

接口测试...

wireshark抓rtp包,提取出H265裸流数

调试rtsp收发流时&#xff0c;经常会需要抓包以确认是网络问题还是程序问题还是其它问题。通过tcpdump或者wireshark抓到的包通常是rtp流&#xff0c;保存为.pcap格式文件后中&#xff0c;可通过wireshark进行解析&#xff0c;得出h264裸流&#xff0c;并保存为文件。 1.wires…...

Excel往Word复制表格时删除空格

1.背景 在编写文档&#xff0c;经常需要从Excel往Word里复制表格 但是复制过去的表格前面会出现空格&#xff08;缩进&#xff09; 再WPS中试了很多方法&#xff0c;终于摆脱了挨个删除的困扰 2. WPS排版中删除 选择表格菜单栏-选在【开始】-【排版】选择【更多段落处理】-【段…...

客户机操作系统已禁用 CPU。请关闭或重置虚拟机(解决)

解决&#xff1a; 关闭虚拟机进入设置点击处理器给虚拟化引擎两个勾上确认后重新即可...

UnityShaderLab —— 简单的流光shader

原理&#xff1a; 就是在原先的模型表面叠加一层可以流动的图片&#xff0c; 算法代码&#xff1a; float2 tex; tex float2(i.uv.x - _Time.x * _Speed,i.uv.y); fixed4 col0 tex2D(_Tex, tex)* _Strenth; fixed4 col1 tex2D(_MainTex, i.uv); return col0 col1; 这里…...

代理IP在保护跨境商家网络安全中的重要作用

在当前全球化的背景下&#xff0c;跨境电商成为一种重要的商业模式&#xff0c;越来越多的商家涌入国际市场&#xff0c;商家们通过互联网平台将商品远销国外&#xff0c;但网络安全风险随之而来。跨境商家因为需要处理大量的在线交易和产品数据&#xff0c;如果未能对这些敏感…...

2核4G服务器支持多少用户同时在线访问?卡不卡?

腾讯云轻量2核4G5M带宽服务器支持多少人在线访问&#xff1f;5M带宽下载速度峰值可达640KB/秒&#xff0c;阿腾云以搭建网站为例&#xff0c;假设优化后平均大小为60KB&#xff0c;则5M带宽可支撑10个用户同时在1秒内打开网站&#xff0c;从CPU内存的角度&#xff0c;网站程序效…...

[Error]在Swift项目Build Settings的Preprocessor Macros中定义的宏无效的问题

问题 如图&#xff0c;在Build Settings -> Preprocessor Macros中添加了ISADEMO1。但在代码中判断无效&#xff0c;还是会输出“isn’t ADemo” #if ISADEMOprint("is ADemo") #elseprint("isnt ADemo") #endif解决 如图&#xff0c;要让Preproces…...

网格管理安全巡检系统—助企业全面安全检查

通过应用安全巡检管理系统&#xff0c;企业能更好地管理控制安全风险&#xff0c;保障员工生命安全和财产安全&#xff0c;避免出现各种危险隐患&#xff0c;帮助企业快速提高生产发展实力。 一、凡尔码搭建安全巡检系统的功能 1.巡检计划:帮助用户制定巡检计划&#xff0c;包括…...

【Java】replace替换方法

String 替换方法 replace() 方法用于将目标字符串中的指定字符&#xff08;串&#xff09;替换成新的字符&#xff08;串&#xff09;replaceFirst() 方法用于将目标字符串中匹配某正则表达式的第一个子字符串替换成新的字符串replaceAll() 方法用于将目标字符串中匹配某正则表…...

CentOS yum update

详情内容 CentOS yum update升级命令详解&#xff0c;包括yum check-update&#xff0c;yum update&#xff0c;yum install等升级安装命令详细使用方法。 1.列出所有可更新的软件清单 命令&#xff1a; yum check-update 2.安装所有更新软件 命令&#xff1a; yum updat…...

/etc/profile与~/.bash_profile的区别

/etc/profile和~/.bash_profile都是用于存储用户的配置文件的&#xff0c;但它们的作用范围和加载顺序有所不同。 /etc/profile是系统级的配置文件&#xff0c;它应用于所有用户。当用户登录时&#xff0c;系统会首先加载/etc/profile。这个文件存储了系统范围的环境变量、系统…...

vue+element实现电商商城礼品代发网,商品、订单管理

一、项目效果图 1.首页 2.登录 版本2&#xff1a; 3.注册 4.找回密码 5.立即下单 6.商品详情 7.个人中心-工作台 8.个人中心-订单列表 9.订单中心-包裹列表 10.个人中心-工单管理 11.我的钱包 12.实名认证 13.升级vip 14.个人中心-推广赚钱 二、关键源码 1.路由配置 impor…...

Python接口自动化-requests模块之post请求

一、源码解析 def post(url, dataNone, jsonNone, **kwargs):r"""Sends a POST request.:param url: URL for the new :class:Request object.:param data: (optional) Dictionary, list of tuples, bytes, or file-likeobject to send in the body of the :cl…...

DDoS检测防御实现方案

流量采集模式 通过分光器将流量直接镜像到攻击检测器&#xff0c;收包采用DPDK库。 当前整机流量、源IP信息、连接数 、连接内容(五元组等)的信息汇聚 当发生告警时采样原始数据包&#xff0c; 采用固定采样算法 基于检测对象的TCP syn ack psh ack established的个数、流量…...

ArcGIS: 第二届全国大学生GIS技能大赛(广西师范学院)详解-下午题

目录 01 题目 02 思路和实操 2.1 流域提取-思路 2.2 流域提取-实操 2.2.1 获取DEM ​编辑 2.2.2 水文分析-提取流域基于单出水口 2.3 河网分级-思路 2.4 河网分级-实操 2.4.1 提取河道网络 2.4.2 河网分级 ​编辑 2.5 子流域提取和处理-思路 2.6 子流域提取和处理-实…...

vue七牛云视频直传

完成后样式&#xff1a; 下面的代码是我自己项目里面用到的&#xff0c;一些判断看自己情况去掉&#xff0c;用的是element-ui组件 安装 uuid 库。你可以使用 npm 或 yarn 来完成安装。在终端中执行以下命令&#xff1a; npm install uuidhtml部分 <el-upload class&quo…...

云原生Kubernetes:K8S集群版本升级(v1.20.15 - v1.22.14)

目录 一、理论 1.K8S集群升级 2.集群概况 3.升级集群&#xff08;v1.21.14&#xff09; 4.验证集群&#xff08;v1.21.14&#xff09; 5.升级集群&#xff08;v1.22.14&#xff09; 6.验证集群 (v1.22.14) 二、实验 1.升级集群&#xff08;v1.21.14&#xff09; 2.验…...