立即春节,写个应景的控件

       

思路分析

1.红包沿着不同的轨迹由上往下运动
2.当手指捕获到一个红包,红包停止原先的运动,能够随着手指的滑动做跟手操作
3.当手指动作停止后,红包放大
4.通过滑动刮开红包,看到期待已久的money 

大体知识点概况

1.属性动画,实现红包依照贝塞尔曲线运动和放大效果
2.实现一个可移动的view。能够參考我的还有一篇博客http://blog.csdn.net/xuan_xiaofeng/article/details/50463595
3.图片的结合模式,主要是实现刮开红包
4.自己定义控件的相关知识 

实战

1.先来做个红包。

继承view,做点初始化的工作

private void init() {
mPath = new Path();
mRandom = new Random(); initPaint();
initMoneyPaint(); mText = moneys[mRandom.nextInt(moneys.length)]; //获取字体的宽高
moneyPaint.getTextBounds(mText, 0, mText.length(), mTextBound);
} private void initPaint() {
mPaint = new Paint();
mPaint.setColor(Color.parseColor("#c0c0c0"));
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeCap(Paint.Cap.ROUND);
/**
* 设置接合处的形态
*/
mPaint.setStrokeJoin(Paint.Join.ROUND);
/**
* 抗抖动
*/
mPaint.setDither(true);
mPaint.setAntiAlias(true);
mPaint.setStrokeWidth(PAINT_WIDTH);
} /**
* money画笔
*/
private void initMoneyPaint() {
moneyPaint = new Paint();
moneyPaint.setColor(Color.RED);
moneyPaint.setAntiAlias(true);
moneyPaint.setTextSize(30);
mTextBound = new Rect();
moneyPaint.getTextBounds(moneys[0], 0, moneys[0].length(), mTextBound);
}

2.创建一个画布,就是一个绘制一个红包的图片。根据手指在控件上的滑动路径,除去图片的结合部分


mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap); Bitmap bitmap = Bitmap.createBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.red_packet)); mCanvas.drawBitmap(bitmap, null, new RectF(0, 0, width, height), null); //设置图片的结合方式
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
mCanvas.drawPath(mPath, mPaint);
canvas.drawBitmap(mBitmap, 0, 0, null);

3.重写onTouchEvent方法记录手指的擦除路径以及实现跟手操作

public boolean onTouchEvent(MotionEvent event) {
x = (int) event.getX();
y = (int) event.getY(); switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//路径的初始化位置
mPath.moveTo(x, y);
break;
case MotionEvent.ACTION_MOVE:
if (movable) {
// 跟手滑效果
setX(x + getLeft() + getTranslationX() - getWidth() / 2);
setY(y + getTop() + getTranslationY() - getHeight() / 2);
} else if (Math.abs(x - mLastX) > DEFAULT_PATH_INSTANCE || Math.abs(y - mLastY) > DEFAULT_PATH_INSTANCE) {
// 记录手指擦除路径
mPath.lineTo(x, y);
invalidate();
}
case MotionEvent.ACTION_UP:
MyAsyncTask task = new MyAsyncTask();
task.execute();
break;
} //记录上次位置
mLastX = x;
mLastY = y;
return true;
}

4.附上完整的代码

