Android高级控件(六)——自定义ListView高仿一个QQ可拖拽列表的实现


我们做一些好友列表或者商品列表的时候,居多的需求可能就是需要列表拖拽了,而我们选择了ListView,也是因为使用ListView太久远了,导致对他已经有浓厚的感情了,我们之前也是写过几篇关于ListView的博文

而今天我们就来实现以下课拖拽的方案,大家可以借鉴以下

我们大致的思路,其实是这样子的,也是我的设想,我们可以先去实现一个简单的ListView的数据,但是他的Adapter,我们可以用系统封装好的,然后传递进去一个实体类,最后自定义一个listview去操作,所以我们先把准备的工作做好,比如?

list_item.xml

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

    <ImageView
        android:id="@+id/iv_logo"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_alignParentLeft="true"
        android:layout_centerInParent="true"
        android:layout_marginLeft="10dp"/>

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:layout_marginLeft="10dp"
        android:layout_toRightOf="@id/iv_logo"/>

</RelativeLayout>

这就只有一个头像和一句话了,然后我们把实体类也给写完了

DragBean

package com.liuguilin.draglistviewsample.entity;

/*
 *  项目名:  DragListViewSample
 *  包名:    com.liuguilin.draglistviewsample.entity
 *  文件名:   DragBean
 *  创建者:   LGL
 *  创建时间:  2016/8/29 22:49
 *  描述:    实体类
 */

public class DragBean {

    private int ivId;
    private String text;

    public DragBean() {

    }

    public DragBean(int ivId, String text) {
        this.ivId = ivId;
        this.text = text;
    }

    public int getIvId() {
        return ivId;
    }

    public String getText() {
        return text;
    }

}

ok,其实很简单,id是图片,然后是文本,这样我们就可以来实现一个Adapter了,这里我用的是ArrayAdapter这样能让我们插入和删除很轻松

DragAdapter

package com.liuguilin.draglistviewsample.adapter;

/*
 *  项目名:  DragListViewSample
 *  包名:    com.liuguilin.draglistviewsample.adapter
 *  文件名:   DragAdapter
 *  创建者:   LGL
 *  创建时间:  2016/8/29 22:41
 *  描述:    拖拽列表的数据源
 */

import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import com.liuguilin.draglistviewsample.R;
import com.liuguilin.draglistviewsample.entity.DragBean;

import java.util.List;

public class DragAdapter extends ArrayAdapter<DragBean> {

    /**
     * 构造方法
     *
     * @param context
     * @param mList
     */
    public DragAdapter(Context context, List<DragBean> mList) {
        super(context, 0, mList);
    }

    /**
     * 实现View
     *
     * @param position
     * @param convertView
     * @param parent
     * @return
     */
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View view;
        ViewHolder viewHolder;
        if (convertView == null) {
            view = View.inflate(getContext(), R.layout.list_item, null);
            viewHolder = new ViewHolder();
            viewHolder.imageView = (ImageView) view
                    .findViewById(R.id.iv_logo);
            viewHolder.textView = (TextView) view.findViewById(R.id.textView);
            view.setTag(viewHolder);
        } else {
            view = convertView;
            viewHolder = (ViewHolder) view.getTag();
        }

        viewHolder.imageView.setImageResource(getItem(position).getIvId());
        viewHolder.textView.setText(getItem(position).getText());
        return view;
    }

    /**
     * 缓存
     */
    static class ViewHolder {
        ImageView imageView;
        TextView textView;
    }

}

好的,其实到这里,他就是一个最普通的ListView了,我们给他填充点数据

MainActivity

