拖动布局的两种方式

news2025/1/16 0:57:42

一种是弹窗的拖动布局,一种是非弹窗。

代码如下:

非弹窗:这里加载了一个本地的视频

import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.widget.MediaController;
import android.widget.VideoView;

import androidx.appcompat.app.AppCompatActivity;

public class MoveActivity extends AppCompatActivity implements View.OnTouchListener{
    private VideoView video;
    private int sx;
    private int sy;
    private SharedPreferences sp;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_move);
        if (getSupportActionBar() != null){
            getSupportActionBar().hide();
        }
        sp = this.getSharedPreferences("config", Context.MODE_PRIVATE);
        video = this.findViewById(R.id.video_view);
        video.setVideoPath("android.resource://" + this.getPackageName() + "/" + R.raw.videos);
        video.setOnTouchListener(this);
        //创建MediaController对象
        MediaController mediaController = new MediaController(this);
        video.setMediaController(mediaController); //让videoView 和 MediaController相关联
        video.setFocusable(true); //让VideoView获得焦点
        video.start(); //开始播放视频
    }

    @Override
    protected void onResume() {
        super.onResume();
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (v.getId()) {
            // 如果手指放在imageView上拖动
            case R.id.video_view:
                // event.getRawX(); //获取手指第一次接触屏幕在x方向的坐标
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:// 获取手指第一次接触屏幕
                        sx = (int) event.getRawX();
                        sy = (int) event.getRawY();
                        break;
                    case MotionEvent.ACTION_MOVE:// 手指在屏幕上移动对应的事件
                        int x = (int) event.getRawX();
                        int y = (int) event.getRawY();
                        // 获取手指移动的距离
                        int dx = x - sx;
                        int dy = y - sy;
                        // 得到imageView最开始的各顶点的坐标
                        int l = video.getLeft();
                        int r = video.getRight();
                        int t = video.getTop();
                        int b = video.getBottom();
                        // 更改imageView在窗体的位置
                        video.layout(l + dx, t + dy, r + dx, b + dy);
                        // 获取移动后的位置
                        sx = (int) event.getRawX();
                        sy = (int) event.getRawY();
                        break;
                    case MotionEvent.ACTION_UP:// 手指离开屏幕对应事件
                        // 记录最后图片在窗体的位置
                        int lasty = video.getTop();
                        int lastx = video.getLeft();
                        SharedPreferences.Editor editor = sp.edit();
                        editor.putInt("lasty", lasty);
                        editor.putInt("lastx", lastx);
                        editor.commit();
                        break;
                }
                break;
        }
        return true;// 不会中断触摸事件的返回
    }
}

布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal">


    <com.example.mymovevideo.tools.ConditionVideoView
        android:id="@+id/video_view"
        android:layout_width="100dp"
        android:layout_height="100dp" />
</LinearLayout>

弹窗试:弹窗加载一个视频

import androidx.appcompat.app.AppCompatActivity;

import android.Manifest;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.View;

import com.example.mymovevideo.databinding.ActivityMainBinding;
import com.example.mymovevideo.tools.HomeWatcher;
import com.example.mymovevideo.tools.SmallWindowsView;

import pub.devrel.easypermissions.EasyPermissions;

