转载请表明出处:http://blog.csdn.net/lmj623565791/article/details/39761281,本文出自:【张鸿洋的博客】

1、概述

前面已经写了关于检测手势识别的文章,如果不了解可以参考:Android 手势检测实战 打造支持缩放平移的图片预览效果(下)。首先本篇文章,将对之前博客的ZoomImageView代码进行些许的修改与改善,然后用到我们的本篇博客中去,实现仿微信的头像截取功能,当然了,个人觉得微信的截取头像功能貌似做得不太好,本篇博客准备去其糟粕,取其精华;最后还会见识到不一样的自定义控件的方式,也是在本人博客中首次出现,如果有兴趣可以读完本篇博客,希望可以启到抛砖引玉的效果。

2、效果分析

1、效果图:

我们来看看妹子的项链,嗯,妹子项链还是不错的~

2、效果分析

根据上面的效果,我们目测需要自定义两个控件,一个就是我们的可自由缩放移动的ImageView,一个就是那个白色的边框;然后一起放置到一个RelativeLayout中;最后对外公布一个裁剪的方法,返回一个Bitmap;

暂时的分析就这样,下面我们来写代码~

首先是白色框框那个自定义View,我们叫做ClipImageBorderView

3、ClipImageBorderView

分析下这个View,其实就是根据在屏幕中绘制一个正方形,正方形区域以外为半透明,绘制这个正方形需要与屏幕左右边距有个边距。

我们准备按如下图绘制:

按顺序在View的onDraw里面绘制上图中:1、2、3、4,四个半透明的区域,然后在中间正方形区域绘制一个正方形

下面看下代码:

  1. package com.zhy.view;
  2. import android.content.Context;
  3. import android.graphics.Canvas;
  4. import android.graphics.Color;
  5. import android.graphics.Paint;
  6. import android.graphics.Paint.Style;
  7. import android.util.AttributeSet;
  8. import android.util.TypedValue;
  9. import android.view.View;
  10. /**
  11. * @author zhy
  12. *
  13. */
  14. public class ClipImageBorderView extends View
  15. {
  16. /**
  17. * 水平方向与View的边距
  18. */
  19. private int mHorizontalPadding = 20;
  20. /**
  21. * 垂直方向与View的边距
  22. */
  23. private int mVerticalPadding;
  24. /**
  25. * 绘制的矩形的宽度
  26. */
  27. private int mWidth;
  28. /**
  29. * 边框的颜色,默认为白色
  30. */
  31. private int mBorderColor = Color.parseColor("#FFFFFF");
  32. /**
  33. * 边框的宽度 单位dp
  34. */
  35. private int mBorderWidth = 1;
  36. private Paint mPaint;
  37. public ClipImageBorderView(Context context)
  38. {
  39. this(context, null);
  40. }
  41. public ClipImageBorderView(Context context, AttributeSet attrs)
  42. {
  43. this(context, attrs, 0);
  44. }
  45. public ClipImageBorderView(Context context, AttributeSet attrs, int defStyle)
  46. {
  47. super(context, attrs, defStyle);
  48. // 计算padding的px
  49. mHorizontalPadding = (int) TypedValue.applyDimension(
  50. TypedValue.COMPLEX_UNIT_DIP, mHorizontalPadding, getResources()
  51. .getDisplayMetrics());
  52. mBorderWidth = (int) TypedValue.applyDimension(
  53. TypedValue.COMPLEX_UNIT_DIP, mBorderWidth, getResources()
  54. .getDisplayMetrics());
  55. mPaint = new Paint();
  56. mPaint.setAntiAlias(true);
  57. }
  58. @Override
  59. protected void onDraw(Canvas canvas)
  60. {
  61. super.onDraw(canvas);
  62. //计算矩形区域的宽度
  63. mWidth = getWidth() - 2 * mHorizontalPadding;
  64. //计算距离屏幕垂直边界 的边距
  65. mVerticalPadding = (getHeight() - mWidth) / 2;
  66. mPaint.setColor(Color.parseColor("#aa000000"));
  67. mPaint.setStyle(Style.FILL);
  68. // 绘制左边1
  69. canvas.drawRect(0, 0, mHorizontalPadding, getHeight(), mPaint);
  70. // 绘制右边2
  71. canvas.drawRect(getWidth() - mHorizontalPadding, 0, getWidth(),
  72. getHeight(), mPaint);
  73. // 绘制上边3
  74. canvas.drawRect(mHorizontalPadding, 0, getWidth() - mHorizontalPadding,
  75. mVerticalPadding, mPaint);
  76. // 绘制下边4
  77. canvas.drawRect(mHorizontalPadding, getHeight() - mVerticalPadding,
  78. getWidth() - mHorizontalPadding, getHeight(), mPaint);
  79. // 绘制外边框
  80. mPaint.setColor(mBorderColor);
  81. mPaint.setStrokeWidth(mBorderWidth);
  82. mPaint.setStyle(Style.STROKE);
  83. canvas.drawRect(mHorizontalPadding, mVerticalPadding, getWidth()
  84. - mHorizontalPadding, getHeight() - mVerticalPadding, mPaint);
  85. }
  86. }