package com.liuguilin.draglistviewsample;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import com.liuguilin.draglistviewsample.adapter.DragAdapter;
import com.liuguilin.draglistviewsample.entity.DragBean;
import com.liuguilin.draglistviewsample.view.DragListView;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    //列表
    private DragListView mListView;
    //数据
    private List<DragBean> mList = new ArrayList<>();
    //数据源
    private DragAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initView();
    }

    /**
     * 初始化View
     */
    private void initView() {
        mListView = (DragListView) findViewById(R.id.mListView);

        //新增數據
        for (int i = 0; i < 30; i++) {
            DragBean bean = new DragBean(R.mipmap.ic_launcher, "刘某人程序员" + i);
            mList.add(bean);
        }
        //初始化数据源
        adapter = new DragAdapter(this,mList);
        mListView.setAdapter(adapter);
    }
}

现在可以看看实际的效果了

现在我们可以重写我们的ListView了

我们首先拦截他的事件

 /**
     * 获取触点所在条目的位置
     * 获取选中条目的图片
     * 事件的拦截机制
     *
     * @param ev
     * @return
     */
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        //识别动作
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                //获取触点的坐标
                int x = (int) ev.getX();
                int y = (int) ev.getY();
                //这样就可以计算我按到哪个条目上了
                mStartPosition = mEndPosition = pointToPosition(x, y);
                //判断触点是否在logo的区域
                ViewGroup itemView = (ViewGroup) getChildAt(mStartPosition - getFirstVisiblePosition());
                //记录手指在条目中的相对Y坐标
                dragPoint = y - itemView.getTop();
                //ListView在屏幕中的Y坐标
                dragOffset = (int) (ev.getRawY() - y);
                //拖动的图标
                View dragger = itemView.findViewById(R.id.iv_logo);
                //判断触点是否在logo区域
                if (dragger != null && x < dragger.getRight() + 10) {
                    //定义ListView的滚动条目
                    //上
                    upScroll = getHeight() / 3;
                    //下
                    downScroll = getHeight() * 2 / 3;
                    //获取选中的图片/截图
                    itemView.setDrawingCacheEnabled(true);
                    //获取截图
                    Bitmap bitMap = itemView.getDrawingCache();
                    //图片滚动
                    startDrag(bitMap, y);
                }
                break;
        }
        //还会传递事件到子View
        return false;
    }

获取到他的position之后我们直接截图,并且显示我们的window,这里做的事情就比较多了我们还要判断是否点击的是头像才去显示window

 /**
     * 图片在Y轴,也就是上下可滚动
     *
     * @param bitMap
     * @param y
     */
    private void startDrag(Bitmap bitMap, int y) {
        //窗体仿照
        wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
        //设置窗体参数
        lParams = new WindowManager.LayoutParams();
        //设置宽高
        lParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
        lParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
        //属性
        lParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
                | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
        //设置半透明
        lParams.alpha = 0.8f;
        //设置居中
        lParams.gravity = Gravity.TOP;
        //设置xy
        lParams.x = 0;
        lParams.y = y-dragPoint + dragOffset;
        //属性
        lParams.format = PixelFormat.TRANSLUCENT;
        //设置动画
        lParams.windowAnimations = 0;
        //图片
        dragImageView = new ImageView(getContext());
        //设置截图
        dragImageView.setImageBitmap(bitMap);
        //添加显示窗体
        wm.addView(dragImageView, lParams);
    }

好的,我们初始化一下window,光显示还不行呢,我们还要可以滑动,怎么监听?onTouchEvent的ACTION_MOVE事件是可以做到的


    /**
     * 触摸事件
     *
     * @param ev
     * @return
     */
    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        //错误的位置
        if (dragImageView != null && mEndPosition != INVALID_POSITION) {
            //在滑动事件中控制上下滑动
            switch (ev.getAction()) {
                case MotionEvent.ACTION_MOVE:
                    //直接获取到Y坐标进行移动
                    int moveY = (int) ev.getY();
                    doDrag(moveY);
                    break;
                //停止拖动成像
                case MotionEvent.ACTION_UP:
                    int upY = (int) ev.getY();
                    stopDrag();
                    onDrag(upY);
                    break;
            }
        }
        //拦截到事件
        return true;
    }