public class MainActivity extends AppCompatActivity {
    SmallWindowsView smallWindowsView;
    ActivityMainBinding mainBinding;
    private HomeWatcher mHomeWatcher;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mainBinding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(mainBinding.getRoot());
        smallWindowsView = new SmallWindowsView(MainActivity.this);
        mainBinding.btShowWindow.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (Build.VERSION.SDK_INT >= 23) {
                    if (!(Settings.canDrawOverlays(MainActivity.this))) {
                        Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
                        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                        startActivity(intent);
                        return;
                    }
                } else {
                    if (!EasyPermissions.hasPermissions(MainActivity.this, Manifest.permission.SYSTEM_ALERT_WINDOW)) {
                        EasyPermissions.requestPermissions(MainActivity.this, "需要权限用以展示悬浮窗",
                                2048, Manifest.permission.SYSTEM_ALERT_WINDOW);
                        return;
                    }
                }
                smallWindowsView.show();
                mainBinding.btShowWindow.setClickable(false);
            }
        });

        mHomeWatcher = new HomeWatcher(this);
        mHomeWatcher.setOnHomePressedListener(new HomeWatcher.OnHomePressedListener() {
            @Override
            public void onHomePressed() {
                smallWindowsView.dismiss();
                mainBinding.btShowWindow.setClickable(true);
            }

            @Override
            public void onHomeLongPressed() {
                smallWindowsView.dismiss();
                mainBinding.btShowWindow.setClickable(true);
            }
        });
        mHomeWatcher.startWatch();

    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        //按下BACK键
        if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
            smallWindowsView.dismiss();
            mainBinding.btShowWindow.setClickable(true);
        }
        return super.onKeyDown(keyCode, event);
    }

    @Override
    public void onOptionsMenuClosed(Menu menu) {
        super.onOptionsMenuClosed(menu);
        smallWindowsView.dismiss();
        mainBinding.btShowWindow.setClickable(true);
    }
}

布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/white"
    android:orientation="vertical">

    <Button
        android:text="展示滑动布局"
        android:id="@+id/bt_show_window"
        android:layout_width="match_parent"
        android:layout_height="50dp"/>

</LinearLayout>

工具类:

import android.content.Context;
import android.util.AttributeSet;
import android.widget.VideoView;

public class ConditionVideoView extends VideoView {
    public ConditionVideoView(Context context) {
        super(context);
    }
    public ConditionVideoView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    public ConditionVideoView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        //使视频全屏播放
        int width = getDefaultSize(0, widthMeasureSpec);
        int height = getDefaultSize(0, heightMeasureSpec);
        setMeasuredDimension(width, height);
    }
}
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
public class HomeWatcher {
    private Context mContext;
    private IntentFilter mFilter;
    private OnHomePressedListener mListener;
    private InnerRecevier mRecevier;
    // 回调接口
    public interface OnHomePressedListener {
        public void onHomePressed();
        public void onHomeLongPressed();
    }

    public HomeWatcher(Context context) {
        mContext = context;
        mRecevier = new InnerRecevier();
        mFilter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
    }

    /**
     * 设置监听
     *
     * @param listener
     */
    public void setOnHomePressedListener(OnHomePressedListener listener) {
        mListener = listener;
    }

    /**
     * 开始监听,注册广播
     */

    public void startWatch() {
        if (mRecevier != null) {
            mContext.registerReceiver(mRecevier, mFilter);
        }
    }

    /**
     * 广播接收者
     */
    class InnerRecevier extends BroadcastReceiver {
        final String SYSTEM_DIALOG_REASON_KEY = "reason";
        final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
        final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";

        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (action.equals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)) {
                String reason = intent.getStringExtra(SYSTEM_DIALOG_REASON_KEY);
                if (reason != null) {
                    if (mListener != null) {
                        if (reason.equals(SYSTEM_DIALOG_REASON_HOME_KEY)) {
                            // 短按home键
                            mListener.onHomePressed();
                        } else if (reason.equals(SYSTEM_DIALOG_REASON_RECENT_APPS)) {
                            // 长按home键
                            mListener.onHomeLongPressed();
                        }
                    }
                }
            }
        }
    }
}
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

public class HomeWatcherReceiver extends BroadcastReceiver {
    private static final String LOG_TAG = "HomeReceiver";
    private static final String SYSTEM_DIALOG_REASON_KEY = "reason";
    private static final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
    private static final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";
    private static final String SYSTEM_DIALOG_REASON_LOCK = "lock";
    private static final String SYSTEM_DIALOG_REASON_ASSIST = "assist";

    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (action.equals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)) {
            String reason = intent.getStringExtra(SYSTEM_DIALOG_REASON_KEY);
            Log.i(LOG_TAG, "reason: " + reason);

            if (SYSTEM_DIALOG_REASON_HOME_KEY.equals(reason)) {
                // 短按Home键
                Log.i(LOG_TAG, "homekey");

            }
            else if (SYSTEM_DIALOG_REASON_RECENT_APPS.equals(reason)) {
                // 长按Home键 或者 activity切换键
                Log.i(LOG_TAG, "long press home key or activity switch");

            }
            else if (SYSTEM_DIALOG_REASON_LOCK.equals(reason)) {
                // 锁屏
                Log.i(LOG_TAG, "lock");
            }
            else if (SYSTEM_DIALOG_REASON_ASSIST.equals(reason)) {
                // samsung 长按Home键
                Log.i(LOG_TAG, "assist");
            }
        }
    }

}
import android.content.Context;
import android.graphics.PixelFormat;
import android.os.Build;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.MediaController;
import android.widget.VideoView;