我们直接预设了一个水平方向的边距,根据边距计算出正方形的边长,接下来就是按照上图分别会1、2、3、4四个区域,最后就是绘制我们的正方形~~

代码还是很简单的~~我们的ClipImageBorderView就搞定了,我们决定来测试一下:

布局文件:

  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:tools="http://schemas.android.com/tools"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:background="@drawable/a"   >
  6. <com.zhy.view.ClipImageBorderView
  7. android:id="@+id/id_clipImageLayout"
  8. android:layout_width="fill_parent"
  9. android:layout_height="fill_parent" />
  10. </RelativeLayout>

效果图:

故意放了个背景,没撒用,就是为了能看出效果,可以看到我们的框框绘制的还是蛮不错的~~嗯,这个框框距离屏幕左右两侧的距离应该抽取出来,嗯,后面再说~

4、ClipZoomImageView

我们准备对我们原先的ZoomImageView进行简单的修改,修改的地方:
1、在onGlobalLayout方法中,如果图片的宽或者高只要一个小于我们的正方形的边长,我们会直接把较小的尺寸放大至正方形的边长;如果图片的宽和高都大于我们的正方形的边长,我们仅仅把图片移动到我们屏幕的中央,不做缩放处理;

2、根据步骤1,我们会获得初始的缩放比例(默认为1.0f),然后SCALE_MID , 与 SCALE_MAX 分别为2倍和4倍的初始化缩放比例。

3、图片在移动过程中的边界检测完全根据正方形的区域,图片不会在移动过程中与正方形区域产生内边距

4、对外公布一个裁切的方法