我们在移动的时候不断的去更新他的位置

    /**
     * 控制窗体移动
     *
     * @param moveY
     */
    private void doDrag(int moveY) {
        if (dragImageView != null) {
            lParams.y = moveY - dragPoint + dragOffset;
            wm.updateViewLayout(dragImageView, lParams);
        }
        //判断移动到分割线 返回-1
        int tempLine = pointToPosition(0, moveY);
        //我们处理他
        if (tempLine != INVALID_POSITION) {
            //只要你不移动到分割线 我才处理
            mEndPosition = tempLine;
        }

        //拖拽时滚动、滚动速度
        int scrollSpeed = 0;
        //上滚
        if (moveY < upScroll) {
            scrollSpeed = 10;
            //下滚
        } else if (moveY > downScroll) {
            scrollSpeed = -10;
        }
        //开始滚动
        if (scrollSpeed != 0) {
            //计算条目的Y坐标
            int dragItemY = getChildAt(mEndPosition - getFirstVisiblePosition()).getTop();
            //当前速度
            int dy = dragItemY + scrollSpeed;
            //设置
            setSelectionFromTop(mEndPosition, dy);
        }
    }

当你移动完成之后,我就可以停止你的window体了

     /**
     * 停止的位置
     */
    private void stopDrag() {
        //直接移除窗体
        if (dragImageView != null) {
            wm.removeView(dragImageView);
            dragImageView = null;
        }

    }

这样,我就直接拼接你的position达到一个拖拽的效果


    /**
     * 最终开始成像
     *
     * @param upY
     */
    private void onDrag(int upY) {
        //分割线的处理
        //判断移动到分割线 返回-1
        int tempLine = pointToPosition(0, upY);
        //我们处理他
        if (tempLine != INVALID_POSITION) {
            //只要你不移动到分割线 我才处理
            mEndPosition = tempLine;
        }

        /**
         * 你在最上方就直接落在第一个最下方就直接最下面一个
         */

        //上边界处理
        if (upY < getChildAt(1).getTop()) {
            mEndPosition = 1;
            //下边界处理
        } else if (upY > getChildAt(getChildCount() - 1).getTop()) {
            mEndPosition = getAdapter().getCount() - 1;
        }

        //开始更新item顺序
        if (mEndPosition > 0 && mEndPosition < getAdapter().getCount()) {
            DragAdapter adapter = (DragAdapter) getAdapter();
            //删除原来的条目
            adapter.remove(adapter.getItem(mStartPosition));
            //更新
            adapter.insert(adapter.getItem(mStartPosition), mEndPosition);
        }
    }

全部代码贴上

DragListView

package com.liuguilin.draglistviewsample.view;

/*
 *  项目名:  DragListViewSample
 *  包名:    com.liuguilin.draglistviewsample.view
 *  文件名:   DragListView
 *  创建者:   LGL
 *  创建时间:  2016/8/29 20:50
 *  描述:    自定义高仿QQ列表可拖拽的ListView
 */

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.PixelFormat;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.ListView;

import com.liuguilin.draglistviewsample.R;
import com.liuguilin.draglistviewsample.adapter.DragAdapter;

public class DragListView extends ListView {

    //按下选中的position
    private int mStartPosition;
    //需要达到的position
    private int mEndPosition;
    //手指在条目中的相对Y坐标
    private int dragPoint;
    //ListView在屏幕中的Y坐标
    private int dragOffset;
    //上
    private int upScroll;
    //下
    private int downScroll;
    //窗体
    private WindowManager wm;
    //显示的截图
    private ImageView dragImageView;
    //窗体参数
    private WindowManager.LayoutParams lParams;

