最近一直在学习自定义控件,搜了许多大牛们Blog里分享的小教程,也上GitHub找了一些类似的控件进行学习。发现读起来都不太好懂,就想写这么一篇东西作为学习笔记吧。

一、控件介绍:

进度条在App中非常常见,例如下载进度、加载图片、打开文章、打开网页等等……都需要这么一个效果让用户知道我们的App正在读取,以构造良好 的交互。如果没有这样一个效果的话,用户没法知道东西有没有下载好、图片加载了没有、文章打开了没……会让用户很不爽。基于这样的情景我们的UI设计师们 创造了这样一个控件。

二、这篇文章会涉及的知识点:

跟我一样刚入门的Android菜鸟们,我推荐大家先了解一下这些知识点再往下看。这些知识点我也会推荐一些博客给大家看看,更推荐大家看文档里的解释,当然大牛们可以直接无视……

1、ClipDrawable类:能够对一个drawable类进行剪切操作(即只显示某一部分的区域,另一部分隐藏),显示多大的区域由level控制(level取值是0~10000)

【博客:http://blog.csdn.net/lonelyroamer/article/details/8244777】、没文档的可以在这看【http://www.apihome.cn/api/android/ClipDrawable.html】

2、自定义View:guolin大神的深入学习View四部曲

Android LayoutInflater原理分析,带你一步步深入了解View —— http://blog.csdn.net/guolin_blog/article/details/12921889】

Android视图绘制流程完全解析,带你一步步深入了解View —— http://blog.csdn.net/guolin_blog/article/details/16330267】

Android视图状态及重绘流程分析,带你一步步深入了解View —— http://blog.csdn.net/guolin_blog/article/details/17045157】

Android自定义View的实现方法,带你一步步深入了解View ——

http://blog.csdn.net/guolin_blog/article/details/17357967】

3、没看过我写的:Android自定义控件——老版优酷三级菜单的话,或许需要看看这个:

【RotateAnimation详解——】

三、Android上的实现方式:

(前三种方法比较简单,第四种方法是GitHub项目的解析,对前三种没兴趣可以直接跳到后边……)

1、效果图:

将进度条的变换过程分解为一帧一帧的图片,将这些一帧一帧的图片连起来构成一个动画。常用于:手机阅读网页、逛社区时,加载图片、文章等不需要清楚知道加载进度,但是需要知道是否进行加载的情景。

这种方法实现可以通过创建一个animation-list的XML文件,然后给系统API提供的ProgressBar的indeterminateDrawable属性就可以了。(这个属性应该是类似于设置一个动画吧……)

<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false" >
<item android:duration="150" >
<clip
android:clipOrientation="horizontal"
android:drawable="@drawable/loading_01"
android:gravity="left"/>
</item>
<item android:duration="150" >
<clip
android:clipOrientation="horizontal"
android:drawable="@drawable/loading_02"
android:gravity="left"/>
</item>
<item android:duration="150" >
<clip
android:clipOrientation="horizontal"
android:drawable="@drawable/loading_03"
android:gravity="left"/>
</item>
<item android:duration="150" >
<clip
android:clipOrientation="horizontal"
android:drawable="@drawable/loading_04"
android:gravity="left"/>
</item>
<item android:duration="150" >
<clip
android:clipOrientation="horizontal"
android:drawable="@drawable/loading_05"
android:gravity="left"/>
</item>
<item android:duration="150" >
<clip
android:clipOrientation="horizontal"
android:drawable="@drawable/loading_06"
android:gravity="left"/>
</item>
<item android:duration="150" >
<clip
android:clipOrientation="horizontal"
android:drawable="@drawable/loading_07"
android:gravity="left"/>
</item>
<item android:duration="150" >
<clip
android:clipOrientation="horizontal"
android:drawable="@drawable/loading_08"
android:gravity="left"/>
</item>
<item android:duration="150" >
<clip
android:clipOrientation="horizontal"
android:drawable="@drawable/loading_09"
android:gravity="left"/>
</item>
<item android:duration="150" >
<clip
android:clipOrientation="horizontal"
android:drawable="@drawable/loading_10"
android:gravity="left"/>
</item>
<item android:duration="150" >
<clip
android:clipOrientation="horizontal"
android:drawable="@drawable/loading_11"
android:gravity="left"/>
</item>
<item android:duration="150" >
<clip
android:clipOrientation="horizontal"
android:drawable="@drawable/loading_12"
android:gravity="left"/>
</item> </animation-list>
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminateDrawable="@drawable/progressbar1"
/>