部分代码:

  1. /**
  2. * 水平方向与View的边距
  3. */
  4. private int mHorizontalPadding = 20;
  5. /**
  6. * 垂直方向与View的边距
  7. */
  8. private int mVerticalPadding;
  9. @Override
  10. public void onGlobalLayout()
  11. {
  12. if (once)
  13. {
  14. Drawable d = getDrawable();
  15. if (d == null)
  16. return;
  17. Log.e(TAG, d.getIntrinsicWidth() + " , " + d.getIntrinsicHeight());
  18. // 计算padding的px
  19. mHorizontalPadding = (int) TypedValue.applyDimension(
  20. TypedValue.COMPLEX_UNIT_DIP, mHorizontalPadding,
  21. getResources().getDisplayMetrics());
  22. // 垂直方向的边距
  23. mVerticalPadding = (getHeight() - (getWidth() - 2 * mHorizontalPadding)) / 2;
  24. int width = getWidth();
  25. int height = getHeight();
  26. // 拿到图片的宽和高
  27. int dw = d.getIntrinsicWidth();
  28. int dh = d.getIntrinsicHeight();
  29. float scale = 1.0f;
  30. if (dw < getWidth() - mHorizontalPadding * 2
  31. && dh > getHeight() - mVerticalPadding * 2)
  32. {
  33. scale = (getWidth() * 1.0f - mHorizontalPadding * 2) / dw;
  34. }
  35. if (dh < getHeight() - mVerticalPadding * 2
  36. && dw > getWidth() - mHorizontalPadding * 2)
  37. {
  38. scale = (getHeight() * 1.0f - mVerticalPadding * 2) / dh;
  39. }
  40. if (dw < getWidth() - mHorizontalPadding * 2
  41. && dh < getHeight() - mVerticalPadding * 2)
  42. {
  43. float scaleW = (getWidth() * 1.0f - mHorizontalPadding * 2)
  44. / dw;
  45. float scaleH = (getHeight() * 1.0f - mVerticalPadding * 2) / dh;
  46. scale = Math.max(scaleW, scaleH);
  47. }
  48. initScale = scale;
  49. SCALE_MID = initScale * 2;
  50. SCALE_MAX = initScale * 4;
  51. Log.e(TAG, "initScale = " + initScale);
  52. mScaleMatrix.postTranslate((width - dw) / 2, (height - dh) / 2);
  53. mScaleMatrix.postScale(scale, scale, getWidth() / 2,
  54. getHeight() / 2);
  55. // 图片移动至屏幕中心
  56. setImageMatrix(mScaleMatrix);
  57. once = false;
  58. }
  59. }
  60. /**
  61. * 剪切图片,返回剪切后的bitmap对象
  62. *
  63. * @return
  64. */
  65. public Bitmap clip()
  66. {
  67. Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(),
  68. Bitmap.Config.ARGB_8888);
  69. Canvas canvas = new Canvas(bitmap);
  70. draw(canvas);
  71. return Bitmap.createBitmap(bitmap, mHorizontalPadding,
  72. mVerticalPadding, getWidth() - 2 * mHorizontalPadding,
  73. getWidth() - 2 * mHorizontalPadding);
  74. }
  75. /**
  76. * 边界检测
  77. */
  78. private void checkBorder()
  79. {
  80. RectF rect = getMatrixRectF();
  81. float deltaX = 0;
  82. float deltaY = 0;
  83. int width = getWidth();
  84. int height = getHeight();
  85. // 如果宽或高大于屏幕,则控制范围
  86. if (rect.width() >= width - 2 * mHorizontalPadding)
  87. {
  88. if (rect.left > mHorizontalPadding)
  89. {
  90. deltaX = -rect.left + mHorizontalPadding;
  91. }
  92. if (rect.right < width - mHorizontalPadding)
  93. {
  94. deltaX = width - mHorizontalPadding - rect.right;
  95. }
  96. }
  97. if (rect.height() >= height - 2 * mVerticalPadding)
  98. {
  99. if (rect.top > mVerticalPadding)
  100. {
  101. deltaY = -rect.top + mVerticalPadding;
  102. }
  103. if (rect.bottom < height - mVerticalPadding)
  104. {
  105. deltaY = height - mVerticalPadding - rect.bottom;
  106. }
  107. }
  108. mScaleMatrix.postTranslate(deltaX, deltaY);
  109. }

这里贴出了改变的代码,完整的代码就不贴了,太长了,如果大家学习过前面的博客应该也会比较熟悉,若没有也没事,后面会提供源码。

贴代码的目的,第一让大家看下我们改变了哪些;第二,我想暴露出我们代码中的问题,我们设置了一个这样的变量:mHorizontalPadding = 20;这个是手动和ClipImageBorderView里面的成员变量mHorizontalPadding 写的一致,也就是说这个变量,两个自定义的View都需要使用且需要相同的值,目前我们的做法,写死且每个View各自定义一个。这种做法不用说,肯定不好,即使抽取成自定义属性,两个View都需要进行抽取,且用户在使用的时候,还需要设置为一样的值,总觉得有点强人所难~~

5、不一样的自定义控件

现在我们考虑下:易用性。目前为止,其实我们的效果已经实现了,但是需要用户这么写布局文件:

  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:tools="http://schemas.android.com/tools"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:background="#aaaaaa" >
  6. <com.zhy.view.ZoomImageView
  7. android:id="@+id/id_zoomImageView"
  8. android:layout_width="fill_parent"
  9. android:layout_height="fill_parent"
  10. android:scaleType="matrix"
  11. android:src="@drawable/a" />
  12. <com.zhy.view.ClipImageView
  13. android:layout_width="fill_parent"
  14. android:layout_height="fill_parent" />
  15. </RelativeLayout>