public class RedPacketView extends ImageView {
private Paint mPaint, moneyPaint;
private Path mPath;
private Canvas mCanvas;
private Bitmap mBitmap;
private int x, y, mLastX, mLastY;
public boolean movable = true;
public boolean isTouch = false;
private String[] moneys = new String[]{"¥5", "¥10", "¥20", "¥50"};
private Rect mTextBound;
private String mText;
private Random mRandom;
private boolean isComplete = false; /**
* 笔触的宽度
*/
private static final float PAINT_WIDTH = 20;
/**
* 默认绘制的最小距离
*/
private static final float DEFAULT_PATH_INSTANCE = 5; public RedPacketView(Context context) {
super(context);
init();
} public RedPacketView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
} public RedPacketView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
} private void init() {
mPath = new Path();
mRandom = new Random(); initPaint();
initMoneyPaint(); //随机产生一个面值
mText = moneys[mRandom.nextInt(moneys.length)]; //获取字体的宽高
moneyPaint.getTextBounds(mText, 0, mText.length(), mTextBound);
} private void initPaint() {
mPaint = new Paint();
mPaint.setColor(Color.parseColor("#c0c0c0"));
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeCap(Paint.Cap.ROUND);
/**
* 设置接合处的形态
*/
mPaint.setStrokeJoin(Paint.Join.ROUND);
/**
* 抗抖动
*/
mPaint.setDither(true);
mPaint.setAntiAlias(true);
mPaint.setStrokeWidth(PAINT_WIDTH);
} /**
* money画笔
*/
private void initMoneyPaint() {
moneyPaint = new Paint();
moneyPaint.setColor(Color.RED);
moneyPaint.setAntiAlias(true);
moneyPaint.setTextSize(30);
mTextBound = new Rect();
} @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec); int width = getMeasuredWidth();
int height = getMeasuredHeight(); try {
mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap); Bitmap bitmap = Bitmap.createBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.red_packet)); mCanvas.drawBitmap(bitmap, null, new RectF(0, 0, width, height), null); } catch (Exception e) {
e.printStackTrace();
}
} @Override
protected void onDraw(Canvas canvas) {
try {
canvas.drawText(mText, getWidth() / 2 - mTextBound.width() / 2, getHeight() / 2 + mTextBound.height() / 2, moneyPaint); if (isComplete) return; //设置图片的结合方式
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
mCanvas.drawPath(mPath, mPaint); canvas.drawBitmap(mBitmap, 0, 0, null);
} catch (Exception e) {
e.printStackTrace();
}
} @Override
public boolean onTouchEvent(MotionEvent event) {
x = (int) event.getX();
y = (int) event.getY(); switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//路径的初始化位置
mPath.moveTo(x, y);
break;
case MotionEvent.ACTION_MOVE:
if (movable) {
// 跟手滑效果
setX(x + getLeft() + getTranslationX() - getWidth() / 2);
setY(y + getTop() + getTranslationY() - getHeight() / 2);
} else if (Math.abs(x - mLastX) > DEFAULT_PATH_INSTANCE || Math.abs(y - mLastY) > DEFAULT_PATH_INSTANCE) {
// 记录手指擦除路径
mPath.lineTo(x, y);
invalidate();
}
case MotionEvent.ACTION_UP:
MyAsyncTask task = new MyAsyncTask();
task.execute();
break;
} //记录上次位置
mLastX = x;
mLastY = y;
return true;
} /**
* 查看眼下的红包的擦除比例,实现全然擦除
*/
class MyAsyncTask extends AsyncTask{
@Override
protected Object doInBackground(Object[] params) {
clearOverPercent();
return null;
} private void clearOverPercent()
{
int[] mPixels; int w = getWidth();
int h = getHeight(); float wipeArea = 0;
float totalArea = w * h; Bitmap bitmap = Bitmap.createBitmap(mBitmap); mPixels = new int[w * h]; //拿到全部像素信息
bitmap.getPixels(mPixels, 0, w, 0, 0, w, h); //获取擦除部分的面积
int index = 0;
for (int i = 0; i < w; i++) {
for (int j = 0; j < h; j++) {
if (mPixels[index] == 0) {
wipeArea++;
}
index++;
}
} int percent = (int) (wipeArea / totalArea * 100);
if (percent > 70) {
isComplete = true;
postInvalidate();
}
}
};
}

5.实现发红包的父容器LaunchRedPacketLayout。

重点说下贝塞尔曲线动画部分的实现。实现的过程用到四个点。各自是起点,随机点1,随机点2,终点。

起点为控件的底部中点,终点为控件顶部的随意点即(x=n, y=0)。

随机点为控件内部随意点。当然为了更好的效果。点位分布均匀为佳。