2 、效果图:

在上一篇有关自定义控件的博客里我们使用了一个RotateAnimation类来实现旋转效果 (http://blog.csdn.net/u012403246/article/details/41309161),其实,我们在这里也可以把一 张图片,通过旋转,达到我们要的效果。本质上和上一种方法没多大区别。

我们只需要创建一个rotate的XML,对其属性进行一些简单的设置,然后加入我们要用的图片就可以了。

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:pivotX="50%"
android:pivotY="50%"
android:fromDegrees="0"
android:toDegrees="360"
android:interpolator="@android:anim/accelerate_decelerate_interpolator" >
<bitmap
android:antialias="true"
android:filter="true"
android:src="@drawable/loading_360"/> </rotate>
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminateDrawable="@drawable/progressbar2"/>

3、效果图:

我们可以弄两张照片,第一张是纯黑色的,然后把这张照片中心挖一个圆出来,圆区域弄成白色,挖出来的圆弄成第二张照片。我们不妨叠加显示两张照片,刚开始把第二张完全“遮住”,随着加载进度的增加,我们减少遮住的区域把第二张照片慢慢的显示出来。

Android 上刚好就有这么一个ClipDrawable类,能够实现剪裁的过程。我们来看看怎么通过这样的方式自定义一个进度条控件。

public class MyProgressBar extends FrameLayout{
private boolean running;
private int progress = 0;
private static final int MAX_PROGRESS = 10000; private ClipDrawable clip; private Handler handler = new Handler(){
@Override
public void handleMessage(android.os.Message msg) {
if(msg.what == 0x123)
clip.setLevel(progress);
}
}; public MyProgressBar(Context context){
this(context,null,0);
} public MyProgressBar(Context context,AttributeSet attrs){
this(context,null,0);
} public MyProgressBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
Init(context);
} public void Init(Context context){
View view = LayoutInflater.from(context).inflate(R.layout.view, null); ImageView iv = (ImageView)view.findViewById(R.id.progress_img); addView(view);
clip = (ClipDrawable)iv.getDrawable(); Thread thread = new Thread(new Runnable() { @Override
public void run() {
running = true;
while(running){
handler.sendEmptyMessage(0x123);
if(progress == MAX_PROGRESS)
progress = 0;
progress += 100;
try {
Thread.sleep(18);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
thread.start();
} public void stop(){
progress = 0;
running = false;
}
}

通过代码我们可以看到,逻辑非常简单,关键就在于ClipDrawable的setLevel()方法,这个是设置剪裁效果的。

4、效果图:

实现一个View的子类——Progress Wheel类,实现进度条效果。具体的内容我都写在了注释上,如果不了解自定义控件的知识,可以去阅读guolin博客里自定义View四部曲的讲解,讲的挺好的。

代码 :

public class ProgressWheel extends View {

  //绘制View用到的各种长、宽带大小
private int layout_height = 0;
private int layout_width = 0;
private int fullRadius = 100;
private int circleRadius = 80;
private int barLength = 60;
private int barWidth = 20;
private int rimWidth = 20;
private int textSize = 20;
private float contourSize = 0; //与页边的间距
private int paddingTop = 5;
private int paddingBottom = 5;
private int paddingLeft = 5;
private int paddingRight = 5; //View要绘制的颜色
private int barColor = 0xAA000000;
private int contourColor = 0xAA000000;
private int circleColor = 0x00000000;
private int rimColor = 0xAADDDDDD;
private int textColor = 0xFF000000; //绘制要用的画笔
private Paint barPaint = new Paint();
private Paint circlePaint = new Paint();
private Paint rimPaint = new Paint();
private Paint textPaint = new Paint();
private Paint contourPaint = new Paint(); //绘制要用的矩形
@SuppressWarnings("unused")
private RectF rectBounds = new RectF();
private RectF circleBounds = new RectF();
private RectF circleOuterContour = new RectF();
private RectF circleInnerContour = new RectF(); //动画
//每次绘制要移动的像素数目
private int spinSpeed = 2;
//绘制过程的时间间隔
private int delayMillis = 0;
int progress = 0;
boolean isSpinning = false; //其他
private String text = "";
private String[] splitText = {}; /**
* ProgressWheel的构造方法
*
* @param context
* @param attrs
*/
public ProgressWheel(Context context, AttributeSet attrs) {
super(context, attrs); parseAttributes(context.obtainStyledAttributes(attrs,
R.styleable.ProgressWheel));
} //----------------------------------
//初始化一些元素
//---------------------------------- /*
* 调用这个方法时,使View绘制为方形
* From: http://www.jayway.com/2012/12/12/creating-custom-android-views-part-4-measuring-and-how-to-force-a-view-to-be-square/
*
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// 首先我们要调用超类的onMeasure借口
// 原因是我们自己去实现一个方法获得长度、宽度太麻烦了
// 使用超类的的方法非常方便而且让复杂的细节可控
super.onMeasure(widthMeasureSpec, heightMeasureSpec); // 在这里我们不能使用getWidth()和getHeight()。
// 因为这两个方法只能在View的布局完成后才能使用,而一个View的绘制过程是先绘制元素,再绘制Layout
// 所以我们必须使用getMeasuredWidth()和getMeasuredHeight()
int size = 0;
int width = getMeasuredWidth();
int height = getMeasuredHeight();
int widthWithoutPadding = width - getPaddingLeft() - getPaddingRight();
int heigthWithoutPadding = height - getPaddingTop() - getPaddingBottom(); // 最后我们用一些简单的逻辑去计算View的大小并调用setMeasuredDimension()去设置View的大小
// 在比较View的长宽前我们不考虑间距,但当我们设置View所需要绘制的面积时,我们要考虑它
// 不考虑间距的View(View内的实际画面)此时就应该是方形的,但是由于间距的存在,最终View所占的面积可能不是方形的
if (widthWithoutPadding > heigthWithoutPadding) {
size = heigthWithoutPadding;
} else {
size = widthWithoutPadding;
} // 如果你重写了onMeasure()方法,你必须调用setMeasuredDimension()方法
// 这是你设置View大小的唯一途径
// 如果你不调用setMeasuredDimension()方法,父控件会抛出异常,并且程序会崩溃
// 如果我们使用了超类的onMeasure()方法,我们就不是那么需要setMeasuredDimension()方法
// 然而,重写onMeasure()方法是为了改变既有的绘制流程,所以我们必须调用setMeasuredDimension()方法以达到我们的目的
setMeasuredDimension(size + getPaddingLeft() + getPaddingRight(), size + getPaddingTop() + getPaddingBottom());
} /**
* 使用onSizeChanged方法代替onAttachedToWindow获得View的面积
* 因为这个方法会在测量了MATCH_PARENT和WRAP_CONTENT后马上被调用
* 使用获得的面积设置View
*/
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh); // Share the dimensions
layout_width = w;
layout_height = h; setupBounds();
setupPaints();
invalidate();
} /**
* 设置我们想要绘制的progress wheel的颜色
*/
private void setupPaints() {
barPaint.setColor(barColor);
barPaint.setAntiAlias(true);
barPaint.setStyle(Style.STROKE);
barPaint.setStrokeWidth(barWidth); rimPaint.setColor(rimColor);
rimPaint.setAntiAlias(true);
rimPaint.setStyle(Style.STROKE);
rimPaint.setStrokeWidth(rimWidth); circlePaint.setColor(circleColor);
circlePaint.setAntiAlias(true);
circlePaint.setStyle(Style.FILL); textPaint.setColor(textColor);
textPaint.setStyle(Style.FILL);
textPaint.setAntiAlias(true);
textPaint.setTextSize(textSize); contourPaint.setColor(contourColor);
contourPaint.setAntiAlias(true);
contourPaint.setStyle(Style.STROKE);
contourPaint.setStrokeWidth(contourSize);
} /**
* 设置元素的边界
*/
private void setupBounds() {
// 为了保持宽度和长度的一致,我们要获得layout_width和layout_height中较小的一个,从而绘制一个圆
int minValue = Math.min(layout_width, layout_height); // 计算在绘制过程中在x,y方向的偏移量
int xOffset = layout_width - minValue;
int yOffset = layout_height - minValue; // 间距加上偏移量
paddingTop = this.getPaddingTop() + (yOffset / 2);
paddingBottom = this.getPaddingBottom() + (yOffset / 2);
paddingLeft = this.getPaddingLeft() + (xOffset / 2);
paddingRight = this.getPaddingRight() + (xOffset / 2); int width = getWidth(); //this.getLayoutParams().width;
int height = getHeight(); //this.getLayoutParams().height; rectBounds = new RectF(paddingLeft,
paddingTop,
width - paddingRight,
height - paddingBottom); circleBounds = new RectF(paddingLeft + barWidth,
paddingTop + barWidth,
width - paddingRight - barWidth,
height - paddingBottom - barWidth);
circleInnerContour = new RectF(circleBounds.left + (rimWidth / 2.0f) + (contourSize / 2.0f), circleBounds.top + (rimWidth / 2.0f) + (contourSize / 2.0f), circleBounds.right - (rimWidth / 2.0f) - (contourSize / 2.0f), circleBounds.bottom - (rimWidth / 2.0f) - (contourSize / 2.0f));
circleOuterContour = new RectF(circleBounds.left - (rimWidth / 2.0f) - (contourSize / 2.0f), circleBounds.top - (rimWidth / 2.0f) - (contourSize / 2.0f), circleBounds.right + (rimWidth / 2.0f) + (contourSize / 2.0f), circleBounds.bottom + (rimWidth / 2.0f) + (contourSize / 2.0f)); fullRadius = (width - paddingRight - barWidth) / 2;
circleRadius = (fullRadius - barWidth) + 1;
} /**
* 从XML中解析控件的属性
*
* @param a the attributes to parse
*/
private void parseAttributes(TypedArray a) {
barWidth = (int) a.getDimension(R.styleable.ProgressWheel_barWidth,
barWidth); rimWidth = (int) a.getDimension(R.styleable.ProgressWheel_rimWidth,
rimWidth); spinSpeed = (int) a.getDimension(R.styleable.ProgressWheel_spinSpeed,
spinSpeed); delayMillis = a.getInteger(R.styleable.ProgressWheel_delayMillis,
delayMillis);
if (delayMillis < 0) {
delayMillis = 0;
} barColor = a.getColor(R.styleable.ProgressWheel_barColor, barColor); barLength = (int) a.getDimension(R.styleable.ProgressWheel_barLength,
barLength); textSize = (int) a.getDimension(R.styleable.ProgressWheel_textSize,
textSize); textColor = (int) a.getColor(R.styleable.ProgressWheel_textColor,
textColor); //如果text是空的,就无视它
if (a.hasValue(R.styleable.ProgressWheel_text)) {
setText(a.getString(R.styleable.ProgressWheel_text));
} rimColor = (int) a.getColor(R.styleable.ProgressWheel_rimColor,
rimColor); circleColor = (int) a.getColor(R.styleable.ProgressWheel_circleColor,
circleColor); contourColor = a.getColor(R.styleable.ProgressWheel_contourColor, contourColor);
contourSize = a.getDimension(R.styleable.ProgressWheel_contourSize, contourSize); // 使用TypedArray获得控件属性时必须要注意:使用结束后必须回收TypedArray的对象
a.recycle();
} //----------------------------------
//动画
//---------------------------------- protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//绘制内圆
canvas.drawArc(circleBounds, 360, 360, false, circlePaint);
//绘制边界
canvas.drawArc(circleBounds, 360, 360, false, rimPaint);
canvas.drawArc(circleOuterContour, 360, 360, false, contourPaint);
canvas.drawArc(circleInnerContour, 360, 360, false, contourPaint);
//绘制条纹
if (isSpinning) {
canvas.drawArc(circleBounds, progress - 90, barLength, false,
barPaint);
} else {
canvas.drawArc(circleBounds, -90, progress, false, barPaint);
}
//绘制我们想要设置的文字 (并让它显示在圆水平和垂直方向的中心处)
float textHeight = textPaint.descent() - textPaint.ascent();
float verticalTextOffset = (textHeight / 2) - textPaint.descent(); for (String s : splitText) {
float horizontalTextOffset = textPaint.measureText(s) / 2;
canvas.drawText(s, this.getWidth() / 2 - horizontalTextOffset,
this.getHeight() / 2 + verticalTextOffset, textPaint);
}
if (isSpinning) {
scheduleRedraw();
}
} private void scheduleRedraw() {
progress += spinSpeed;
if (progress > 360) {
progress = 0;
}
postInvalidateDelayed(delayMillis);
} /**
* 判断wheel是否在旋转
*/ public boolean isSpinning() {
if(isSpinning){
return true;
} else {
return false;
}
} /**
* 重设进度条的值
*/
public void resetCount() {
progress = 0;
setText("0%");
invalidate();
} /**
* 停止进度条的旋转
*/
public void stopSpinning() {
isSpinning = false;
progress = 0;
postInvalidate();
} /**
* 让进度条开启旋转模式
*/
public void spin() {
isSpinning = true;
postInvalidate();
} /**
* 让进度条每次增加1(最大值为360)
*/
public void incrementProgress() {
isSpinning = false;
progress++;
if (progress > 360)
progress = 0;
setText(Math.round(((float) progress / 360) * 100) + "%");
postInvalidate();
} /**
* 设置进度条为一个确切的数值
*/
public void setProgress(int i) {
isSpinning = false;
progress = i;
postInvalidate();
} //----------------------------------
//get和set方法
//---------------------------------- /**
* 设置progress bar的文字并不需要刷新View
*
* @param text the text to show ('\n' constitutes a new line)
*/
public void setText(String text) {
this.text = text;
splitText = this.text.split("\n");
} public int getCircleRadius() {
return circleRadius;
} public void setCircleRadius(int circleRadius) {
this.circleRadius = circleRadius;
} public int getBarLength() {
return barLength;
} public void setBarLength(int barLength) {
this.barLength = barLength;
} public int getBarWidth() {
return barWidth;
} public void setBarWidth(int barWidth) {
this.barWidth = barWidth; if ( this.barPaint != null ) {
this.barPaint.setStrokeWidth( this.barWidth );
}
} public int getTextSize() {
return textSize;
} public void setTextSize(int textSize) {
this.textSize = textSize; if ( this.textPaint != null ) {
this.textPaint.setTextSize( this.textSize );
}
} public int getPaddingTop() {
return paddingTop;
} public void setPaddingTop(int paddingTop) {
this.paddingTop = paddingTop;
} public int getPaddingBottom() {
return paddingBottom;
} public void setPaddingBottom(int paddingBottom) {
this.paddingBottom = paddingBottom;
} public int getPaddingLeft() {
return paddingLeft;
} public void setPaddingLeft(int paddingLeft) {
this.paddingLeft = paddingLeft;
} public int getPaddingRight() {
return paddingRight;
} public void setPaddingRight(int paddingRight) {
this.paddingRight = paddingRight;
} public int getBarColor() {
return barColor;
} public void setBarColor(int barColor) {
this.barColor = barColor; if ( this.barPaint != null ) {
this.barPaint.setColor( this.barColor );
}
} public int getCircleColor() {
return circleColor;
} public void setCircleColor(int circleColor) {
this.circleColor = circleColor; if ( this.circlePaint != null ) {
this.circlePaint.setColor( this.circleColor);
}
} public int getRimColor() {
return rimColor;
} public void setRimColor(int rimColor) {
this.rimColor = rimColor; if ( this.rimPaint != null ) {
this.rimPaint.setColor( this.rimColor );
}
} public Shader getRimShader() {
return rimPaint.getShader();
} public void setRimShader(Shader shader) {
this.rimPaint.setShader(shader);
} public int getTextColor() {
return textColor;
} public void setTextColor(int textColor) {
this.textColor = textColor; if ( this.textPaint != null ) {
this.textPaint.setColor( this.textColor );
}
} public int getSpinSpeed() {
return spinSpeed;
} public void setSpinSpeed(int spinSpeed) {
this.spinSpeed = spinSpeed;
} public int getRimWidth() {
return rimWidth;
} public void setRimWidth(int rimWidth) {
this.rimWidth = rimWidth; if ( this.rimPaint != null ) {
this.rimPaint.setStrokeWidth( this.rimWidth );
}
} public int getDelayMillis() {
return delayMillis;
} public void setDelayMillis(int delayMillis) {
this.delayMillis = delayMillis;
} public int getContourColor() {
return contourColor;
} public void setContourColor(int contourColor) {
this.contourColor = contourColor; if ( contourPaint != null ) {
this.contourPaint.setColor( this.contourColor );
}
} public float getContourSize() {
return this.contourSize;
} public void setContourSize(float contourSize) {
this.contourSize = contourSize; if ( contourPaint != null ) {
this.contourPaint.setStrokeWidth( this.contourSize );
}
}
}