然后这两个类中都有一个mHorizontalPadding变量,且值一样,上面也说过,即使抽取成自定义变量,也需要在布局文件中每个View中各写一次。so, we need change . 这样的耦合度太夸张了,且使用起来蹩脚。

于是乎,我决定把这两个控件想办法整到一起,用户使用时只需要声明一个控件:

怎么做呢,我们使用组合的思想来自定义控件,我们再声明一个控件,继承子RelativeLayout,然后在这个自定义RelativeLayout中通过代码添加这两个自定义的布局,并且设置一些公用的属性,具体我们就开始行动。

1、ClipImageLayout

我们自定义一个RelativeLayout叫做ClipImageLayout,用于放置我们的两个自定义View,并且由ClipImageLayout进行设置边距,然后传给它内部的两个View,这样的话,跟用户交互的就一个ClipImageLayout,用户只需要设置一次边距即可。

完整的ClipImageLayout代码:

  1. package com.zhy.view;
  2. import android.content.Context;
  3. import android.graphics.Bitmap;
  4. import android.util.AttributeSet;
  5. import android.util.TypedValue;
  6. import android.widget.RelativeLayout;
  7. import com.zhy.clippic.R;
  8. /**
  9. * zhy
  10. * @author zhy
  11. *
  12. */
  13. public class ClipImageLayout extends RelativeLayout
  14. {
  15. private ClipZoomImageView mZoomImageView;
  16. private ClipImageBorderView mClipImageView;
  17. /**
  18. * 这里测试,直接写死了大小,真正使用过程中,可以提取为自定义属性
  19. */
  20. private int mHorizontalPadding = 20;
  21. public ClipImageLayout(Context context, AttributeSet attrs)
  22. {
  23. super(context, attrs);
  24. mZoomImageView = new ClipZoomImageView(context);
  25. mClipImageView = new ClipImageBorderView(context);
  26. android.view.ViewGroup.LayoutParams lp = new LayoutParams(
  27. android.view.ViewGroup.LayoutParams.MATCH_PARENT,
  28. android.view.ViewGroup.LayoutParams.MATCH_PARENT);
  29. /**
  30. * 这里测试,直接写死了图片,真正使用过程中,可以提取为自定义属性
  31. */
  32. mZoomImageView.setImageDrawable(getResources().getDrawable(
  33. R.drawable.a));
  34. this.addView(mZoomImageView, lp);
  35. this.addView(mClipImageView, lp);
  36. // 计算padding的px
  37. mHorizontalPadding = (int) TypedValue.applyDimension(
  38. TypedValue.COMPLEX_UNIT_DIP, mHorizontalPadding, getResources()
  39. .getDisplayMetrics());
  40. mZoomImageView.setHorizontalPadding(mHorizontalPadding);
  41. mClipImageView.setHorizontalPadding(mHorizontalPadding);
  42. }
  43. /**
  44. * 对外公布设置边距的方法,单位为dp
  45. *
  46. * @param mHorizontalPadding
  47. */
  48. public void setHorizontalPadding(int mHorizontalPadding)
  49. {
  50. this.mHorizontalPadding = mHorizontalPadding;
  51. }
  52. /**
  53. * 裁切图片
  54. *
  55. * @return
  56. */
  57. public Bitmap clip()
  58. {
  59. return mZoomImageView.clip();
  60. }
  61. }

可以看到,现在用户需要使用头像裁切功能只需要声明下ClipImageLayout即可,完全避免了上述我们描述的问题,我们对用户屏蔽了两个真正实现的类。这个也是自定义控件的一种方式,希望可以借此抛砖引玉,大家能够更加合理的设计出自己的控件~~

好了,我们的ClipImageLayout搞定以后,下面看下如何使用~

6、用法

1、布局文件

  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:tools="http://schemas.android.com/tools"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:background="#aaaaaa"   >
  6. <com.zhy.view.ClipImageLayout
  7. android:id="@+id/id_clipImageLayout"
  8. android:layout_width="fill_parent"
  9. android:layout_height="fill_parent" />
  10. </RelativeLayout>