import androidx.annotation.NonNull;
import androidx.camera.lifecycle.ProcessCameraProvider;
import androidx.core.content.ContextCompat;

import com.example.mymovevideo.R;
import com.google.common.util.concurrent.ListenableFuture;

import java.util.concurrent.ExecutionException;

public class SmallWindowsView extends FrameLayout {

    private int mSlop;//触发移动事件的最小距离
    private float downX;//手指放下去的x坐标
    private float downY;//手指放下去的Y坐标
    /**
     * 下面四个数据都为像素
     */
    private int screenWidth;//屏幕宽度
    private int screenHeight;//屏幕高度
    private int viewWidth;//小窗的宽度
    private int viewHeight;//小窗的高度

    private WindowManager wm;//窗口管理器,用来把view添加进窗口层
    private WindowManager.LayoutParams wmParams;

    private ProcessCameraProvider mCameraProvider;
    private ListenableFuture<ProcessCameraProvider> mCameraProviderFuture;

    public SmallWindowsView(@NonNull Context context) {
        super(context);
        init(context);
    }

    private void init(Context context) {
        ViewConfiguration vc = ViewConfiguration.get(getContext());
        // 窗口里的布局
        View view = View.inflate(context, R.layout.view_floating_window, null);
        mSlop = vc.getScaledTouchSlop();
        screenWidth = getContext().getResources().getDisplayMetrics().widthPixels;
        screenHeight = getContext().getResources().getDisplayMetrics().heightPixels;
        viewWidth = dp2px(getContext(), 130);
        viewHeight = dp2px(getContext(), 130);

        mCameraProviderFuture = ProcessCameraProvider.getInstance(context);
        mCameraProviderFuture.addListener(() -> {
            try {
                mCameraProvider = mCameraProviderFuture.get();
            } catch (ExecutionException | InterruptedException e) {
                // 这里不用处理
            }
        }, ContextCompat.getMainExecutor(context));

        VideoView video = view.findViewById(R.id.videoView);
        video.setVideoPath("android.resource://" + context.getPackageName() + "/" + R.raw.videos);
        /**
         * 控制视频的播放 主要通过MediaController控制视频的播放
         */
        //创建MediaController对象
        MediaController mediaController = new MediaController(context);
        video.setMediaController(mediaController); //让videoView 和 MediaController相关联
        video.setFocusable(true); //让VideoView获得焦点
        video.start(); //开始播放视频

        // 实际上就是拿到一个View从WindowManager给addView进去
        LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT);
        addView(view, params);

    }

    //dp转px
    public int dp2px(Context context, int dp) {
        return (int) (getDensity(context) * dp + 0.5);
    }

    public float getDensity(Context context) {
        return context.getResources().getDisplayMetrics().density;
    }

    public void show() {
        wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
        wmParams = new WindowManager.LayoutParams(
                viewWidth, viewHeight,
                WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,//8.0以上需要用这个权限
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                        | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
                PixelFormat.TRANSLUCENT);
        wmParams.gravity = Gravity.NO_GRAVITY;
        wmParams.x = screenWidth / 2 - viewWidth / 2;
        wmParams.y = screenHeight / 2 - viewHeight / 2;
        // 适配8.0以上
        if (Build.VERSION.SDK_INT > 24) {
            wmParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
        } else {
            wmParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
        }
        wm.addView(this, wmParams);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    //拦截触摸事件自己消费
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return true;
    }

    private long downTime;
    private float lastMoveX;
    private float lastMoveY;

    //消费触摸事件
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                downX = event.getRawX();
                downY = event.getRawY();
                lastMoveX = downX;
                lastMoveY = downY;
                downTime = System.currentTimeMillis();
                break;
            case MotionEvent.ACTION_MOVE:
                float moveX = event.getRawX();
                float moveY = event.getRawY();
                //就两个坐标算他们距离要大于触发移动事件的最小距离
                //这里也可以减去lastMoveX lastMoveY 但是移动会有卡顿感 因此这里使用的还是downX downY
                if (Math.pow(Math.abs(moveX - downX), 2) + Math.pow(Math.abs(moveY - downY), 2) > Math.pow(mSlop, 2)) {
                    updateViewPosition(moveX - lastMoveX, moveY - lastMoveY);
                    lastMoveX = moveX;
                    lastMoveY = moveY;
                }

                break;
            case MotionEvent.ACTION_UP:
                float upX = event.getRawX();
                float upY = event.getRawY();
                long upTime = System.currentTimeMillis();
                long time = upTime - downTime;
                //点击事件实现 点击小窗口消失
                //这里加了时间判断,是因为假如移动到原来的地方,也会触发成点击事件
                if (Math.pow(Math.abs(upX - downX), 2) + Math.pow(Math.abs(upY - downY), 2) < Math.pow(mSlop, 2) && time < 1000) {
                    showRtcVideo();
                }
                break;
        }
        return true;
    }

    private void showRtcVideo() {
        dismiss();
    }

    public void dismiss() {
        if (null != wm) {
            wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
            wm.removeView(this);
        }
    }

    private void updateViewPosition(float moveX, float moveY) {
        wmParams.gravity = Gravity.NO_GRAVITY;
        //更新浮动窗口位置参数
        wmParams.x = (int) (wmParams.x + moveX);
        wmParams.y = (int) (wmParams.y + moveY);
        //刷新显示
        wm.updateViewLayout(this, wmParams);
    }
}