    //构造方法
    public DragListView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    /**
     * 获取触点所在条目的位置
     * 获取选中条目的图片
     * 事件的拦截机制
     *
     * @param ev
     * @return
     */
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        //识别动作
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                //获取触点的坐标
                int x = (int) ev.getX();
                int y = (int) ev.getY();
                //这样就可以计算我按到哪个条目上了
                mStartPosition = mEndPosition = pointToPosition(x, y);
                //判断触点是否在logo的区域
                ViewGroup itemView = (ViewGroup) getChildAt(mStartPosition - getFirstVisiblePosition());
                //记录手指在条目中的相对Y坐标
                dragPoint = y - itemView.getTop();
                //ListView在屏幕中的Y坐标
                dragOffset = (int) (ev.getRawY() - y);
                //拖动的图标
                View dragger = itemView.findViewById(R.id.iv_logo);
                //判断触点是否在logo区域
                if (dragger != null && x < dragger.getRight() + 10) {
                    //定义ListView的滚动条目
                    //上
                    upScroll = getHeight() / 3;
                    //下
                    downScroll = getHeight() * 2 / 3;
                    //获取选中的图片/截图
                    itemView.setDrawingCacheEnabled(true);
                    //获取截图
                    Bitmap bitMap = itemView.getDrawingCache();
                    //图片滚动
                    startDrag(bitMap, y);
                }
                break;
        }
        //还会传递事件到子View
        return false;
    }

    /**
     * 图片在Y轴,也就是上下可滚动
     *
     * @param bitMap
     * @param y
     */
    private void startDrag(Bitmap bitMap, int y) {
        //窗体仿照
        wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
        //设置窗体参数
        lParams = new WindowManager.LayoutParams();
        //设置宽高
        lParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
        lParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
        //属性
        lParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
                | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
        //设置半透明
        lParams.alpha = 0.8f;
        //设置居中
        lParams.gravity = Gravity.TOP;
        //设置xy
        lParams.x = 0;
        lParams.y = y-dragPoint + dragOffset;
        //属性
        lParams.format = PixelFormat.TRANSLUCENT;
        //设置动画
        lParams.windowAnimations = 0;
        //图片
        dragImageView = new ImageView(getContext());
        //设置截图
        dragImageView.setImageBitmap(bitMap);
        //添加显示窗体
        wm.addView(dragImageView, lParams);
    }

    /**
     * 触摸事件
     *
     * @param ev
     * @return
     */
    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        //错误的位置
        if (dragImageView != null && mEndPosition != INVALID_POSITION) {
            //在滑动事件中控制上下滑动
            switch (ev.getAction()) {
                case MotionEvent.ACTION_MOVE:
                    //直接获取到Y坐标进行移动
                    int moveY = (int) ev.getY();
                    doDrag(moveY);
                    break;
                //停止拖动成像
                case MotionEvent.ACTION_UP:
                    int upY = (int) ev.getY();
                    stopDrag();
                    onDrag(upY);
                    break;
            }
        }
        //拦截到事件
        return true;
    }

    /**
     * 最终开始成像
     *
     * @param upY
     */
    private void onDrag(int upY) {
        //分割线的处理
        //判断移动到分割线 返回-1
        int tempLine = pointToPosition(0, upY);
        //我们处理他
        if (tempLine != INVALID_POSITION) {
            //只要你不移动到分割线 我才处理
            mEndPosition = tempLine;
        }

        /**
         * 你在最上方就直接落在第一个最下方就直接最下面一个
         */

        //上边界处理
        if (upY < getChildAt(1).getTop()) {
            mEndPosition = 1;
            //下边界处理
        } else if (upY > getChildAt(getChildCount() - 1).getTop()) {
            mEndPosition = getAdapter().getCount() - 1;
        }

        //开始更新item顺序
        if (mEndPosition > 0 && mEndPosition < getAdapter().getCount()) {
            DragAdapter adapter = (DragAdapter) getAdapter();
            //删除原来的条目
            adapter.remove(adapter.getItem(mStartPosition));
            //更新
            adapter.insert(adapter.getItem(mStartPosition), mEndPosition);
        }
    }

    /**
     * 停止的位置
     */
    private void stopDrag() {
        //直接移除窗体
        if (dragImageView != null) {
            wm.removeView(dragImageView);
            dragImageView = null;
        }

    }

    /**
     * 控制窗体移动
     *
     * @param moveY
     */
    private void doDrag(int moveY) {
        if (dragImageView != null) {
            lParams.y = moveY - dragPoint + dragOffset;
            wm.updateViewLayout(dragImageView, lParams);
        }
        //判断移动到分割线 返回-1
        int tempLine = pointToPosition(0, moveY);
        //我们处理他
        if (tempLine != INVALID_POSITION) {
            //只要你不移动到分割线 我才处理
            mEndPosition = tempLine;
        }

        //拖拽时滚动、滚动速度
        int scrollSpeed = 0;
        //上滚
        if (moveY < upScroll) {
            scrollSpeed = 10;
            //下滚
        } else if (moveY > downScroll) {
            scrollSpeed = -10;
        }
        //开始滚动
        if (scrollSpeed != 0) {
            //计算条目的Y坐标
            int dragItemY = getChildAt(mEndPosition - getFirstVisiblePosition()).getTop();
            //当前速度
            int dy = dragItemY + scrollSpeed;
            //设置
            setSelectionFromTop(mEndPosition, dy);
        }
    }
}