---------------------
作者:oooo呼呼
来源:CNBLOGS
原文:https://www.cnblogs.com/wangying222/p/5304990.html
版权声明:本文为作者原创文章,转载请附上博文链接!

[转]Android自定义控件:进度条的四种实现方式(Progress Wheel的解析)的更多相关文章

  1. Android自定义控件:进度条的四种实现方式(Progress Wheel的解析)

    最近一直在学习自定义控件,搜了许多大牛们Blog里分享的小教程,也上GitHub找了一些类似的控件进行学习.发现读起来都不太好懂,就想写这么一篇东西作为学习笔记吧. 一.控件介绍: 进度条在App中非 ...

  2. Android自己定义控件:进度条的四种实现方式

    前三种实现方式代码出自: http://stormzhang.com/openandroid/2013/11/15/android-custom-loading/ (源代码下载)http://down ...

  3. Android开发_Android数据的四种存储方式

    Android系统一共提供了四种数据存储方式.分别是:SharePreference.SQLite.Content Provider和File.由于Android系统中,数据基本都是私有的的,都是存放 ...

  4. (四十二)c#Winform自定义控件-进度条扩展

    前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. GitHub:https://github.com/kwwwvagaa/NetWinformControl 码云:ht ...

  5. (四十一)c#Winform自定义控件-进度条

    前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. 开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control ...

  6. Android开发之基本控件和详解四种布局方式

    Android中的控件的使用方式和iOS中控件的使用方式基本相同,都是事件驱动.给控件添加事件也有接口回调和委托代理的方式.今天这篇博客就总结一下Android中常用的基本控件以及布局方式.说到布局方 ...

  7. Android多种进度条使用详解

    在这里,总结一下loading进度条的使用简单总结一下. 一.说起进度条,必须说说条形进度条,经常都会使用到嘛,特别是下载文件进度等等,还有像腾讯QQ安装进度条一样,有个进度总给人良好的用户体验. 先 ...

  8. Android loading进度条使用简单总结

    在这里,总结一下loading进度条的使用简单总结一下. 一.说起进度条,必须说说条形进度条,经常都会使用到嘛,特别是下载文件进度等等,还有像腾讯QQ安装进度条一样,有个进度总给人良好的用户体验. 先 ...

  9. Android数据的四种存储方式

    作为一个完成的应用程序,数据存储操作是必不可少的.因此,Android系统一共提供了四种数据存储方式.分别是:SharePreference.SQLite.Content Provider和File. ...