工具类布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/cardview_light_background"
    android:orientation="vertical">

    <com.example.mymovevideo.tools.ConditionVideoView
        android:id="@+id/videoView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

配置文件:

plugins {
    id 'com.android.application'
}

android {
    namespace 'com.example.mymovevideo'
    compileSdk 32

    defaultConfig {
        applicationId "com.example.mymovevideo"
        minSdk 21
        targetSdk 32
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    dataBinding {
        enabled = true
    }

    viewBinding {
        enabled = true
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {

    implementation 'pub.devrel:easypermissions:3.0.0'

    implementation "androidx.camera:camera-core:1.1.0-alpha11"
    implementation "androidx.camera:camera-camera2:1.1.0-alpha11"
    implementation "androidx.camera:camera-lifecycle:1.1.0-alpha11"
    implementation "androidx.camera:camera-view:1.0.0-alpha31"
    implementation "androidx.camera:camera-extensions:1.0.0-alpha31"

    implementation 'androidx.appcompat:appcompat:1.4.1'
    implementation 'com.google.android.material:material:1.5.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}

清单文件

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <uses-permission android:name="android.permission.INTERNET"/>
    <!-- 授予该程序移动窗口的权限 -->
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
    <!-- 授予该程序使用摄像头的权限 -->
    <uses-permission android:name="android.permission.CAMERA"/>
    <!-- 授予使用外部存储器的权限 -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.AppCompat.NoActionBar"
        tools:targetApi="31">
        <activity
            android:name=".MoveActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>

            <meta-data
                android:name="android.app.lib_name"
                android:value="" />
        </activity>
    </application>

</manifest>

视频文件:

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/101026.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Go1.19.3 map原理简析

map简析 map是一个集数组与链表(美貌与智慧)特性于一身的数据结构&#xff0c;其增删改查时间复杂度都非常优秀&#xff0c;在很多场景下用其替代树结构。关于map的特性请自行学习。 Go语言在语言层面就支持了map&#xff0c;而非其他语言(如Java)通过外置类库的方式实现。 使…

【LSSVM回归预测】基于matlab天鹰算法优化最小二乘支持向量机AO-LSSVM数据回归预测【含Matlab源码 1848期】

⛄一、天鹰算法优化最小二乘支持向量机LSSVM简介 1 最小二乘支持向量机 最小二乘支持向量机是支持向量机的一种改进算法[9,10],它将SVM算法中的不等式约束转化为等式约束,采用最小二乘线性系统作为损失函数代替支持向量机所采用的二次规划方法,以下介绍了该方法的基本原理。 …

DSPE-PEG-DBCO磷脂聚乙二醇二苯基环辛炔简介

名称 磷脂聚乙二醇二苯基环辛炔 DSPE-PEG-DBCO 中文名称 二硬脂酰基磷脂酰乙醇胺-聚乙二醇-二苯基环辛炔 英文名称 DSPE-PEG-DBCO 溶剂 部分常规有机溶剂 存储条件 -20冷冻保存&#xff0c;惰性气体保护 保存时间 1年 PEG常规分子量 2000 3400 5000 DSPE-PEG-DBCO DSPE&a…

typescript 类型运算探讨

以函数的方式来看typescript 类型运算尖括号 <>TypeScript 类型运算符1、extends2、keyof3、infer4、in题目示例对于初接触typescript的前端开发者来说&#xff0c;我们可能会对typescript的类型运算感到很陌生和难以理解。现在想说的是&#xff0c;其实我们可以换另外一…

我国服务行业体经济尽显强大韧性 2021年全年总体保持恢复性增长态势

根据观研报告网发布的《2022年中国服务行业分析报告-行业发展监测与投资潜力分析》显示&#xff0c;所谓服务业&#xff0c;不是指商品的买卖&#xff0c;而是指通过各种不同的服务工作&#xff0c;让顾客得到满足。 服务业有传统服务业与现代服务业之分。传统服务业是指为人们…

【云原生进阶之容器】第一章Docker核心技术1.7节——Docker镜像技术剖析

1 容器镜像概述 1.1 什么是镜像 镜像就是一个可执行独立运行的软件包。包含应用运行所必须的文件和依赖包;镜像可以理解为类或者模板,只要在容器的环境下开箱即用; Docker容器与镜像的关系: 1.2 bootfs和rootfs 通常而言,Linux的操作系统由两类文件系统组成:bootfs…

一、Kubernetes基本介绍和功能架构

1、kubernetes 概述 kubernetes&#xff0c;简称 K8s&#xff0c;是用 8 代替 8 个字符“ubernete”而成的缩写。是一个开源 的&#xff0c;用于管理云平台中多个主机上的容器化的应用&#xff0c;Kubernetes 的目标是让部署容器化的 应用简单并且高效(powerful),Kubernetes 提…

python中的异常捕获与传递

目录 一.了解异常 二.异常的捕获方法 1.捕获常规异常 演示 2.捕获制定异常 演示 3.捕获多个异常 演示 4.捕获所有异常 演示 5.异常else 演示 6.异常的finally 演示 三.异常的传递 一.了解异常 当我们的程序遇到了BUG&#xff0c;那么接下来有两种情况: 整个程序因…

leetcode.1971 寻找图中是否存在路径 - bfs dfs 并查集 邻接表 邻接矩阵

1971. 寻找图中是否存在路径 目录 1、bfs - 邻接矩阵 2、dfs - 邻接表 3、并查集 1、bfs - 邻接矩阵 让源点source入队 取队头遍历未标记的邻接节点并入队如果队伍里有dest目标节点 说明dest被遍历到 则return trueclass Solution { public:static const int N2*1e5;bool st[…

靴子落地:ChatGPT 国内发展或被「拉手刹」

内容一览&#xff1a;深度合成服务在满足用户需求、改进用户体验的同时&#xff0c;也被一些不法人员用于制作、复制、发布、传播违法信息&#xff0c;诋毁、贬损他人名誉、荣誉&#xff0c;仿冒他人身份实施诈骗等违法行为&#xff0c;如今针对这一技术的管理规定终于发布了。…

游戏开发 mask和RectMask2D区别

1. Mask遮罩的大小与形状依赖于Graphic&#xff0c;而RectMask2D只需要依赖RectTransform 2. Mask支持圆形或其他形状遮罩&#xff0c; 而RectMask2D只支持矩形 3. Mask会增加drawcall 4、mask的性质&#xff1a; 性质1&#xff1a;Mask会在首尾&#xff08;首Mask节点&…

Jenkins(4)— 配置钉钉通知

1、创建钉钉机器人 自定义机器人接入 - 钉钉开放平台 群设置 >> 智能群助手 >> 添加机器人 >> 自定义webhook机器人 输入自定义钉钉机器人名字和选择必要的安全设置。 注意&#xff1a;复制上面的加密信息和Webhook&#xff0c;后面在jenkins配置钉钉机器…

[附源码]计算机毕业设计Python的家政服务平台(程序+源码+LW文档)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等…

解决jeecgboot框架下单点登录后,页面刷新后,会自动跳转到单点登录服务的登录页问题

1.配置单点服务&#xff0c;可参考官方文档&#xff1a;http://doc.jeecg.com/2044170 - 打开.env文件,UE_APP_SSOtrue即代表开启SSO登录 NODE_ENVproduction VUE_APP_PLATFORM_NAMEJeecg-Boot 企业级快速开发平台 VUE_APP_SSOtrue- 打开.env.development文件&#xff0c;修改…

黑*头条_第7章_app端文章搜索(新版)

黑*头条_第7章_app端文章搜索(新版) 文章目录黑*头条_第7章_app端文章搜索(新版)1) 今日内容介绍1.1)App端搜索-效果图1.2)今日内容2) 搭建ElasticSearch环境2.1) 拉取镜像2.2) 创建容器2.3) 配置中文分词器 ik2.4) 使用postman测试3) app端文章搜索3.1) 需求分析3.2) 思路分析…