然后我们引用

layout_main.xml

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

    <com.liuguilin.draglistviewsample.view.DragListView
        android:id="@+id/mListView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>

对了,别忘记了添加窗体的权限哦

 <!--窗口权限-->
 <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

做完这一系列事情之后,就觉得这个设想其实是对的,然后我们可以尝试性的运行一下

运行时成功的,说明我们的设想是没有问题的,但是随着而来的,也是诸多的bug,所以呢,这也只是思想的参考,不过这些bug我有时间野就修复一下,应该是可以的,好的,本篇博文就先到这里!

有兴趣的加群:555974449

DragListViewSample:http://download.csdn.net/detail/qq_26787115/9616355

Android高级控件(六)——自定义ListView高仿一个QQ可拖拽列表的实现的更多相关文章

  1. Android高级控件(五)——如何打造一个企业级应用对话列表,以QQ,微信为例

    Android高级控件(五)--如何打造一个企业级应用对话列表,以QQ,微信为例 看标题这么高大上,实际上,还是运用我么拿到listview去扩展,我们讲什么呢,就是研究一下QQ,微信的这种对话列表, ...

  2. Android高级控件(一)——ListView绑定CheckBox实现全选,增加和删除等功能

    Android高级控件(一)--ListView绑定CheckBox实现全选,增加和删除等功能 这个控件还是挺复杂的,也是项目中应该算是比较常用的了,所以写了一个小Demo来讲讲,主要是自定义adap ...

  3. Android高级控件(一)——ListView绑定CheckBox实现全选,添加和删除等功能

    Android高级控件(一)--ListView绑定CheckBox实现全选,添加和删除等功能 这个控件还是挺复杂的.也是项目中应该算是比較经常使用的了,所以写了一个小Demo来讲讲,主要是自己定义a ...

  4. Android高级控件--AdapterView与Adapter

    在J2EE中提供过一种非常好的框架--MVC框架,实现原理:数据模型M(Model)存放数据,利用控制器C(Controller)将数据显示在视图V(View)上.在Android中有这样一种高级控件 ...

  5. Android 高级控件(七)——RecyclerView的方方面面

    Android 高级控件(七)--RecyclerView的方方面面 RecyclerView出来很长时间了,相信大家都已经比较了解了,这里我把知识梳理一下,其实你把他看成一个升级版的ListView ...

  6. Android高级控件(二)——SurfaceView实现GIF动画架包,播放GIF动画,自己实现功能的初体现

    Android高级控件(二)--SurfaceView实现GIF动画架包,播放GIF动画,自己实现功能的初体现 写这个的原因呢,也是因为项目中用到了gif动画,虽然网上有很多的架包可以实现,不过我们还 ...

  7. Android高级控件(四)——VideoView 实现引导页播放视频欢迎效果,超级简单却十分的炫酷

    Android高级控件(四)--VideoView 实现引导页播放视频欢迎效果,超级简单却十分的炫酷 是不是感觉QQ空间什么的每次新版本更新那炫炫的引导页就特别的激动,哈哈,其实他实现起来真的很简单很 ...

  8. Android高级控件(三)—— 使用Google ZXing实现二维码的扫描和生成相关功能体系

    Android高级控件(三)-- 使用Google ZXing实现二维码的扫描和生成相关功能体系 摘要 现在的二维码可谓是烂大街了,到处都是二维码,什么都是二维码,扫一扫似乎已经流行到习以为常了,今天 ...

  9. Android高级控件(三)——&#160;使用Google ZXing实现二维码的扫描和生成相关功能体系

    Android高级控件(三)-- 使用Google ZXing实现二维码的扫描和生成相关功能体系 摘要 如今的二维码可谓是烂大街了.到处都是二维码.什么都是二维码,扫一扫似乎已经流行到习以为常了,今天 ...