6.有了四个点后,依据贝塞尔曲线的公式新建一个估值器,以便于计算红包当前的位置
/**
* 估值器
*/
static class BSEEvaluator implements TypeEvaluator<PointF> {
private PointF pointF1;
private PointF pointF2; public BSEEvaluator(PointF pointF1, PointF pointF2) {
this.pointF1 = pointF1;
this.pointF2 = pointF2;
} @Override
public PointF evaluate(float fraction, PointF startValue, PointF endValue) {
PointF pointF = new PointF(); float lFraction = 1 - fraction; pointF.x = (float) (startValue.x * Math.pow(lFraction, 3) +
3 * pointF1.x * fraction * Math.pow(lFraction, 2) +
3 * pointF2.x * Math.pow(lFraction, 2) * fraction +
endValue.x * Math.pow(fraction, 3));
pointF.y = (float) (startValue.y * Math.pow(lFraction, 3) +
3 * pointF1.y * fraction * Math.pow(lFraction, 2) +
3 * pointF2.y * Math.pow(fraction, 2) * lFraction +
endValue.y * Math.pow(fraction, 3)); return pointF;
}
}

7.设置属性动画的监听器,不断将新的位置设置给红包,让红包动起来

private ValueAnimator getBSEValueAnimator(View target) {
//贝赛尔估值器
BSEEvaluator evaluator = new BSEEvaluator(getPoint(), getPoint());
ValueAnimator animator = ValueAnimator.ofObject(evaluator, new PointF((mWidth - dWidth) / 2, mHeight - dHeight), new PointF(random.nextInt(mWidth), 0));
animator.addUpdateListener(new BSEListenr(target));
animator.setTarget(target);
animator.setDuration(3000);
return animator;
} private class BSEListenr implements ValueAnimator.AnimatorUpdateListener { private View target; public BSEListenr(View target) {
this.target = target;
} @Override
public void onAnimationUpdate(ValueAnimator animation) {
//这里获取到贝塞尔曲线计算出来的的xy值
PointF pointF = (PointF) animation.getAnimatedValue();
target.setX(pointF.x);
target.setY(pointF.y);
}
}

8.提供发射红包的入口方法

/**
* 发射多个红包
*
* @param numb
*/
public void launch(int numb) throws Exception {
for (int i = 0; i < numb; i++)
launch();
} /**
* 发射红包
*/
public void launch() throws Exception {
final RedPacketView imageView = new RedPacketView(getContext());
imageView.setImageDrawable(drawable); //设置位置
LayoutParams layoutParams = new LayoutParams(dWidth, dHeight);
layoutParams.addRule(ALIGN_PARENT_BOTTOM, TRUE);
layoutParams.addRule(CENTER_HORIZONTAL, TRUE);
imageView.setLayoutParams(layoutParams); final Animator set = addAnimatior(imageView); imageView.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
x = (int) imageView.getX();
y = (int) imageView.getY(); if (!imageView.isTouch) {
imageView.isTouch = true;
set.end();
} if (MotionEvent.ACTION_UP == event.getAction()) {
if (imageView.movable) {
ObjectAnimator.ofFloat(imageView, View.ALPHA, 1f).start();
AnimatorSet setDown = new AnimatorSet();
setDown.playTogether(
ObjectAnimator.ofFloat(imageView, "scaleX", 0.8f, 1.5f),
ObjectAnimator.ofFloat(imageView, "scaleY", 0.8f, 1.5f)
);
setDown.start(); imageView.movable = false;
}
} return false;
}
}); addView(imageView);
set.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation); // 动画结束移除view
if (imageView.isTouch) {
imageView.setX(x);
imageView.setY(y);
} else {
removeView(imageView);
}
}
});
set.start();
}

9.附上完整代码