2、MainActivity

  1. package com.zhy.clippic;
  2. import java.io.ByteArrayOutputStream;
  3. import android.app.Activity;
  4. import android.content.Intent;
  5. import android.graphics.Bitmap;
  6. import android.os.Bundle;
  7. import android.view.Menu;
  8. import android.view.MenuItem;
  9. import com.zhy.view.ClipImageLayout;
  10. public class MainActivity extends Activity
  11. {
  12. private ClipImageLayout mClipImageLayout;
  13. @Override
  14. protected void onCreate(Bundle savedInstanceState)
  15. {
  16. super.onCreate(savedInstanceState);
  17. setContentView(R.layout.activity_main);
  18. mClipImageLayout = (ClipImageLayout) findViewById(R.id.id_clipImageLayout);
  19. }
  20. @Override
  21. public boolean onCreateOptionsMenu(Menu menu)
  22. {
  23. getMenuInflater().inflate(R.menu.main, menu);
  24. return true;
  25. }
  26. @Override
  27. public boolean onOptionsItemSelected(MenuItem item)
  28. {
  29. switch (item.getItemId())
  30. {
  31. case R.id.id_action_clip:
  32. Bitmap bitmap = mClipImageLayout.clip();
  33. ByteArrayOutputStream baos = new ByteArrayOutputStream();
  34. bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
  35. byte[] datas = baos.toByteArray();
  36. Intent intent = new Intent(this, ShowImageActivity.class);
  37. intent.putExtra("bitmap", datas);
  38. startActivity(intent);
  39. break;
  40. }
  41. return super.onOptionsItemSelected(item);
  42. }
  43. }

我们在menu里面体检了一个裁切的按钮,点击后把裁切好的图片传递给我们的ShowImageActivity

看一下眼menu的xml

  1. <menu xmlns:android="http://schemas.android.com/apk/res/android" >
  2. <item
  3. android:id="@+id/id_action_clip"
  4. android:icon="@drawable/actionbar_clip_icon"
  5. android:showAsAction="always|withText"
  6. android:title="裁切"/>
  7. </menu>

3、ShowImageActivity

  1. package com.zhy.clippic;
  2. import android.app.Activity;
  3. import android.graphics.Bitmap;
  4. import android.graphics.BitmapFactory;
  5. import android.os.Bundle;
  6. import android.widget.ImageView;
  7. public class ShowImageActivity extends Activity
  8. {
  9. private ImageView mImageView;
  10. @Override
  11. protected void onCreate(Bundle savedInstanceState)
  12. {
  13. super.onCreate(savedInstanceState);
  14. setContentView(R.layout.show);
  15. mImageView = (ImageView) findViewById(R.id.id_showImage);
  16. byte[] b = getIntent().getByteArrayExtra("bitmap");
  17. Bitmap bitmap = BitmapFactory.decodeByteArray(b, 0, b.length);
  18. if (bitmap != null)
  19. {
  20. mImageView.setImageBitmap(bitmap);
  21. }
  22. }
  23. }

layout/show.xml

  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:tools="http://schemas.android.com/tools"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:background="#ffffff" >
  6. <ImageView
  7. android:id="@+id/id_showImage"
  8. android:layout_width="wrap_content"
  9. android:layout_height="wrap_content"
  10. android:layout_centerInParent="true"
  11. android:src="@drawable/tbug"
  12. />
  13. </RelativeLayout>

好了,到此我们的 高仿微信头像截取功能 就已经结束了~~希望大家可以从本篇博客中可以领悟到something~

最后我们把ClipImageLayout里面的mHorizontalPadding设置为50,贴个静态效果图~

ok ~~

源码点击下载