随机推荐

  1. [POI2016]Nim z utrudnieniem

    Description A和B两个人玩游戏,一共有m颗石子,A把它们分成了n堆,每堆石子数分别为a[1],a[2],...,a[n],每轮可以选择一堆石子,取掉任意颗石子,但不能不取.谁先不能操作,谁 ...

  2. SAC E#1 - 一道中档题 Factorial

    题目背景 SOL君(炉石主播)和SOL菌(完美信息教室讲师)是好朋友. 题目描述 SOL君很喜欢阶乘.而SOL菌很喜欢研究进制. 这一天,SOL君跟SOL菌炫技,随口算出了n的阶乘. SOL菌表示不服 ...

  3. bzoj 5212: [Zjoi2018]历史

    Description 九条可怜是一个热爱阅读的女孩子. 这段时间,她看了一本非常有趣的小说,这本小说的架空世界引起了她的兴趣. 这个世界有n个城市,这n个城市被恰好n?1条双向道路联通,即任意两个城 ...

  4. ●POJ 2794 Double Patience

    题链: http://poj.org/problem?id=2794题解: 状压DP,概率 9元组表示每一堆还剩几张牌.可以用5进制状压,共5^9=1953124个状态. 令P(S)表示S这个状态被取 ...

  5. 后缀自动机模板(SPOJ1811)

    用后缀自动机实现求两个串的最长公共子串. #include <cstdio> #include <algorithm> ; char s[N]; ]; int main() { ...

  6. 如何使用GitHub

    进行版本控制时,我们可以直接通过网页来进行版本控制,也可以下载git客户端.值得注意的是,git的客户端有很多种,具体的可以参考:https://git-scm.com/downloads/guis/ ...

  7. 一款基于Vue的扩展性组件库 VV-UI

    github: https://github.com/VV-UI/VV-UI 演示地址: https://vv-ui.github.io/VV-UI/#/meta-info 1. LoadingBar ...

  8. H3C系列之三层交换机系统版本升级

    本文涉及到的硬件与软件交换机:H3C S3600-28TP-SItftp软件:tftpd32小软件升级的文件:S36SI_E-CMW310-R1702P44.zip 关于升级的文件说明如下: S36S ...

  9. Mysql--七种 Join 查询

    Mysql 系列文章主页 =============== 1 准备数据 1.1 建立 Employee 表 DROP TABLE IF EXISTS employee; CREATE TABLE IF ...

  10. 40. Combination Sum II(midum, backtrack, 重要)

    Given a collection of candidate numbers (C) and a target number (T), find all unique combinations in ...