最近一直在学习自定义控件,搜了许多大牛们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 );
}
}
}

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. Configure the Struts Tag Libraries

    In Struts framework, you always need to configure the Struts tag libraries in order to access it in ...

  2. Jsp页面设计易忘点

    文本标签: <b>文本加粗 <i>斜体 <u>下划线 <sub>作为下标 <sup>作为上标 样式: italic;斜体 text-deco ...

  3. [iOS微博项目 - 2.5] - 封装授权和用户信息读写业务

    github: https://github.com/hellovoidworld/HVWWeibo   A.封装授权业务 1.把app的授权信息移动到HVWWeibo-Prefix.pch中作为公共 ...

  4. JavaScript学习——内置属性

    在js中,几乎所有的对象都是同源对象,都继承Object对象.对象的内置属性指的是它们作为Object实例所具有的属性,这些属性通常反映对象本身的基本信息和数据无关.因此我们称它们为元属性.这些属性通 ...

  5. hdoj 5326 Work

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5326 #include<stdio.h> #include<cstring> ...

  6. java 对excel操作导入excel数据到数据库

    加入jar包jxl.jar ===================services层掉用工具类==================================== // 导入 public Lis ...

  7. Unity中的C#规则

    命名 文件名和Class要一致(CamelCase) 类公共和保护类型Property(CamelCase) 类的公共和保护类型Fields(CamelCase)* 先采用.Net的命名方法,如果出现 ...

  8. JS:公历、农历互转

    先申明这段代码不是我写的,纯粹只是觉的比较好用,所以记录下来以后继续使用,也同样分享给大家,大家有更好的可以推荐给我,谢谢! function CalConv(M, dateStr) { if (da ...

  9. JPA一对多和多对一关系

    1-m:多的一方为关系维护端,关系维护端负责外键纪录的更新,关系被维护端没有权力更新外键纪录. 维护端注解 @OneToMany(cascade = { CascadeType.PERSIST, Ca ...

  10. 如何让DIV相对于body水平和垂直居中

    我们在设计页面的时候,经常要把DIV居中显示,而且是相对页面窗口水平和垂直方向居中显示,如让登录窗口居中显示.我们传统解决的办法是用纯CSS来让DIV居中.在本文中,我将给大家讲述如何用CSS和jQu ...