m基于CNN卷积神经网络的IBDFE单载波频域均衡算法

目录 1.算法描述 2.仿真效果预览 3.MATLAB核心程序 4.完整MATLAB 1.算法描述 单载波频域均衡(SC-FDE)是解决符号间干扰(ISI)问题的一项重要技术。相比于单载波时域均衡(SC-TDE)技术和正交频分复用(OFDM)技术,SC-FDE技术具有复杂度低、峰均功率比小的优点。但是,SC-FDE技术中…

Android 测试文字编码格式

测试文字编码格式&#xff0c;与设置字符串格式 调用&#xff1a; juniversalchardet-1.0.3.jar app里的Build.gradle implementation files(libs\\juniversalchardet-1.0.3.jar) java调用&#xff1a; import org.mozilla.universalchardet.UniversalDetector;/*** 测试编…

面试:分库分表经典15连问

目录 1. 我们为什么需要分库分表 1.1 为什么要分库 1.2 为什么要分表 2. 什么时候考虑分库分表&#xff1f; 3. 如何选择分表键 4.非分表键如何查询 5. 分表策略如何选择 5.1 range范围 5.2 hash取模 5.3 一致性Hash 6. 如何避免热点问题数据倾斜&#xff08;热点数…

LaTex教程(二)——LaTeX排版

文章目录1. 中文宏包2. 字符2.1 空格和分段2.2 标点符号2.2.1 引号2.2.2 连字号和破折号2.2.3 省略号3. 文字强调4. 断行断页1. 中文宏包 ctex 宏包和文档类是对CJK 和xeCJK 等宏包的进一步封装。ctex 文档类包括 ctexart /ctexrep / ctexbook&#xff0c;是对LATEX 的三个标准…

第十七届D2大会(II)

一、无极&#xff1a;面向复杂B端项目的低代码平台设计与实践 页面片&#xff1a;自定义的最小低代码开发单元&#xff0c;包括&#xff1a;数据、布局、业务逻辑等低代码编辑器可配合配置分支管理、DevTool等能力&#xff0c;提供更好的工程体验 二、基于H5页面“高差指纹”技…