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

Android 解决TextView多行滑动与NestedScrollView嵌套滑动冲突的问题

关键计算地方:

1.当前是上滑动还是下滑动(相对于屏幕) ,使用ev.getRawY()获得当前滑动位置在屏幕哪个地方

2.  计算文本客滑动到哪里即可停止, (行高*总文本行数)- (行高 * 最多显示行数)   int sum = getLineHeight() * getLineCount() - getLineHeight() * getMaxLines();

代码:

import android.content.Context;
import android.text.method.ScrollingMovementMethod;
import android.util.AttributeSet;
import android.view.MotionEvent;/*** @Description: 可滑动的TextView, 并且解决了与 ScrollView等的滑动冲突*/
public class ScrollTextView extends android.support.v7.widget.AppCompatTextView {public ScrollTextView(Context context) {super(context);setMovementMethod(ScrollingMovementMethod.getInstance());}public ScrollTextView(Context context, AttributeSet attrs) {super(context, attrs);setMovementMethod(ScrollingMovementMethod.getInstance());}public ScrollTextView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);setMovementMethod(ScrollingMovementMethod.getInstance());}float lastScrollY = 0;@Overridepublic boolean onTouchEvent(MotionEvent ev) {if (getLineCount() > getMaxLines()) {if (ev.getAction() == MotionEvent.ACTION_DOWN) {lastScrollY = ev.getRawY();} else if (ev.getAction() == MotionEvent.ACTION_MOVE) {//滑动到头并且还在继续上滑动,或者滑动到底部就不要再拦截了(有误差)int sum = getLineHeight() * getLineCount() - getLineHeight() * getMaxLines();//计算上次与本次差float diff = lastScrollY - ev.getRawY();if (diff>0){//下滑动并且到达了底部也不要处理了//底部这里用abs的原因是,因为计算sum的时候有些误差if (Math.abs(sum - getScrollY())<5) {getParent().requestDisallowInterceptTouchEvent(false);} else {getParent().requestDisallowInterceptTouchEvent(true);}}else if (diff<0){//上滑动if (getScrollY() == 0) {//上滑动并且已经到达了顶部就不要在处理了getParent().requestDisallowInterceptTouchEvent(false);} else {getParent().requestDisallowInterceptTouchEvent(true);}}lastScrollY = ev.getRawY();} else {getParent().requestDisallowInterceptTouchEvent(false);}}return super.onTouchEvent(ev);}
}

如果上面方法不能解决你的问题,那就参考下面的文章,让textview实现 NestedScroolChild3 接口,并重写相应的方法,从而实现TextView嵌套滑动。

WebView 实现嵌套滑动,丝滑般实现吸顶效果,完美兼容 X5 webview

我使用的代码:

package com.**.view;
import android.annotation.SuppressLint;
import android.text.StaticLayout;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.text.Layout;
import android.text.TextPaint;
import android.text.method.ScrollingMovementMethod;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewParent;
import android.widget.OverScroller;
import android.widget.TextView;import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.view.NestedScrollingChild3;
import androidx.core.view.NestedScrollingChildHelper;
import androidx.core.view.ViewCompat;public class JustifyTextView extends androidx.appcompat.widget.AppCompatTextView implements NestedScrollingChild3 {private static final String TAG = "JustifyTextView";private int mLineY;private int mViewWidth;private static final int INVALID_POINTER = -1;private final int[] mScrollOffset = new int[2];private final int[] mScrollConsumed = new int[2];private int mLastMotionY;private NestedScrollingChildHelper mChildHelper;private boolean mIsBeingDragged = false;private VelocityTracker mVelocityTracker;private int mTouchSlop;private int mActivePointerId = INVALID_POINTER;private int mNestedYOffset;private OverScroller mScroller;private int mMinimumVelocity;private int mMaximumVelocity;private int mLastScrollerY;public JustifyTextView(Context context) {super(context);init();}public JustifyTextView(Context context, AttributeSet attrs) {super(context, attrs);init();}public JustifyTextView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init();}private void init() {mScroller = new OverScroller(getContext());setMovementMethod(ScrollingMovementMethod.getInstance());setOverScrollMode(TextView.OVER_SCROLL_NEVER);mChildHelper = new NestedScrollingChildHelper(this);setNestedScrollingEnabled(true);}@Overrideprotected void onLayout(boolean changed, int left, int top, int right, int bottom) {super.onLayout(changed, left, top, right, bottom);}@Overrideprotected void onDraw(Canvas canvas) {TextPaint paint = getPaint();paint.setColor(getCurrentTextColor());// 返回绘制状态的资源ID数组表示视图的当前状态paint.drawableState = getDrawableState();// 对View上的内容进行测量后得到的View内容占据的宽度// 前提是你必须在父布局的onLayout()方法或者此View的onDraw()方法里调用measure(0,0);// 否则你得到的结果和getWidth()得到的结果一样。mViewWidth = getMeasuredWidth();// 获取文本String text = getText().toString();mLineY = 0;mLineY += getTextSize();// 获取用于显示当前文本的布局Layout layout = getLayout();if (layout == null) {return;}Paint.FontMetrics fm = paint.getFontMetrics();int textHeight = (int) (Math.ceil(fm.descent - fm.ascent));textHeight = (int) (textHeight * layout.getSpacingMultiplier() + layout.getSpacingAdd());for (int i = 0; i < layout.getLineCount(); i++) {// 返回文本中的指定行开头的偏移int lineStart = layout.getLineStart(i);// 返回文本中的指定行最后一个字符的偏移int lineEnd = layout.getLineEnd(i);float width = StaticLayout.getDesiredWidth(text, lineStart, lineEnd, getPaint());String line = text.substring(lineStart, lineEnd);if (line.equals("")) {break;}if (i < layout.getLineCount() - 1) {if (needScale(line)) {drawScaledText(canvas, lineStart, line, width);} else {
//                    canvas.drawText(line.replace("%", ""), 0, mLineY, paint);canvas.drawText(line, 0, mLineY, paint);}} else {canvas.drawText(line, 0, mLineY, paint);}// 增加行高mLineY += textHeight;}}private void drawScaledText(Canvas canvas, int lineStart, String line,float lineWidth) {float x = 0;if (isFirstLineOfParagraph(lineStart, line)) {String blanks = "  ";canvas.drawText(blanks, x, mLineY, getPaint());float bw = StaticLayout.getDesiredWidth(blanks, getPaint());x += bw;line = line.substring(3);}int gapCount = line.length() - 1;int i = 0;if (line.length() > 2 && line.charAt(0) == 12288&& line.charAt(1) == 12288) {String substring = line.substring(0, 2);float cw = StaticLayout.getDesiredWidth(substring, getPaint());canvas.drawText(substring, x, mLineY, getPaint());x += cw;i += 2;}float d = (mViewWidth - lineWidth) / gapCount;for (; i < line.length(); i++) {String c = String.valueOf(line.charAt(i));float cw = StaticLayout.getDesiredWidth(c, getPaint());canvas.drawText(c, x, mLineY, getPaint());x += cw + d;}}private boolean isFirstLineOfParagraph(int lineStart, String line) {return line.length() > 3 && line.charAt(0) == ' ' && line.charAt(1) == ' ';}private boolean needScale(String line) {if (line.length() == 0) {return false;} else {
//            return line.charAt(line.length() - 1) != '%';return line.charAt(line.length() - 1) != '\n';}}@SuppressLint("ClickableViewAccessibility")@Overridepublic boolean onTouchEvent(MotionEvent ev) {initVelocityTrackerIfNotExists();MotionEvent vtev = MotionEvent.obtain(ev);final int actionMasked = ev.getActionMasked();if (actionMasked == MotionEvent.ACTION_DOWN) {mNestedYOffset = 0;}vtev.offsetLocation(0, mNestedYOffset);switch (actionMasked) {case MotionEvent.ACTION_DOWN:if ((mIsBeingDragged = !mScroller.isFinished())) {final ViewParent parent = getParent();if (parent != null) {parent.requestDisallowInterceptTouchEvent(true);}}if (!mScroller.isFinished()) {abortAnimatedScroll();}mLastMotionY = (int) ev.getY();mActivePointerId = ev.getPointerId(0);startNestedScroll(ViewCompat.SCROLL_AXIS_VERTICAL, ViewCompat.TYPE_TOUCH);break;case MotionEvent.ACTION_MOVE:final int activePointerIndex = ev.findPointerIndex(mActivePointerId);if (activePointerIndex == -1) {Log.e(TAG, "Invalid pointerId=" + mActivePointerId + " in onTouchEvent");break;}final int y = (int) ev.getY(activePointerIndex);int deltaY = mLastMotionY - y;if (dispatchNestedPreScroll(0, deltaY, mScrollConsumed, mScrollOffset,ViewCompat.TYPE_TOUCH)) {deltaY -= mScrollConsumed[1];mNestedYOffset += mScrollOffset[1];}if (!mIsBeingDragged && Math.abs(deltaY) > mTouchSlop) {final ViewParent parent = getParent();if (parent != null) {parent.requestDisallowInterceptTouchEvent(true);}mIsBeingDragged = true;if (deltaY > 0) {deltaY -= mTouchSlop;} else {deltaY += mTouchSlop;}}if (mIsBeingDragged) {mLastMotionY = y - mScrollOffset[1];final int oldY = getScrollY();final int range = getScrollRange();// Calling overScrollByCompat will call onOverScrolled, which// calls onScrollChanged if applicable.if (overScrollByCompat(0, deltaY, 0, oldY, 0, range, 0,0, true) && !hasNestedScrollingParent(ViewCompat.TYPE_TOUCH)) {mVelocityTracker.clear();}final int scrolledDeltaY = getScrollY() - oldY;final int unconsumedY = deltaY - scrolledDeltaY;mScrollConsumed[1] = 0;dispatchNestedScroll(0, scrolledDeltaY, 0, unconsumedY, mScrollOffset,ViewCompat.TYPE_TOUCH, mScrollConsumed);mLastMotionY -= mScrollOffset[1];mNestedYOffset += mScrollOffset[1];}break;case MotionEvent.ACTION_UP:final VelocityTracker velocityTracker = mVelocityTracker;velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);int initialVelocity = (int) velocityTracker.getYVelocity(mActivePointerId);if ((Math.abs(initialVelocity) > mMinimumVelocity)) {if (!dispatchNestedPreFling(0, -initialVelocity)) {dispatchNestedFling(0, -initialVelocity, true);fling(-initialVelocity);}} else if (mScroller.springBack(getScrollX(), getScrollY(), 0, 0, 0,getScrollRange())) {ViewCompat.postInvalidateOnAnimation(this);}mActivePointerId = INVALID_POINTER;endDrag();break;case MotionEvent.ACTION_CANCEL:if (mIsBeingDragged) {if (mScroller.springBack(getScrollX(), getScrollY(), 0, 0, 0,getScrollRange())) {ViewCompat.postInvalidateOnAnimation(this);}}mActivePointerId = INVALID_POINTER;endDrag();break;case MotionEvent.ACTION_POINTER_DOWN:final int index = ev.getActionIndex();mLastMotionY = (int) ev.getY(index);mActivePointerId = ev.getPointerId(index);break;case MotionEvent.ACTION_POINTER_UP:onSecondaryPointerUp(ev);mLastMotionY = (int) ev.getY(ev.findPointerIndex(mActivePointerId));break;}if (mVelocityTracker != null) {mVelocityTracker.addMovement(vtev);}vtev.recycle();return super.onTouchEvent(ev);}private void abortAnimatedScroll() {mScroller.abortAnimation();stopNestedScroll(ViewCompat.TYPE_NON_TOUCH);}private void endDrag() {mIsBeingDragged = false;recycleVelocityTracker();stopNestedScroll();}private void onSecondaryPointerUp(MotionEvent ev) {final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK)>> MotionEvent.ACTION_POINTER_INDEX_SHIFT;final int pointerId = ev.getPointerId(pointerIndex);if (pointerId == mActivePointerId) {final int newPointerIndex = pointerIndex == 0 ? 1 : 0;mLastMotionY = (int) ev.getY(newPointerIndex);mActivePointerId = ev.getPointerId(newPointerIndex);if (mVelocityTracker != null) {mVelocityTracker.clear();}}}private void fling(int velocityY) {int height = getHeight();mScroller.fling(getScrollX(), getScrollY(), // start0, velocityY, // velocities0, 0, // xInteger.MIN_VALUE, Integer.MAX_VALUE, // y0, height / 2);runAnimatedScroll(true);}private void runAnimatedScroll(boolean participateInNestedScrolling) {if (participateInNestedScrolling) {startNestedScroll(ViewCompat.SCROLL_AXIS_VERTICAL, ViewCompat.TYPE_NON_TOUCH);} else {stopNestedScroll(ViewCompat.TYPE_NON_TOUCH);}mLastScrollerY = getScrollY();ViewCompat.postInvalidateOnAnimation(this);}private void initOrResetVelocityTracker() {if (mVelocityTracker == null) {mVelocityTracker = VelocityTracker.obtain();} else {mVelocityTracker.clear();}}private void initVelocityTrackerIfNotExists() {if (mVelocityTracker == null) {mVelocityTracker = VelocityTracker.obtain();}}private void recycleVelocityTracker() {if (mVelocityTracker != null) {mVelocityTracker.recycle();mVelocityTracker = null;}}@Overrideprotected boolean overScrollBy(int deltaX, int deltaY,int scrollX, int scrollY,int scrollRangeX, int scrollRangeY,int maxOverScrollX, int maxOverScrollY,boolean isTouchEvent) {// this is causing double scroll call (doubled speed), but this WebView isn't overscrollable// all overscrolls are passed to appbar, so commenting this out during dragif (!mIsBeingDragged)overScrollByCompat(deltaX, deltaY, scrollX, scrollY, scrollRangeX, scrollRangeY,maxOverScrollX, maxOverScrollY, isTouchEvent);// without this call webview won't scroll to top when url change or when user pick input// (webview should move a bit making input still in viewport when "adjustResize")return true;}int getScrollRange() {//Using scroll range of webview instead of childs as NestedScrollView does.return computeVerticalScrollRange();}@Overridepublic boolean isNestedScrollingEnabled() {return mChildHelper.isNestedScrollingEnabled();}@Overridepublic void setNestedScrollingEnabled(boolean enabled) {mChildHelper.setNestedScrollingEnabled(enabled);}@Overridepublic boolean startNestedScroll(int axes, int type) {return mChildHelper.startNestedScroll(axes, type);}@Overridepublic boolean startNestedScroll(int axes) {return startNestedScroll(axes, ViewCompat.TYPE_TOUCH);}@Overridepublic void stopNestedScroll(int type) {mChildHelper.stopNestedScroll(type);}@Overridepublic void stopNestedScroll() {stopNestedScroll(ViewCompat.TYPE_TOUCH);}@Overridepublic boolean hasNestedScrollingParent(int type) {return mChildHelper.hasNestedScrollingParent(type);}@Overridepublic boolean hasNestedScrollingParent() {return hasNestedScrollingParent(ViewCompat.TYPE_TOUCH);}@Overridepublic boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed,int[] offsetInWindow) {return dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed,offsetInWindow, ViewCompat.TYPE_TOUCH);}@Overridepublic boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed,int[] offsetInWindow, int type) {return mChildHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed,offsetInWindow, type);}@Overridepublic void dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed,@Nullable int[] offsetInWindow, int type, @NonNull int[] consumed) {mChildHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed,offsetInWindow, type, consumed);}@Overridepublic boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) {return dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow, ViewCompat.TYPE_TOUCH);}@Overridepublic boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow, int type) {return mChildHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow, type);}@Overridepublic boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {return mChildHelper.dispatchNestedFling(velocityX, velocityY, false);}@Overridepublic boolean dispatchNestedPreFling(float velocityX, float velocityY) {return mChildHelper.dispatchNestedPreFling(velocityX, velocityY);}@Overridepublic void computeScroll() {if (mScroller.isFinished()) {return;}mScroller.computeScrollOffset();final int y = mScroller.getCurrY();int unconsumed = y - mLastScrollerY;mLastScrollerY = y;// Nested Scrolling Pre PassmScrollConsumed[1] = 0;dispatchNestedPreScroll(0, unconsumed, mScrollConsumed, null,ViewCompat.TYPE_NON_TOUCH);unconsumed -= mScrollConsumed[1];if (unconsumed != 0) {// Internal Scrollfinal int oldScrollY = getScrollY();overScrollByCompat(0, unconsumed, getScrollX(), oldScrollY, 0, getScrollRange(),0, 0, false);final int scrolledByMe = getScrollY() - oldScrollY;unconsumed -= scrolledByMe;// Nested Scrolling Post PassmScrollConsumed[1] = 0;dispatchNestedScroll(0, 0, 0, unconsumed, mScrollOffset,ViewCompat.TYPE_NON_TOUCH, mScrollConsumed);unconsumed -= mScrollConsumed[1];}if (unconsumed != 0) {abortAnimatedScroll();}if (!mScroller.isFinished()) {ViewCompat.postInvalidateOnAnimation(this);}}// copied from NestedScrollView exacly as it looks, leaving overscroll related code, maybe future useprivate boolean overScrollByCompat(int deltaX, int deltaY,int scrollX, int scrollY,int scrollRangeX, int scrollRangeY,int maxOverScrollX, int maxOverScrollY,boolean isTouchEvent) {final int overScrollMode = getOverScrollMode();final boolean canScrollHorizontal =computeHorizontalScrollRange() > computeHorizontalScrollExtent();final boolean canScrollVertical =computeVerticalScrollRange() > computeVerticalScrollExtent();final boolean overScrollHorizontal = overScrollMode == View.OVER_SCROLL_ALWAYS|| (overScrollMode == View.OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);final boolean overScrollVertical = overScrollMode == View.OVER_SCROLL_ALWAYS|| (overScrollMode == View.OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);int newScrollX = scrollX + deltaX;if (!overScrollHorizontal) {maxOverScrollX = 0;}int newScrollY = scrollY + deltaY;if (!overScrollVertical) {maxOverScrollY = 0;}// Clamp values if at the limits and recordfinal int left = -maxOverScrollX;final int right = maxOverScrollX + scrollRangeX;final int top = -maxOverScrollY;final int bottom = maxOverScrollY + scrollRangeY;boolean clampedX = false;if (newScrollX > right) {newScrollX = right;clampedX = true;} else if (newScrollX < left) {newScrollX = left;clampedX = true;}boolean clampedY = false;if (newScrollY > bottom) {newScrollY = bottom;clampedY = true;} else if (newScrollY < top) {newScrollY = top;clampedY = true;}if (clampedY && !hasNestedScrollingParent(ViewCompat.TYPE_NON_TOUCH)) {mScroller.springBack(newScrollX, newScrollY, 0, 0, 0, getScrollRange());}onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);return clampedX || clampedY;}
}

分享:

定时垂直滚动的textview:GitHub - paradoxie/AutoVerticalTextview: 垂直滚动的textview,继承自TextSwitcher,抽出一个依赖库供以后备用

左右对齐的TextView

GitHub - Giftedcat/JustifyTextView: 左右对齐的TextView,适配各种分辨率,完美实现UI需求