public class LaunchRedPacketLayout extends RelativeLayout {
private Drawable drawable;
private int dWidth;
private int dHeight;
private int mWidth;
private int mHeight;
int x, y; /**
* 插值器组
*/
private Interpolator[] interpolatorsArray; private Random random; public LaunchRedPacketLayout(Context context) {
super(context);
init();
} public LaunchRedPacketLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init();
} private void init() {
drawable = getResources().getDrawable(R.drawable.red_packet);
dWidth = drawable.getIntrinsicWidth();
dHeight = drawable.getIntrinsicHeight(); random = new Random(); interpolatorsArray = new Interpolator[4];
interpolatorsArray[0] = new LinearInterpolator();
interpolatorsArray[1] = new AccelerateInterpolator();
interpolatorsArray[2] = new DecelerateInterpolator();
interpolatorsArray[3] = new AccelerateDecelerateInterpolator(); post(new Runnable() {
@Override
public void run() {
mHeight = getMeasuredHeight();
mWidth = getMeasuredWidth(); int curWidth = dWidth;
dWidth = mWidth / 5;
dHeight = dHeight * dWidth / curWidth;
}
});
} /**
* 发射多个红包
*
* @param numb
*/
public void launch(int numb) throws Exception {
for (int i = 0; i < numb; i++)
launch();
} /**
* 发射红包
*/
public void launch() throws Exception {
final RedPacketView imageView = new RedPacketView(getContext());
imageView.setImageDrawable(drawable); //设置位置
LayoutParams layoutParams = new LayoutParams(dWidth, dHeight);
layoutParams.addRule(ALIGN_PARENT_BOTTOM, TRUE);
layoutParams.addRule(CENTER_HORIZONTAL, TRUE);
imageView.setLayoutParams(layoutParams); final Animator set = addAnimatior(imageView); imageView.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
x = (int) imageView.getX();
y = (int) imageView.getY(); if (!imageView.isTouch) {
imageView.isTouch = true;
set.end();
} if (MotionEvent.ACTION_UP == event.getAction()) {
if (imageView.movable) {
ObjectAnimator.ofFloat(imageView, View.ALPHA, 1f).start();
AnimatorSet setDown = new AnimatorSet();
setDown.playTogether(
ObjectAnimator.ofFloat(imageView, "scaleX", 0.8f, 1.5f),
ObjectAnimator.ofFloat(imageView, "scaleY", 0.8f, 1.5f)
);
setDown.start(); imageView.movable = false;
}
} return false;
}
}); addView(imageView);
set.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation); // 动画结束移除view
if (imageView.isTouch) {
imageView.setX(x);
imageView.setY(y);
} else {
removeView(imageView);
}
}
});
set.start();
} /**
* 设置动画
*
* @param target
*/
private Animator addAnimatior(View target) throws Exception {
AnimatorSet set = new AnimatorSet();
AnimatorSet enterSet = getEnterSet(target); ValueAnimator bezierValueAnimator = getBSEValueAnimator(target);
set.playSequentially(enterSet, bezierValueAnimator);
set.setInterpolator(interpolatorsArray[random.nextInt(4)]);
set.setTarget(target);
return set;
} private class BSEListenr implements ValueAnimator.AnimatorUpdateListener { private View target; public BSEListenr(View target) {
this.target = target;
} @Override
public void onAnimationUpdate(ValueAnimator animation) {
//这里获取到贝塞尔曲线计算出来的的x y值
PointF pointF = (PointF) animation.getAnimatedValue();
target.setX(pointF.x);
target.setY(pointF.y);
}
} /**
* 设置贝赛尔曲线动画
*
* @param target
* @return
*/
private ValueAnimator getBSEValueAnimator(View target) {
//贝赛尔估值器
BSEEvaluator evaluator = new BSEEvaluator(getPoint(), getPoint());
ValueAnimator animator = ValueAnimator.ofObject(evaluator, new PointF((mWidth - dWidth) / 2, mHeight - dHeight), new PointF(random.nextInt(mWidth), 0));
animator.addUpdateListener(new BSEListenr(target));
animator.setTarget(target);
animator.setDuration(3000);
return animator;
} private PointF getPoint() {
PointF pointF = new PointF();
pointF.x = random.nextInt(mWidth);
pointF.y = random.nextInt(mHeight - dHeight);
return pointF;
} /**
* 估值器
*/
static class BSEEvaluator implements TypeEvaluator<PointF> {
private PointF pointF1;
private PointF pointF2; public BSEEvaluator(PointF pointF1, PointF pointF2) {
this.pointF1 = pointF1;
this.pointF2 = pointF2;
} @Override
public PointF evaluate(float fraction, PointF startValue, PointF endValue) {
PointF pointF = new PointF(); float lFraction = 1 - fraction; pointF.x = (float) (startValue.x * Math.pow(lFraction, 3) +
3 * pointF1.x * fraction * Math.pow(lFraction, 2) +
3 * pointF2.x * Math.pow(lFraction, 2) * fraction +
endValue.x * Math.pow(fraction, 3));
pointF.y = (float) (startValue.y * Math.pow(lFraction, 3) +
3 * pointF1.y * fraction * Math.pow(lFraction, 2) +
3 * pointF2.y * Math.pow(fraction, 2) * lFraction +
endValue.y * Math.pow(fraction, 3)); return pointF;
}
} /**
* 入场动画
*
* @param target
* @return
*/
private AnimatorSet getEnterSet(View target) {
try {
AnimatorSet enterSet = new AnimatorSet(); enterSet.playTogether(
ObjectAnimator.ofFloat(target, View.ALPHA, 0, 1f),
ObjectAnimator.ofFloat(target, View.SCALE_X, 0.1f, 0.8f),
ObjectAnimator.ofFloat(target, View.SCALE_Y, 0.1f, 0.8f)
);
enterSet.setDuration(500);
enterSet.setInterpolator(new LinearInterpolator());
enterSet.setTarget(target); return enterSet;
} catch (Exception e) {
e.printStackTrace();
}
return null;
} }