Android 高仿微信头像截取 打造不一样的自定义控件的更多相关文章

  1. 安卓高仿QQ头像截取升级版

    观看此篇文章前,请先阅读上篇文章:高仿QQ头像截取: 本篇之所以为升级版,是在截取头像界面添加了与qq类似的阴影层(裁剪区域以外的部分),且看效果图:   为了适应大家不同需求,这次打了两个包,及上图 ...

  2. 高仿QQ头像截取

    花费了半天时间,把 仿QQ头像截取的方法整理了下,并制作了一个demo以供大家参考,基本上实现了qq中我的资料界面上(包括背景透明化,上滑标题栏显示,下拉隐藏等)的大致效果,先上图看效果吧: 支持的功 ...

  3. Android 高仿微信6.0主界面 带你玩转切换图标变色

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/41087219,本文出自:[张鸿洋的博客] 1.概述 学习Android少不了模仿 ...

  4. Android 高仿微信语音聊天页面高斯模糊效果

    目前的应用市场上,使用毛玻璃效果的APP随处可见,比如用过微信语音聊天的人可以发现,语音聊天页面就使用了高斯模糊效果. 先看下效果图: 仔细观察上图,我们可以发现,背景图以用户头像为模板,对其进行了高 ...

  5. Android高仿微信(一)——如何消除启动时的白屏

    默认情况下,APP启动时会先把屏幕刷成白色,然后才绘制第一个Activity中的View,这两个步骤之间的延迟会造成启动后先看到白屏(时间大概为1秒左右).时间不长,但是我们也看到,一般的APP时不存 ...

  6. Android 高仿微信实时聊天 基于百度云推送

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38799363 ,本文出自:[张鸿洋的博客] 一直在仿微信界面,今天终于有幸利用百 ...

  7. android高仿微信拍照、多选、预览、删除(去除相片)相冊功能

    先声明授人与鱼不如授人与渔,仅仅能提供一个思路,当然须要源代码的同学能够私下有偿问我要源代码:QQ:508181017 工作了将近三年时间了,一直没正儿八经的研究系统自带的相冊和拍照,这回来个高仿微信 ...

  8. Android 高仿微信即时聊天 百度云为基础的推

    转载请注明出处:http://blog.csdn.net/lmj623565791/article/details/38799363 ,本文出自:[张鸿洋的博客] 一直在仿微信界面,今天最终有幸利用百 ...

  9. Android 高仿微信支付键盘

    现在很多app的支付.输入密码功能,都已经开始使用自定义数字键盘,不仅更加方便.其效果着实精致. 下面带着大家学习下,如何高仿微信的数字键盘,可以拿来直接用在自身的项目中. 先看下效果图: 1. 自定 ...

随机推荐

  1. Java基础知识强化45:StringBuffer类之字符串反转的案例

    1. 案例演示: package cn.itcast_07; import java.util.Scanner; /* * 把字符串反转 */ public class StringBufferTes ...

  2. USB HID Report Descriptor 报告描述符详解

    Report descriptors are composed of pieces of information. Each piece of information is called an Ite ...

  3. AnkhSVN 中文版 支持VS2015

    简介:AnkhSVN是一款在VS中管理Subversion的插件,您可以在VS中轻松的提交.更新.添加文件,而不用在命令行或资源管理器中提交,而且该插件属于开源项目. 这个版本是简体中文的重新编译版本 ...

  4. (转)url重写

    使用URLRewriter.dll后,根本不需要使用任何代码,我之前做的项目就是用的做URL重写的,其实不是进化,其实表面上看是.html扩展名而已,当然你还可以用其他的任意扩展名下面是你的配置 &l ...

  5. 服务器上开启远程sqlserver小细节

    之前按网络上过程配置完成后,连接都很正常.今天看的时候,突然就连接不上了.弄了半天,终于知道问题在哪里了.

  6. iOS_SN_UITableView的优化

    1.提前计算并缓存好高度(布局),因为heightForRowAtIndexPath:是调用最频繁的方法. 2.异步绘制,遇到复杂界面,遇到性能瓶颈时,可能就是突破口. 3.滑动时按需加载,这个在大量 ...

  7. web前端工程师学习之路开启(前言)

    web前端工程师需要掌握的所有技能 图解1: 图解2:

  8. 02.Lua的数据类型

    简单认识Lua 百度了一下(偷哈懒就不自己写了) Lua 是一个小巧的脚本语言.是巴西里约热内卢天主教大学(Pontifical Catholic University of Rio de Janei ...

  9. 关于ajax直接提交表单jQuery .validator验证不起作用问题

    之前用$.ajax(function(){});直接提交表单,而表单验证不通过也能提交. $(document).ready(function(){ $.ajax({       url:" ...

  10. Visual Studio的广告剧

    一个热衷于code的developer,一个热衷于developer的girl,他们将发生怎样的故事? 第一集:<想做你的Code> 第二集:<让爱延长> 第三集:<幸福 ...