 JustifyTextView 自定义TextView解决中文排版-CSDN博客

相关文章:

Android 解决TextView多行滑动与NestedScrollView嵌套滑动冲突的问题

关键计算地方: 1.当前是上滑动还是下滑动(相对于屏幕) ,使用ev.getRawY()获得当前滑动位置在屏幕哪个地方 2. 计算文本客滑动到哪里即可停止, (行高*总文本行数)- (行高 * 最多显示行数) int sum getLineHeight() * getLineCount() - getLineHeight() * getMaxLines(); …...

Laravel 开发Api规范

一&#xff0c;修改时区 配置 config/app.php 文件 // 时区修改&#xff0c;感觉两者皆可&#xff0c;自己根据实际情况定义 timezone > PRC, // 大陆时间二&#xff0c;设置 Accept 头中间件 accept头即为客户端请求头&#xff0c;做成中间件来使用。Accept 决定了响应返…...

蓝色wordpress外贸建站模板

蓝色wordpress外贸建站模板 https://www.mymoban.com/wordpress/7.html...

windos环境,使用docker容器运行项目的,新增外部访问地址配置

对于运行在 Docker 容器中的项目&#xff0c;你需要在容器内部编辑 resolv.conf 文件。以下是一种常见的方法&#xff1a; 进入正在运行的 Docker 容器&#xff1a;docker exec -it [container_id] bash其中 [container_id] 是你正在运行的 Docker 容器的 ID。 在容器内部使…...

设计模式:生活中的组合模式

想象一下&#xff0c;你正在组织一个大型的家庭聚会。在这个聚会中&#xff0c;你需要准备各种菜肴&#xff0c;每个菜肴又包含不同的食材。你的目标是能够以统一的方式处理整个聚会的准备工作&#xff0c;不论是处理单个食材还是一整道菜肴。 在这个场景中&#xff0c;我们可…...

WPF OnStartup

在Windows Presentation Foundation (WPF)框架中&#xff0c;OnStartup 是 System.Windows.Application 类的一个受保护的虚方法&#xff0c;它是应用程序启动过程中的一个重要环节。当一个 WPF 应用程序启动时&#xff0c;其入口点通常是 App.xaml 文件和对应的后台代码文件 A…...

docker-相关

打镜像 1、编写dockfile文件&#xff0c;请自行百度 2、docker build -t 镜像名称:版本号 dockerFile路径 3、docker save -o 镜像压缩包名称.tar 镜像名称:镜像版本号 部署镜像 1、将镜像tar包放到部署机器上 2、加载镜像&#xff1a;docker load -i 镜像tar包路径 3、dock…...

二十、Rust AOP 切面增强

用过 java spring 的同学&#xff0c;应该会对 AspectJ 的 前置、后置、环绕 增强 念念不忘&#xff0c;巧了 rust 也有类似能力&#xff0c;稍显不同的是&#xff0c;为了向 “零成本抽象” 靠齐&#xff0c;Rust 的 “增强” 是在编译期 完成的。 编译期生成&#xff0c;则离…...

掌握Go语言:Go语言精细错误,清晰、高效的错误处理实践(32)

错误处理是任何编程语言中都至关重要的一部分&#xff0c;Go 语言提供了一套简单而强大的错误处理机制&#xff0c;使得处理错误变得高效而清晰。 Go 错误类型 在 Go 中&#xff0c;错误是一个普通的接口类型&#xff0c;即 error 接口&#xff0c;其定义如下&#xff1a; t…...

Spring与Web环境的集成

1. ApplicationContext应用上下文获取方式 应用上下文对象是通过new ClasspathXmlApplicationContext(spring配置文件) 方式获取的&#xff0c;但是每次从容器中获得Bean时都要编写new ClasspathXmlApplicationContext(spring配置文件) &#xff0c;这样的弊端是配置文件加载多…...

二叉树的遍历——bfs广度优先搜索

1、BinNode类的创建 &#xff08;1&#xff09;代码总览 ##&#xff08;2&#xff09;测试示例 2、二叉树的遍历 &#xff08;1&#xff09;图示 &#xff08;2&#xff09;代码总览 &#xff08;3&#xff09;测试示例...

飞鸟写作可靠吗 #职场发展#经验分享#经验分享

飞鸟写作是一个非常便捷的论文写作工具&#xff0c;不仅可以帮助用户高效地完成论文写作&#xff0c;还可以提供查重降重的功能&#xff0c;帮助用户确保论文的原创性。那么&#xff0c;飞鸟写作到底可靠吗&#xff1f;答案是肯定的。 首先&#xff0c;飞鸟写作提供的查重降重功…...

Java 实现自定义注解

一、interface 关键字 我们想定义一个自己的注解 需要使用 interface 关键字来定义。 如定义一个叫 MyAnnotation 的注解&#xff1a; public interface MyAnnotation { } 二、元注解 光加上 interface 关键字 还不够&#xff0c;我们还需要了解5大元注解 RetentionTargetDo…...

代码随想录Day48

Day 48 动态规划part09 今日任务 198.打家劫舍213.打家劫舍II337.打家劫舍III 代码实现 基础打家劫舍 class Solution {public static int rob(int[] nums) {if (nums null || nums.length 0) return 0;if (nums.length 1) return nums[0];int[] dp new int[nums.leng…...

Web 后台项目,权限如何定义、设置、使用:菜单权限、按钮权限 ts element-ui-Plus

Web 后台项目&#xff0c;权限如何定义、设置、使用&#xff1a;菜单权限、按钮权限 ts element-ui-Plus 做一个后台管理项目&#xff0c;里面需要用到权限管理。这里说一下权限定义的大概&#xff0c;代码不多&#xff0c;主要讲原理和如何实现它。 一、权限管理的原理 权限…...

ADB 操作命令及其详细用法

adb devices 用途&#xff1a;列出连接到计算机的所有 Android 设备。详解&#xff1a;执行该命令后&#xff0c;ADB 将扫描连接到计算机的所有 Android 设备&#xff0c;并列出它们的序列号。 adb connect <device> 用途&#xff1a;连接到指定 IP 地址的 Android 设备。…...

类的函数成员(三):拷贝构造函数

一.什么是拷贝构造函数&#xff1f; 1.1 概念 同一个类的对象在内存中有完全相同的结构&#xff0c;如果作为一个整体进行复制或称拷贝是完全可行的。这个拷贝过程只需要拷贝数据成员&#xff0c;而函数成员是共用的&#xff08;只有一份拷贝&#xff09;。 在建立对象…...

C#操作MySQL从入门到精通(8)——对查询数据进行高级过滤

前言 我们在查询数据库中数据的时候,有时候需要剔除一些我们不想要的数据,这时候就需要对数据进行过滤,比如学生信息中,我只需要年龄等于18的,同时又要家乡地址是安徽的,类似这种操作专栏第7篇的C#操作MySQL从入门到精通(7)——对查询数据进行简单过滤简单过滤方法就无法…...

Centos 7 安装通过yum安装google浏览器

在CentOS 7上使用yum安装Google Chrome浏览器稍微复杂一些&#xff0c;因为Chrome并不直接包含在默认的Yum仓库中。按照以下步骤来操作&#xff1a; 1、添加Google Chrome仓库 首先&#xff0c;您需要手动添加Google Chrome的Yum仓库。打开终端&#xff0c;并使用文本编辑器&a…...

题目:学习使用按位与 。

题目&#xff1a;学习使用按位与 & 。   There is no nutrition in the blog content. After reading it, you will not only suffer from malnutrition, but also impotence. The blog content is all parallel goods. Those who are worried about being cheated shoul…...

7.4.分块查找

一.分块查找的算法思想&#xff1a; 1.实例&#xff1a; 以上述图片的顺序表为例&#xff0c; 该顺序表的数据元素从整体来看是乱序的&#xff0c;但如果把这些数据元素分成一块一块的小区间&#xff0c; 第一个区间[0,1]索引上的数据元素都是小于等于10的&#xff0c; 第二…...

synchronized 学习

学习源&#xff1a; https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖&#xff0c;也要考虑性能问题&#xff08;场景&#xff09; 2.常见面试问题&#xff1a; sync出…...

docker详细操作--未完待续

docker介绍 docker官网: Docker&#xff1a;加速容器应用程序开发 harbor官网&#xff1a;Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台&#xff0c;用于将应用程序及其依赖项&#xff08;如库、运行时环…...

Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)

目录 1.TCP的连接管理机制&#xff08;1&#xff09;三次握手①握手过程②对握手过程的理解 &#xff08;2&#xff09;四次挥手&#xff08;3&#xff09;握手和挥手的触发&#xff08;4&#xff09;状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...

cf2117E

原题链接&#xff1a;https://codeforces.com/contest/2117/problem/E 题目背景&#xff1a; 给定两个数组a,b&#xff0c;可以执行多次以下操作&#xff1a;选择 i (1 < i < n - 1)&#xff0c;并设置 或&#xff0c;也可以在执行上述操作前执行一次删除任意 和 。求…...

Keil 中设置 STM32 Flash 和 RAM 地址详解

文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...

ServerTrust 并非唯一

NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...

ardupilot 开发环境eclipse 中import 缺少C++

目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...

【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)

升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点&#xff0c;但无自动故障转移能力&#xff0c;Master宕机后需人工切换&#xff0c;期间消息可能无法读取。Slave仅存储数据&#xff0c;无法主动升级为Master响应请求&#xff…...

使用 SymPy 进行向量和矩阵的高级操作

在科学计算和工程领域&#xff0c;向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能&#xff0c;能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作&#xff0c;并通过具体…...