View 作为Android中最直接的和用户进行交互的单位,对于 View 的事件处理重要程度自然不言而喻,View 的事件处理直接影响到用户体验,下面我们来看一下对 View 的触摸事件的处理:

首先,View 的源代码中已经给我们写了一个 onTouchEvent 方法用于处理最直接的触摸事件,我们可以在官方文档中看到对这个方法的介绍:

public boolean  onTouchEvent (MotionEvent event) Added in API level 1Implement this method to handle touch screen motion events. If this method is used to detect click actions, it is recommended that the actions be performed by implementing and calling performClick(). This will ensure consistent system behavior, including:
•obeying click sound preferences
•dispatching OnClickListener calls
•handling ACTION_CLICK when accessibility features are enabled Parametersevent
The motion event. Returns
True if the event was handled, false otherwise.

大致意思是:实现这个方法去处理屏幕的触摸事件,如果这个方法用于处理单击事件,它将会:播放单击事件的声音,回调OnClickListener 接口的方法,如果可能的话处理单击动作。
简答来说就是我们可以在这个方法中处理当前 View 的触摸事件(单击事件也是一种触摸事件)。
方法的参数是一个 MotionEvent 类,用于储存当前触摸事件的信息,我们可以利用这些信息达到我们想要的效果。

接下来介绍一个配合这个方法使用的类:VelocityTracker(速度追踪类),这个类用于获取触摸移动的时候的速度,一般来说,我们会在 onTouchEvent 中使用这个类,先看看官方文档的说明:

文档里面提到的方法已经可以完成一些基本的需求,这里解释一下里面提到的方法的作用:

//// 通过静态方法实例化这个类的一个对象
VelocityTracker velocityTracker = VelocityTracker.obtain();
// 设置这个类要检测的触摸事件对象
velocityTracker.addMovement(event);
// 设置计算速度的时间间隔(毫秒)
velocityTracker.computeCurrentVelocity(1000);
/** 获取在上一个设置的时间间隔(这里是1000ms)内这个检测的触摸事件在 X 方向和 Y 方向上移动的距离,* 那么就可以根据移动的距离和时间间隔算出速度*/// 获取 x 方向上的移动速度
velocityTracker.getXVelocity();// 获取 y 方向上的移动速度
velocityTracker.getYVelocity();

下面我们通过一个小例子来具体的看一下怎么使用,假设我们要在屏幕上自由的移动手指,并且随时把手指的坐标和在 X 、Y 方向上的移动速度显示出来。新建一个 Android 工程:

activty_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/activity_main"android:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center_horizontal"tools:context="com.example.administrator.viewontouchevent.MainActivity"android:orientation="vertical"><TableRow
        android:layout_width="wrap_content"android:layout_height="wrap_content"><TextView
            android:id="@+id/showXYTextView"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="坐标:"android:background="#3300ff00"/><TextView
            android:id="@+id/showVelocityTextView"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="速度:"android:background="#220000ff"/></TableRow></LinearLayout>

主布局文件中有两个 TextView 控件成一行排列,分别用于显示当前手指的坐标和 X 、 Y 方向上的移动速度。接下来,我们要自定义一个控件,然后重写 onTouchEvent 方法用于检测我们的手指移动的触摸信息并且传递给两个 TextView 控件。

但是在这里我们仔细思考一下:我们重写的 onTouchEvent 方法的参数和返回值都是固定的,不允许我们更改,那么我们该怎么将里面的数据传递出去呢?其实利用java中的回调机制就可以很好地解决这个问题:
我们新建一个自定义接口 GetInfFromMotionEvent:


/*** Created by Administrator on 2017/2/27.*/public interface GetInfFromMotionEvent {public void getX(float x);public void getY(float y);public void getXVelocity(float xVelocity);public void getYVelocity(float yVelocity);
}

在这个自定义接口中我们写了四个抽象方法分别用于获取当前触摸事件的触摸点坐标和 X 、 Y 方向上的速度。这个接口我们要在 MainActivity.java 中实现并且重写里面的四个方法,接下来我们先看我们自定义的View: CustomView.java:


import android.content.Context;
import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;/*** Created by Administrator on 2017/2/27.*/public class CustomView extends View {private VelocityTracker velocityTracker = VelocityTracker.obtain();// 这个接口用于随时获取触摸事件相关信息并返回(坐标、速度)private GetInfFromMotionEvent getInfFromMotionEvent = null;public void init(Context context, GetInfFromMotionEvent getInfFromMotionEvent) { // 初始化this.getInfFromMotionEvent = getInfFromMotionEvent; // 初始化自定义触摸事件获取接口}public CustomView(Context context, GetInfFromMotionEvent getInfFromMotionEvent) { // 构造方法super(context);init(context, getInfFromMotionEvent);}@Overridepublic boolean onTouchEvent(MotionEvent event) {// 添加要检测的触摸事件velocityTracker.addMovement(event);// 对触摸事件正在进行的动作类型进行判断switch (event.getAction()) {// 手指正在移动:case MotionEvent.ACTION_MOVE:Log.i("onTouchEvent", "MotionEvent.ACTION_MOVE");/** computeCurrentVelocity 方法设定一个时间间隔(毫秒),那么此时通过 getXVelocity* 方法和 getYVelocity 方法 得到的速度就是在上一个* 设定的这个时间间隔里面得到的触摸移动距离* 这里设定为 1 毫秒,即为上个 1 毫秒的间隔内 X 、 Y 方向上手指移动的距离* 这么短的时间可以理解为瞬时速度,算的时候乘上1000就变成了单位为 “秒” 的速度*/velocityTracker.computeCurrentVelocity(1);getInfFromMotionEvent.getX(event.getRawX());getInfFromMotionEvent.getY(event.getRawY());getInfFromMotionEvent.getXVelocity(velocityTracker.getXVelocity()*1000);getInfFromMotionEvent.getYVelocity(velocityTracker.getYVelocity()*1000);break;// 手指按下:case MotionEvent.ACTION_DOWN:/** getRawX 和 getRawY 方法返回的是当前触摸点相对于屏幕左上角得到的 X 和 Y* getX 和 getY 方法返回的是当前触摸点相对于当前 View 左上角得到的 X 和 Y*/Log.i("onTouchEvent", "MotionEvent.ACTION_DOWN");getInfFromMotionEvent.getX(event.getRawX());getInfFromMotionEvent.getY(event.getRawY());break;// 手指抬起:case MotionEvent.ACTION_UP:Log.i("onTouchEvent", "MotionEvent.ACTION_UP");break;}/** 如果这个返回值为false,那么触摸事件不会继续向下传递,* 此时就只有 MotionEvent.ACTION_DOWN 这个动作被执行了,这个触摸事件就不由这个 View 继续处理了,* 也就是说这个 View 的OnTouchEvent方法对于当前的触摸事件(在这一次触摸事件手指松开之前)已经失效了*/return true;}
}

这个自定义控件只能在代码中新建,不能再布局文件中使用,因为我们只写了一个构造方法,并且这里我们利用 GetInfFromMotionEvent 接口将得到的触摸信息传递出去,接下就是MainActivity.java:


import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;public class MainActivity extends AppCompatActivity {private Button button = null;private TextView textView1 = null;private TextView textView2 = null;private String xYString = null;private String xYVelocity = null;private GetInfFromMotionEvent getInfFromMotionEvent = new GetInfFromMotionEvent() {@Overridepublic void getX(float x) {xYString = "(" + x + ",  ";}@Overridepublic void getY(float y) {xYString += y + ")";textView1.setText("坐标:" + xYString);}@Overridepublic void getXVelocity(float xVelocity) {xYVelocity = "(" + xVelocity + ",  ";}@Overridepublic void getYVelocity(float yVelocity) {xYVelocity += yVelocity + ")";textView2.setText("速度: " + xYVelocity);}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);textView1 = (TextView) findViewById(R.id.showXYTextView);textView2 = (TextView) findViewById(R.id.showVelocityTextView);// 新建我们自定义的控件对象CustomView customView = new CustomView(this, getInfFromMotionEvent);LinearLayout linearLayout = (LinearLayout) findViewById(R.id.activity_main);// 设置自定义控件对象的参数customView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT));// 用代码将自定义控件加入布局中linearLayout.addView(customView);}}

在 MainActivity.java 中我们实现了 GetInfFromMotionEvent 接口,在里面对应的方法中更新两个 TextView 控件中显示的数据,分别为更新坐标和 X、Y 方向上的速度,并且新建自定义 View 的时候将这个接口对象传入,这样的话只要坐标和速度一经更新,我们就可以通过这个接口中的方法同步更新TextView 控件中的数据显示。好了,让我们来运行一下:

Ok,成功的显示了坐标和速度。

其实,对于 View 的触摸事件的处理,Android还提供了另一个方法:通过 GestureDetector 类(手势识别)和 这个类里面的提供的3个接口和一个类,先看一下官方文档:

提供的接口有:

我们常用的两个接口是:

GestureDetector.GestureListener
GestureDetector.OnDoubleTapListener

我们下面来看一下 GestureDetector 类中提供的两个常用的接口中的方法:
GestureDetector.GestureListener:

// 当控件被触摸到的一瞬间就会调用的方法,对应触摸事件动作:MotionEvent.ACTION_DOWNpublic boolean onDown(MotionEvent e) {return false;}// 手指触摸控件还未移动或者松开的时候(强调还未移动或者松开),对应动作:MotionEvent.ACTION_DOWNpublic void onShowPress(MotionEvent e) {}// 控件单击时候调用的方法,对应动作:MotionEvent.ACTION_DOWN --->  MotionEvent.ACTION_UPpublic boolean onSingleTapUp(MotionEvent e) {return false;}/** 手指触摸控件并且拖动,对应动作:MotionEvent.ACTION_DOWN  --->  MotionEvent.ACTION_MOVE(多个)* 方法中四个参数的含义:e1:第一次调用 onScroll 方法储存的触摸信息,e2:当前触摸点的触摸信息,* distanceX、distanceY:上一次调用 onScroll 方法和这一次调用 Scroll 方法* 过程中X 方向上和 Y 方向上移动的距离*/public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {return false;}/** 控件长按的时候调用的方法,如果这个方法被调用,那么是无法识别滑动事件的,也就是说长按之后,* 这个触摸事件就对于这个手势监听器来说就结束了,之后只有松开之后在次触摸(重新触发触摸事件)* 但是如果对手势识别器(myGestureDetector)对象设置了 setIsLongpressEnabled(false) 方法之后,* 那么无论怎么长按当前 View 也不会回调这个方法*/public void onLongPress(MotionEvent e) {}/** 当产生系统识别出来的滑动事件的时候,会调用这个方法,这里值得注意的是:* 并不是调用了 onScroll 之后就一定会调用这个方法,这个方法对滑动的速率大小有要求,* 即滑动的速率达到一定大小的时候才会调用这个方法,方法参数分别代表:* 触摸开始点的事件信息,触摸结束(手指松开)的时候储存的事件信息,* 整个滑动过程 x 方向上滑动的平均速度,整个滑动过程 y 方向上滑动的平均速度。*/public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {return false;}

下面是 GestureDetector.OnDoubleTapListener 接口的方法:

        /* * 严格的单击行为,如果一次单击之后到系统认为双击的时间段内没发生另一次单击行为时调用,* 也就是说这个方法被调用了之后不可能再调用双击行为方法,注意和 onSingleTap的区别,* 调用顺序:onDown --> onSingleTapUp --> onSingleTapConfirmed*/public boolean onSingleTapConfirmed(MotionEvent e) {return false;}// 双击,它不可能和 onSingleTapConfirmd 方法同时被调用public boolean onDoubleTap(MotionEvent e) {return false;}/** 表示发生了双击(onDoubleTap)行为,在onDoubleTap调用的期间,发生了 MotionEvent.ACTION_DOWN* MotionEvent.ACTION_UP 动作都会调用这个方法*/public boolean onDoubleTapEvent(MotionEvent e) {return false;}

接下来来看一下 GestureDetector 类的构造方法:

可以看到,所有的构造方法里面都需要一个 GestureDetector.OnGestureListener 接口对象作为参数。

一般来说,要使用 GestureDetector 类来检测一个 View 中的手势事件,我们会通过以下步骤:

1、新建一个 GestureDetector 对象并且设置它的手势监听器接口对象

2、这个 View 本身设置 OnTouchListener 接口并且在接口中的 onTouch 方法中设置:GestureDetector.onTouchEvent(Event event) 方法来将 View 的触摸事件交给 GestureDetector 对象去处理,GestureDetector 对象会将触摸事件交给其设置的手势监听接口处理

3、根据要求实现 GestureDetector 类中提供的手势监听接口来识别对应的触摸事件。

需要注意的是一个 View 如果要使用 GestureDetector.onDoubleTapListener 接口中的方法就一定先要实现 GestureDetector.OnGestureListener 接口,因为 GestureDetector 的构造方法中必须要有一个 GestureDetector.OnGestureListener 对象作为参数,得到 GestureDetector 对象之后调用

GestureDetector.setOnDoubleTapListener(GestureDetector.OnDoubleTapListener onDoubleTapListener)

方法来监听 View 的单双击事件来进行处理。

有些小伙伴可能会觉得使用 OnDoubleTapListener 接口会很麻烦,还要实现 OnGestureListener 接口,那么 GestureDetector 中还有一个类:GestureDetector.SimpleOnGestureListener,就是上图里面的最后一个类,这个类为我们重写了 GestureDetector.OnGestureListener 接口和 GestureDetector.OnDoubleTapListener 接口中的抽象方法,让我们在使用这两个接口的时候只需要重写我们需要的方法就行了,根据 Java 的多态性,这个类就是 GestureDetector.OnGestureListener 接口的对象,所以可以作为 GestureDetector 构造方法的参数,即我们可以写成这样:

gestureDetector = new GestureDetector(context, simpleOnGestureListener);

同样的步骤,将触摸事件交给 GestureDetector 对象处理:

gestureDetector.onTouchEvent(event);

对于这个类,小伙伴们可以自己尝试一下。

下面我们通过 GestureDetector 来实现上面的小例子:
只需修改 Custom.java 中的代码:


import android.content.Context;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;public class CustomView extends View {// 使用这个类的对象来计算手指滑动的速度private VelocityTracker velocityTracker = VelocityTracker.obtain();// 这个接口用于随时获取触摸事件相关信息并返回(坐标、速度)private GetInfFromMotionEvent getInfFromMotionEvent = null;private GestureDetector myGestureDetector = null;public CustomView(Context context, GetInfFromMotionEvent getInfFromMotionEvent) {super(context);this.getInfFromMotionEvent = getInfFromMotionEvent;// 新建一个手势识别器,并设置它的手势监听器myGestureDetector = new GestureDetector(context, gestureListener);this.setOnTouchListener(onTouchListener); // 设置触摸事件监听对象}/** 自定义触摸事件的监听对象*/private View.OnTouchListener onTouchListener = new View.OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {myGestureDetector.onTouchEvent(event); // 将触摸事件交给手势识别器去处理/** 一定要返回 true ,这个如果返回值为false,* 证明这一系列的触摸事件不由该 View 处理。* 那么接下来的触摸事件都不会传递给该 View ,也就无法将触摸事件作为手势进行处理* 详细的可以搜索一下 Android 里面的触摸事件的分发和拦截机制*/return true;}};/** 新建一个手势监听器,实现手势监听接口,并重写其中的抽象方法*/private GestureDetector.OnGestureListener gestureListener = new GestureDetector.OnGestureListener() {// 当控件被触摸到的一瞬间就会调用的方法,对应触摸事件动作:MotionEvent.ACTION_DOWN@Overridepublic boolean onDown(MotionEvent e) {Log.i("OnTouchListener", "onDown");getInfFromMotionEvent.getX(e.getRawX());getInfFromMotionEvent.getY(e.getRawY());return false;}// 手指触摸控件还未移动或者松开的时候(强调还未移动或者松开),对应动作:MotionEvent.ACTION_DOWN@Overridepublic void onShowPress(MotionEvent e) {Log.i("OnTouchListener", "onShowPress");}// 控件单击时候调用的方法,对应动作:MotionEvent.ACTION_DOWN --->  MotionEvent.ACTION_UP@Overridepublic boolean onSingleTapUp(MotionEvent e) {Log.i("OnTouchListener", "onSingleTapUp");return false;}/** 手指触摸控件并且拖动,对应动作:MotionEvent.ACTION_DOWN  --->  MotionEvent.ACTION_MOVE(多个)* 方法中四个参数的含义:e1:调用 onDown 方法储存的触摸点信息,e2:当前 onScroll 方法触摸点的触摸信息,* distanceX、distanceY:上一次调用 onScroll 方法和这一次调用 Scroll 方法* 过程中X 方向上和 Y 方向上移动的距离*/@Overridepublic boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {Log.i("OnTouchListener", "onScroll");getInfFromMotionEvent.getX(e2.getRawX());getInfFromMotionEvent.getY(e2.getRawY());velocityTracker.addMovement(e2);velocityTracker.computeCurrentVelocity(1);getInfFromMotionEvent.getXVelocity(velocityTracker.getXVelocity()*1000);getInfFromMotionEvent.getYVelocity(velocityTracker.getYVelocity()*1000);return false;}/** 控件长按的时候调用的方法,如果这个方法被调用,那么是无法识别滑动事件的,也就是说长按之后,* 这个触摸事件就结束了,之后只有松开之后在次触摸(重新触发触摸事件)* 但是如果对手势识别器(myGestureDetector)对象设置了 setIsLongpressEnabled(false) 方法之后,* 那么无论怎么长按当前 View 也不会回调这个方法*/@Overridepublic void onLongPress(MotionEvent e) {Log.i("OnTouchListener", "onLongPress");}/** 当产生系统识别出来的滑动事件的时候,会调用这个方法,参数分别是:* 触摸开始点的事件信息,触摸结束(手指松开)的时候储存的事件信息,* 整个滑动过程 x 方向上滑动的平均速度,整个滑动过程 y 方向上滑动的平均速度。*/@Overridepublic boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {Log.i("OnTouchListener", "onFling");return false;}};}

让我们来看看效果:

单击一个位置之后,onDown 方法和 onSingleTapUp 方法被调用,并且模拟器中显示出了单击位置的坐标,接下来试试滑动:

确实显示出了坐标和速度信息,来看看LogCat中打印的信息:

可以看到,滑动的时候先执行了onDown 和 onShowPress 方法,然后再执行 onScroll 方法

在鼠标指针方开之后(手指松开),还调用了 onFling 方法,上文代码中说过:onFling 方法只有滑动速率达到一定要求时候才会被调用。

你可以试试慢慢滑动,那么 onFling 方法将不会调用,所以在处理的时候要注意一下。

接下来,我们再试试长按 View :

你会发现长按 View 之后就不会更新坐标和速度了,其实就像上面代码注释中所说的那样,当 View 调用了 onLongPress 方法之后就无法识别滑动事件了,也就是说在这个接口中长按和滑动无法同时存在。我们可以在 构造方法中加一句代码:

myGestureDetector.setIsLongpressEnabled(false); // 设置手势识别器不监听长按事件

之后再试试,你会发现即使长按当前 View 之后在开始滑动仍然可以调用 onScroll 和 onFling 方法来更新坐标和速度信息。

最后还有一个问题:当一个 View 中既有 onTouchEvent 方法并且设置了 OnTouchListener 接口时,情况是怎样的呢?
这个问题我们可以看一下Android关于 onTouchEvent 方法调用的源码:

public boolean dispatchTouchEvent(MotionEvent event){  ... ...  if(onFilterTouchEventForSecurity(event)){  ListenerInfo li = mListenerInfo;  if(li != null && li.mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED  && li.mOnTouchListener.onTouch(this, event)) {  return true;  }  if(onTouchEvent(event)){  return true;  }  }  ... ...  return false;
}  

我们可以看到里面有这么一段:li.mOnTouchListener.onTouch(this, event)onTouchEvent(event) 并且前者写在前面,那么我们就可以推出,OnTouchListener 接口的 onTouch 方法的优先级是高于 View 里面自带的 onTouchEvent 方法的,当 View 设置了 OnTouchListener 接口并且 onTouch 方法返回 true 的时候, View 里面的 onTouchEvent 方法是不会被调用的。 所以说 OnTouchListener 接口和 View 中自带的 onTouchEvent 方法是不能同时使用的。有兴趣的小伙伴可以自己去试验一下。Ok,这个问题就解决了。

如果博客中有什么不正确的地方,还请多多指点。
谢谢观看。。。

Android 中 View 的手势事件处理相关推荐

  1. android中view手势滑动冲突的两种解决方法

    android中view手势滑动冲突的解决方法,主要解决方法有两种,外部和内部拦截.有需要的可以参考下. Android手势事件的冲突跟点击事件的分发过程息息相关,由三个重要的方法来共同完成,分别是: ...

  2. Android 中View的绘制机制源代码分析 三

    到眼下为止,measure过程已经解说完了,今天開始我们就来学习layout过程.只是在学习layout过程之前.大家有没有发现我换了编辑器,哈哈.最终下定决心从Html编辑器切换为markdown编 ...

  3. Android中View绘制流程以及invalidate()等相关方法分析

                                                                                                        ...

  4. Android 中View仅仅能接收到ACTION_DOWN无法接收ACTION_MOVE和ACTION_UP解决的方法

    Android 中View仅仅能接收到ACTION_DOWN无法接收ACTION_MOVE和ACTION_UP解决的方法 参考文章: (1)Android 中View仅仅能接收到ACTION_DOWN ...

  5. Android中View转换为Bitmap及getDrawingCache=null的解决方法

    Android中View转换为Bitmap及getDrawingCache=null的解决方法 参考文章: (1)Android中View转换为Bitmap及getDrawingCache=null的 ...

  6. Android中View绘制各种状态的背景图片原理深入分析以及StateListDrawable使用

    /* Call this to force a view to update its drawable state. This will cause drawableStateChanged to b ...

  7. android view 绘制过程,深入理解Android中View绘制的三大流程

    前言 最近对Android中View的绘制机制有了一些新的认识,所以想记录下来并分享给大家.View的工作流程主要是指measure.layout.draw这三大流程,即测量.布局和绘制,其中meas ...

  8. 深入解析Android中View的工作原理

    Android中的任何一个布局.任何一个控件其实都是直接或间接继承自View实现的,当然也包括我们在平时开发中所写的各种炫酷的自定义控件了,所以学习View的工作原理对于我们来说显得格外重要,本篇博客 ...

  9. android draw canvas,Android 中View.onDraw(Canvas canvas)的使用方法

    Android 中View.onDraw(Canvas canvas)的使用方法 View通过View.onDraw(Canvas canvas)来Draw. 我们可以定义自己的继承于View的Tes ...

最新文章

  1. java导入excle表格,并且对表格进行相应的修改,并对表格数据进行整理,最后导出本地表格等一系列...
  2. Java 常用对象-Date类和Calender类
  3. 三组关键词,拆解2021年赤子城的中期业绩报告
  4. 计算机系统基础:计算机性能评价知识笔记
  5. LuoguP5504 [JSOI2011]柠檬
  6. 多线程多进程解析:Python、os、sys、Queue、multiprocessing、threading
  7. C# 基础知识和VS2010的小技巧总汇(2)[转]
  8. INITRANS和MAXTRANS参数的作用
  9. phaser java_Java 7的并发编程-Phaser
  10. Windows 启动方式总结(转)
  11. 杜克大学计算机统计学,Duke的Statistical Science「杜克大学统计学系」
  12. Atiti  qq空间破解(3)------------gui图形化通用cli执行器atiuse
  13. 【教育知识与能力】人物总结
  14. 安信可CA-01首款4G模组以物模型连接阿里云物联网,实现远程控制;
  15. 交换机怎么用计算机配置文件,如何将交换机配置导入本地计算机做备份
  16. 迪士尼电影经过多年的
  17. Go语言与Java语言对比
  18. ASEMI整流桥GBP406~GBP410,GBP406参数,GBP410图片
  19. 人生重开模拟器怎么刷到神秘的小盒子
  20. consul-agent

热门文章

  1. 创建一个简单的workflow工作流(WF4)
  2. Unity 3D 菜单栏与快捷键
  3. ESXi社区版网卡驱动2022年3月更新
  4. PowerJob 的自实现高可用方案,妙妙妙!
  5. 孙正兴:普适计算与计算机视觉
  6. 软考 - 10 智能家居管理系统
  7. OpenGL之GLEW安装
  8. 有关嵌入式硬件测试的资料
  9. 163yum源的配置安装
  10. js删除数组中的指定对象