10.试下

<?

xml version="1.0" encoding="utf-8"?

>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context="sample.MainActivity"
tools:showIn="@layout/activity_main"> <com.empty.launchredpacket.LaunchRedPacketLayout
android:id="@+id/launchRedPacket"
android:layout_width="match_parent"
android:background="#faecec"
android:layout_height="400dp"
/> <Button
android:id="@+id/launchBtn"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_margin="5dp"
android:background="@color/colorPrimary"
android:text="发射"
android:textColor="@android:color/white" /> <Button
android:id="@+id/reStart"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_margin="5dp"
android:background="@color/colorPrimary"
android:text="又一次開始"
android:textColor="@android:color/white" />
</LinearLayout>
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private LaunchRedPacketLayout launchRedPacketLayout;
private Button launchBtn, reStartBtn; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar); launchRedPacketLayout = (LaunchRedPacketLayout) findViewById(R.id.launchRedPacket);
launchBtn = (Button) findViewById(R.id.launchBtn);
reStartBtn = (Button) findViewById(R.id.reStart); launchBtn.setOnClickListener(this);
reStartBtn.setOnClickListener(this);
} @Override
public void onClick(View v) {
try {
switch (v.getId()) {
case R.id.reStart:
startActivity(new Intent(this, MainActivity.class));
finish();
overridePendingTransition(0, 0);
break;
case R.id.launchBtn:
launchRedPacketLayout.launch(3);
break;
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

总结

1.发射过多红包会引起页面卡顿,须要优化
2.代码结构还能够优化下
3.欢迎大家评论交流 

十分感谢 程序亦非猿,hongyang 大神的博客

源代码地址 https://github.com/wolow3/LaunchRedPacket

发红包android的更多相关文章

  1. PHP实现发红包程序

    我们先来分析下规律. 设定总金额为10元,有N个人随机领取: N=1 第一个 则红包金额=X元: N=2 第二个 为保证第二个红包可以正常发出,第一个红包金额=0.01至9.99之间的某个随机数. 第 ...

  2. PHP实现发红包程序(helloweba网站经典小案例)

    我们先来分析下规律. 设定总金额为10元,有N个人随机领取: N=1 第一个 则红包金额=X元: N=2 第二个 为保证第二个红包可以正常发出,第一个红包金额=0.01至9.99之间的某个随机数. 第 ...

  3. 使用PHP编写发红包程序

    使用PHP编写发红包程序 http://www.jb51.net/article/69815.htm 投稿:hebedich 字体:[增加 减小] 类型:转载 时间:2015-07-22   微信发红 ...

  4. js 发红包

    <!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content ...

  5. 微信小程序红包开发 小程序发红包 开发过程中遇到的坑 微信小程序红包接口的

    最近公司在开发一个小程序红包系统,客户抢到红包需要提现.也就是通过小程序来给用户发红包. 小程序如何来发红包呢?于是我想到两个方法. 之前公众号开发一直用了的.一个是红包接口,一个是企业支付接口.一开 ...

  6. 微信小程序发红包

    背景: 近期一个朋友公司要做活动,活动放在小程序上.小程序开发倒是不难,不过要使用小程序给微信用户发红包,这个就有点麻烦 确定模式: 小程序目前没有发红包接口,要实现的话,只能是模拟红包,即小程序上做 ...

  7. JAVA发红包案例

    模拟拼手气红包* 对于指定总金额以及红包个数,可以生成不同金额的红包,*,每个红包金额随机生成. * 分析这个题目:* 1.首先需要一个分发红包的方法.输入的参数是 总金额 以及 红包个数.* 按照这 ...

  8. Python_程序实现发红包

    发红包 200块钱  20个红包 将200块随机分成20份 基础版本: import random ret = random.sample(range(1, 200 * 100), 19) ret = ...

  9. 微信发红包 PHP 实现

    最近做生日营销,需要微信发红包,特此从网上找了一篇教程 首先你的有个服务号,并且开通了微信支付,我在这就不说怎么去申请和开通了,我是看了微信官方文档后,想看官方文档的朋友可以到下面这个链接 https ...

随机推荐

  1. javascript 备忘 细节 相关

    DOMContentLoaded事件触发时机,即dom tree完成但页面未必渲染完毕.   var a = [1,2,3,4]; var length = a.length; alert((leng ...

  2. spring cloud+dotnet core搭建微服务架构:Api授权认证(六)

    前言 这篇文章拖太久了,因为最近实在太忙了,加上这篇文章也非常长,所以花了不少时间,给大家说句抱歉.好,进入正题.目前的项目基本都是前后端分离了,前端分Web,Ios,Android...,后端也基本 ...

  3. [译]ASP.NET Core 2.0 区域

    问题 如何将一个规模庞大的ASP.NET Core 2.0应用程序进行逻辑分组? 答案 新建一个ASP.NET Core 2.0空项目,修改Startup类,增加Mvc服务和中间件: public v ...

  4. 浅谈postgresql的GIN索引(通用倒排索引)

    1.倒排索引原理 倒排索引来源于搜索引擎的技术,可以说是搜索引擎的基石.正是有了倒排索引技术,搜索引擎才能有效率的进行数据库查找.删除等操作.在详细说明倒排索引之前,我们说一下与之相关的正排索引并与之 ...

  5. 在为知笔记中使用Markdown和思维导图

    为知笔记Wiz是一款很好的网摘和笔记工具,作为为知的忠实用户,我在为知收费后第一时间就购买了两年的授权,毕竟这么多年积累的资料都在为知上,我也习惯了使用Wiz来做些工作相关的笔记.为知笔记自带Mark ...

  6. Java多线程由易到难

    线程可以驱动任务,因此你需要一种描述任务的方式,这可以由Runnable接口来提供.要想定义任务,只需实现Runnable接口并编写run方法,使得该任务可以执行你的命令. public class ...

  7. C# Ioc容器Unity,简单实用

    开头先吐槽一下博客园超级不好用,添加图片后就写不动字了,难道是bug 好进入正题,先来说下依赖注入,简单来说就是定义好接口,上层代码调用接口,具体实现通过配置文件方式去指定具体实现类. 首先我们需要通 ...

  8. [Intel Edison开发板] 06、Edison开发在linux中烧写、配置、搭建开发环境

    1.前言 linux上烧写.配置.搭建Edison环境,千万不要用默认的setup tool for ubuntu!!! (即使,你用的就是ubuntu) 因为,其默认的工具会从一个坏链接下载配置文件 ...

  9. EditText 限制输入整数和小数 的位数

    如题,本文主要说的就是  如何限制 EditText 中 可输入整数和小数 的位数 . 近期,由于公司业务需求中有价格输入功能,给出的要求说是,必须整数能输入几位,小数能输入几位...好嘛,产品一句话 ...

  10. 机器学习实验一SVM分类实验

    一.实验目的和内容 (一)实验目的 1.熟悉支持向量机SVM(Support Vector Machine)模型分类算法的使用. 2.用svm-train中提供的代码框架(填入SVM分类器代码)用tr ...