随机推荐

  1. Sublime Text3安装教程,配置教程,常用插件安装等方法

    前言: sublimeText3的特点: 1.Sublime Text 是一款跨平台代码编辑器,在Linux.OS X和Windows下均可使用. 2.Sublime Text 是可扩展的,并包含大量 ...

  2. LeetCode136 Single Number, LeetCode137 Single Number II, LeetCode260 Single Number III

    136. Single Number Given an array of integers, every element appears twice except for one. Find that ...

  3. Mac查看Python安装路径和版本

    目录 #查看当前所有Python版本路径 appledeMBP:~ apple$ which python2.7 /usr/local/bin/python2.7 appledeMBP:~ apple ...

  4. Directx11教程(58) 鼠标控制摄像机

    原文:Directx11教程(58) 鼠标控制摄像机        本篇教程我们实现鼠标旋转摄像机的操作.主要就是按下鼠标左键的时候,根据鼠标的移动对摄像机进行pitch, raw的组合旋转.具体修改 ...

  5. oracle水线的定义

    1.水线定义了表的数据在一个BLOCK中所达到的最高的位置. 2.当有新的记录插入,水线增高 3.当删除记录时,水线不回落 4.减少查询量

  6. @spoj - ADAMOLD@ Ada and Mold

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定一个长度为 N 的序列 A,将其划分成 K + 1 段,划分 ...

  7. 杨柳目-杨柳科-Info-新闻:注意了!杨絮解决有办法了

    ylbtech-杨柳目-杨柳科-Info-新闻:注意了!杨絮解决有办法了  1.返回顶部 1. 注意了!杨絮解决有办法了 2018-05-03 14:18 昨天中午经过一个理发店,门口蹲了个染黄发.系 ...

  8. 集合--Collection接口详解&&迭代器

    /* * 集合的顶层接口--Collection接口 * 添加 * add() * addAll() * * 遍历集合 * iterator() 迭代器 * * 删除 * remove() * rem ...

  9. 【JZOJ4817】【NOIP2016提高A组五校联考4】square

    题目描述 输入 输出 样例输入 3 4 1 1 0 1 0 1 1 0 0 1 1 0 5 1 1 2 3 2 1 3 2 3 2 3 4 1 1 3 4 1 2 3 4 样例输出 1 1 1 2 2 ...

  10. hdu5137 枚举删点

    #include<stdio.h> #include<string.h> #include<algorithm> using namespace std; ; ; ...