介绍几个好用的android自定义控件
首先看效果图,


看下这两个界面,第一个中用到了一个自定义的FlowRadioGroup,支持复合子控件,自定义布局;
第二个界面中看到了输入的数字 自动4位分割了吧;也用到了自定义的DivisionEditText控件。
下面直接看源码FlowRadioGroup了;

1 /*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package com.newgame.sdk.view;
18
19 import java.util.ArrayList;
20
21 import android.content.Context;
22 import android.content.res.TypedArray;
23 import android.util.AttributeSet;
24 import android.view.View;
25 import android.view.ViewGroup;
26 import android.widget.CompoundButton;
27 import android.widget.LinearLayout;
28 import android.widget.RadioButton;
29
30 /** 可以放多种布局控件,能找到radiobutton */
31 public class FlowRadioGroup extends LinearLayout {
32 // holds the checked id; the selection is empty by default
33 private int mCheckedId = -1;
34 // tracks children radio buttons checked state
35 private CompoundButton.OnCheckedChangeListener mChildOnCheckedChangeListener;
36 // when true, mOnCheckedChangeListener discards events
37 private boolean mProtectFromCheckedChange = false;
38 private OnCheckedChangeListener mOnCheckedChangeListener;
39 private PassThroughHierarchyChangeListener mPassThroughListener;
40
41 // 存放当前的radioButton
42 private ArrayList<RadioButton> radioButtons;
43
44 public FlowRadioGroup(Context context) {
45 super(context);
46 setOrientation(VERTICAL);
47 init();
48 }
49
50 public FlowRadioGroup(Context context, AttributeSet attrs) {
51 super(context, attrs);
52 init();
53 }
54
55 private void init() {
56 mChildOnCheckedChangeListener = new CheckedStateTracker();
57 mPassThroughListener = new PassThroughHierarchyChangeListener();
58 super.setOnHierarchyChangeListener(mPassThroughListener);
59 radioButtons = new ArrayList<RadioButton>();
60 }
61
62 @Override
63 public void setOnHierarchyChangeListener(OnHierarchyChangeListener listener) {
64 // the user listener is delegated to our pass-through listener
65 mPassThroughListener.mOnHierarchyChangeListener = listener;
66 }
67
68 @Override
69 protected void onFinishInflate() {
70 super.onFinishInflate();
71
72 // checks the appropriate radio button as requested in the XML file
73 if (mCheckedId != -1) {
74 mProtectFromCheckedChange = true;
75 setCheckedStateForView(mCheckedId, true);
76 mProtectFromCheckedChange = false;
77 setCheckedId(mCheckedId);
78 }
79 }
80
81 @Override
82 public void addView(View child, int index, ViewGroup.LayoutParams params) {
83 if (child instanceof RadioButton) {
84 final RadioButton button = (RadioButton) child;
85 radioButtons.add(button);
86
87 if (button.isChecked()) {
88 mProtectFromCheckedChange = true;
89 if (mCheckedId != -1) {
90 setCheckedStateForView(mCheckedId, false);
91 }
92 mProtectFromCheckedChange = false;
93 setCheckedId(button.getId());
94 }
95 } else if (child instanceof ViewGroup) {// 如果是复合控件
96 // 遍历复合控件
97 ViewGroup vg = ((ViewGroup) child);
98 setCheckedView(vg);
99 }
100
101 super.addView(child, index, params);
102 }
103
104 /** 查找复合控件并设置radiobutton */
105 private void setCheckedView(ViewGroup vg) {
106 int len = vg.getChildCount();
107 for (int i = 0; i < len; i++) {
108 if (vg.getChildAt(i) instanceof RadioButton) {// 如果找到了,就设置check状态
109 final RadioButton button = (RadioButton) vg.getChildAt(i);
110 // 添加到容器
111 radioButtons.add(button);
112 if (button.isChecked()) {
113 mProtectFromCheckedChange = true;
114 if (mCheckedId != -1) {
115 setCheckedStateForView(mCheckedId, false);
116 }
117 mProtectFromCheckedChange = false;
118 setCheckedId(button.getId());
119 }
120 } else if (vg.getChildAt(i) instanceof ViewGroup) {// 迭代查找并设置
121 ViewGroup childVg = (ViewGroup) vg.getChildAt(i);
122 setCheckedView(childVg);
123 }
124 }
125 }
126
127 /** 查找复合控件并设置id */
128 private void setCheckedId(ViewGroup vg) {
129 int len = vg.getChildCount();
130 for (int i = 0; i < len; i++) {
131 if (vg.getChildAt(i) instanceof RadioButton) {// 如果找到了,就设置check状态
132 final RadioButton button = (RadioButton) vg.getChildAt(i);
133 int id = button.getId();
134 // generates an id if it's missing
135 if (id == View.NO_ID) {
136 id = button.hashCode();
137 button.setId(id);
138 }
139 button.setOnCheckedChangeListener(mChildOnCheckedChangeListener);
140 } else if (vg.getChildAt(i) instanceof ViewGroup) {// 迭代查找并设置
141 ViewGroup childVg = (ViewGroup) vg.getChildAt(i);
142 setCheckedId(childVg);
143 }
144 }
145 }
146
147 /** 查找radioButton控件 */
148 public RadioButton findRadioButton(ViewGroup group) {
149 RadioButton resBtn = null;
150 int len = group.getChildCount();
151 for (int i = 0; i < len; i++) {
152 if (group.getChildAt(i) instanceof RadioButton) {
153 resBtn = (RadioButton) group.getChildAt(i);
154 } else if (group.getChildAt(i) instanceof ViewGroup) {
155 resBtn = findRadioButton((ViewGroup) group.getChildAt(i));
156 findRadioButton((ViewGroup) group.getChildAt(i));
157 break;
158 }
159 }
160 return resBtn;
161 }
162
163 /** 返回当前radiobutton控件的count */
164 public int getRadioButtonCount() {
165 return radioButtons.size();
166 }
167
168 /** 返回当前index的radio */
169 public RadioButton getRadioButton(int index) {
170 return radioButtons.get(index);
171 }
172
173 /**
174 * <p>
175 * Sets the selection to the radio button whose identifier is passed in
176 * parameter. Using -1 as the selection identifier clears the selection;
177 * such an operation is equivalent to invoking {@link #clearCheck()}.
178 * </p>
179 *
180 * @param id
181 * the unique id of the radio button to select in this group
182 *
183 * @see #getCheckedRadioButtonId()
184 * @see #clearCheck()
185 */
186 public void check(int id) {
187 // don't even bother
188 if (id != -1 && (id == mCheckedId)) {
189 return;
190 }
191
192 if (mCheckedId != -1) {
193 setCheckedStateForView(mCheckedId, false);
194 }
195
196 if (id != -1) {
197 setCheckedStateForView(id, true);
198 }
199
200 setCheckedId(id);
201 }
202
203 private void setCheckedId(int id) {
204 mCheckedId = id;
205 if (mOnCheckedChangeListener != null) {
206 mOnCheckedChangeListener.onCheckedChanged(this, mCheckedId);
207 }
208 }
209
210 private void setCheckedStateForView(int viewId, boolean checked) {
211 View checkedView = findViewById(viewId);
212 if (checkedView != null && checkedView instanceof RadioButton) {
213 ((RadioButton) checkedView).setChecked(checked);
214 }
215 }
216
217 /**
218 * <p>
219 * Returns the identifier of the selected radio button in this group. Upon
220 * empty selection, the returned value is -1.
221 * </p>
222 *
223 * @return the unique id of the selected radio button in this group
224 *
225 * @see #check(int)
226 * @see #clearCheck()
227 */
228 public int getCheckedRadioButtonId() {
229 return mCheckedId;
230 }
231
232 /**
233 * <p>
234 * Clears the selection. When the selection is cleared, no radio button in
235 * this group is selected and {@link #getCheckedRadioButtonId()} returns
236 * null.
237 * </p>
238 *
239 * @see #check(int)
240 * @see #getCheckedRadioButtonId()
241 */
242 public void clearCheck() {
243 check(-1);
244 }
245
246 /**
247 * <p>
248 * Register a callback to be invoked when the checked radio button changes
249 * in this group.
250 * </p>
251 *
252 * @param listener
253 * the callback to call on checked state change
254 */
255 public void setOnCheckedChangeListener(OnCheckedChangeListener listener) {
256 mOnCheckedChangeListener = listener;
257 }
258
259 /**
260 * {@inheritDoc}
261 */
262 @Override
263 public LayoutParams generateLayoutParams(AttributeSet attrs) {
264 return new FlowRadioGroup.LayoutParams(getContext(), attrs);
265 }
266
267 /**
268 * {@inheritDoc}
269 */
270 @Override
271 protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
272 return p instanceof FlowRadioGroup.LayoutParams;
273 }
274
275 @Override
276 protected LinearLayout.LayoutParams generateDefaultLayoutParams() {
277 return new LayoutParams(LayoutParams.WRAP_CONTENT,
278 LayoutParams.WRAP_CONTENT);
279 }
280
281 /**
282 * <p>
283 * This set of layout parameters defaults the width and the height of the
284 * children to {@link #WRAP_CONTENT} when they are not specified in the XML
285 * file. Otherwise, this class ussed the value read from the XML file.
286 * </p>
287 *
288 * <p>
289 * See {@link android.R.styleable#LinearLayout_Layout LinearLayout
290 * Attributes} for a list of all child view attributes that this class
291 * supports.
292 * </p>
293 *
294 */
295 public static class LayoutParams extends LinearLayout.LayoutParams {
296 /**
297 * {@inheritDoc}
298 */
299 public LayoutParams(Context c, AttributeSet attrs) {
300 super(c, attrs);
301 }
302
303 /**
304 * {@inheritDoc}
305 */
306 public LayoutParams(int w, int h) {
307 super(w, h);
308 }
309
310 /**
311 * {@inheritDoc}
312 */
313 public LayoutParams(int w, int h, float initWeight) {
314 super(w, h, initWeight);
315 }
316
317 /**
318 * {@inheritDoc}
319 */
320 public LayoutParams(ViewGroup.LayoutParams p) {
321 super(p);
322 }
323
324 /**
325 * {@inheritDoc}
326 */
327 public LayoutParams(MarginLayoutParams source) {
328 super(source);
329 }
330
331 /**
332 * <p>
333 * Fixes the child's width to
334 * {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT} and the
335 * child's height to
336 * {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT} when not
337 * specified in the XML file.
338 * </p>
339 *
340 * @param a
341 * the styled attributes set
342 * @param widthAttr
343 * the width attribute to fetch
344 * @param heightAttr
345 * the height attribute to fetch
346 */
347 @Override
348 protected void setBaseAttributes(TypedArray a, int widthAttr,
349 int heightAttr) {
350
351 if (a.hasValue(widthAttr)) {
352 width = a.getLayoutDimension(widthAttr, "layout_width");
353 } else {
354 width = WRAP_CONTENT;
355 }
356
357 if (a.hasValue(heightAttr)) {
358 height = a.getLayoutDimension(heightAttr, "layout_height");
359 } else {
360 height = WRAP_CONTENT;
361 }
362 }
363 }
364
365 /**
366 * <p>
367 * Interface definition for a callback to be invoked when the checked radio
368 * button changed in this group.
369 * </p>
370 */
371 public interface OnCheckedChangeListener {
372 /**
373 * <p>
374 * Called when the checked radio button has changed. When the selection
375 * is cleared, checkedId is -1.
376 * </p>
377 *
378 * @param group
379 * the group in which the checked radio button has changed
380 * @param checkedId
381 * the unique identifier of the newly checked radio button
382 */
383 public void onCheckedChanged(FlowRadioGroup group, int checkedId);
384 }
385
386 private class CheckedStateTracker implements
387 CompoundButton.OnCheckedChangeListener {
388 public void onCheckedChanged(CompoundButton buttonView,
389 boolean isChecked) {
390 // prevents from infinite recursion
391 if (mProtectFromCheckedChange) {
392 return;
393 }
394
395 mProtectFromCheckedChange = true;
396 if (mCheckedId != -1) {
397 setCheckedStateForView(mCheckedId, false);
398 }
399 mProtectFromCheckedChange = false;
400
401 int id = buttonView.getId();
402 setCheckedId(id);
403 }
404 }
405
406 /**
407 * <p>
408 * A pass-through listener acts upon the events and dispatches them to
409 * another listener. This allows the table layout to set its own internal
410 * hierarchy change listener without preventing the user to setup his.
411 * </p>
412 */
413 private class PassThroughHierarchyChangeListener implements
414 ViewGroup.OnHierarchyChangeListener {
415 private ViewGroup.OnHierarchyChangeListener mOnHierarchyChangeListener;
416
417 public void onChildViewAdded(View parent, View child) {
418 if (parent == FlowRadioGroup.this && child instanceof RadioButton) {
419 int id = child.getId();
420 // generates an id if it's missing
421 if (id == View.NO_ID) {
422 id = child.hashCode();
423 child.setId(id);
424 }
425 ((RadioButton) child)
426 .setOnCheckedChangeListener(mChildOnCheckedChangeListener);
427 } else if (parent == FlowRadioGroup.this
428 && child instanceof ViewGroup) {// 如果是复合控件
429 // 查找并设置id
430 setCheckedId((ViewGroup) child);
431 }
432
433 if (mOnHierarchyChangeListener != null) {
434 mOnHierarchyChangeListener.onChildViewAdded(parent, child);
435 }
436 }
437
438 public void onChildViewRemoved(View parent, View child) {
439 if (parent == FlowRadioGroup.this && child instanceof RadioButton) {
440 ((RadioButton) child).setOnCheckedChangeListener(null);
441 } else if (parent == FlowRadioGroup.this
442 && child instanceof ViewGroup) {
443 findRadioButton((ViewGroup) child).setOnCheckedChangeListener(
444 null);
445 }
446 if (mOnHierarchyChangeListener != null) {
447 mOnHierarchyChangeListener.onChildViewRemoved(parent, child);
448 }
449 }
450 }
451 }

简单讲解下我的实现:
1)在addview方法中,加上判断,当前子控件是否为viewgroup类型

@Override
public void addView(View child, int index, ViewGroup.LayoutParams params) {
if (child instanceof RadioButton) {
final RadioButton button = (RadioButton) child;
radioButtons.add(button);//将找到的控件添加到集合中
if (button.isChecked()) {
mProtectFromCheckedChange = true;
if (mCheckedId != -1) {
setCheckedStateForView(mCheckedId, false);
}
mProtectFromCheckedChange = false;
setCheckedId(button.getId());
}
} else if (child instanceof ViewGroup) {// 如果是复合控件
// 遍历复合控件
ViewGroup vg = ((ViewGroup) child);
setCheckedView(vg);
}
super.addView(child, index, params);
}
/** 查找复合控件并设置radiobutton */
private void setCheckedView(ViewGroup vg) {
int len = vg.getChildCount();
for (int i = 0; i < len; i++) {
if (vg.getChildAt(i) instanceof RadioButton) {// 如果找到了,就设置check状态
final RadioButton button = (RadioButton) vg.getChildAt(i);
// 添加到容器
radioButtons.add(button);
if (button.isChecked()) {
mProtectFromCheckedChange = true;
if (mCheckedId != -1) {
setCheckedStateForView(mCheckedId, false);
}
mProtectFromCheckedChange = false;
setCheckedId(button.getId());
}
} else if (vg.getChildAt(i) instanceof ViewGroup) {// 迭代查找并设置
ViewGroup childVg = (ViewGroup) vg.getChildAt(i);
setCheckedView(childVg);
}
}
}

2)定义一个数组存放当前所有查到到的radiobutton;
3)在onChildViewAdded方法中,判断新添加的子控件是否为viewgroup类型
|
1
2
3
4
5
|
else if (parentthis &&instanceof ViewGroup)// // setCheckedId((ViewGroup) } |

/** 查找复合控件并设置id */
private void setCheckedId(ViewGroup vg) {
int len = vg.getChildCount();
for (int i = 0; i < len; i++) {
if (vg.getChildAt(i) instanceof RadioButton) {// 如果找到了,就设置check状态
final RadioButton button = (RadioButton) vg.getChildAt(i);
int id = button.getId();
// generates an id if it's missing
if (id == View.NO_ID) {
id = button.hashCode();
button.setId(id);
}
button.setOnCheckedChangeListener(mChildOnCheckedChangeListener);
} else if (vg.getChildAt(i) instanceof ViewGroup) {// 迭代查找并设置
ViewGroup childVg = (ViewGroup) vg.getChildAt(i);
setCheckedId(childVg);
}
}
}

下面是DivisionEditText的源码;

1 package com.newgame.sdk.view;
2
3 import android.content.Context;
4 import android.text.Editable;
5 import android.text.TextWatcher;
6 import android.util.AttributeSet;
7 import android.view.View;
8 import android.widget.EditText;
9
10 /**
11 * 分割输入框
12 *
13 * @author Administrator
14 *
15 */
16 public class DivisionEditText extends EditText {
17
18 /* 每组的长度 */
19 private Integer eachLength = 4;
20 /* 分隔符 */
21 private String delimiter = " ";
22
23 private String text = "";
24
25 public DivisionEditText(Context context) {
26 super(context);
27 init();
28 }
29
30 public DivisionEditText(Context context, AttributeSet attrs) {
31 super(context, attrs);
32 init();
33
34 }
35
36 public DivisionEditText(Context context, AttributeSet attrs, int defStyle) {
37 super(context, attrs, defStyle);
38 init();
39 }
40
41 /**
42 * 初始化
43 */
44 public void init() {
45
46 // 内容变化监听
47 this.addTextChangedListener(new DivisionTextWatcher());
48 // 获取焦点监听
49 this.setOnFocusChangeListener(new DivisionFocusChangeListener());
50 }
51
52 /**
53 * 文本监听
54 *
55 * @author Administrator
56 *
57 */
58 private class DivisionTextWatcher implements TextWatcher {
59
60 @Override
61 public void afterTextChanged(Editable s) {
62 }
63
64 @Override
65 public void beforeTextChanged(CharSequence s, int start, int count,
66 int after) {
67 }
68
69 @Override
70 public void onTextChanged(CharSequence s, int start, int before,
71 int count) {
72 // 统计个数
73 int len = s.length();
74 if (len < eachLength)// 长度小于要求的数
75 return;
76 if (count > 1) {
77 return;
78 }
79 // 如果包含空格,就清除
80 char[] chars = s.toString().replace(" ", "").toCharArray();
81 len = chars.length;
82 // 每4个分组,加上空格组合成新的字符串
83 StringBuffer sb = new StringBuffer();
84 for (int i = 0; i < len; i++) {
85 if (i % eachLength == 0 && i != 0)// 每次遍历到4的倍数,就添加一个空格
86 {
87 sb.append(" ");
88 sb.append(chars[i]);// 添加字符
89 } else {
90 sb.append(chars[i]);// 添加字符
91 }
92 }
93 // 设置新的字符到文本
94 // System.out.println("*************" + sb.toString());
95 text = sb.toString();
96 setText(text);
97 setSelection(text.length());
98 }
99 }
100
101 /**
102 * 获取焦点监听
103 *
104 * @author Administrator
105 *
106 */
107 private class DivisionFocusChangeListener implements OnFocusChangeListener {
108
109 @Override
110 public void onFocusChange(View v, boolean hasFocus) {
111 if (hasFocus) {
112 // 设置焦点
113 setSelection(getText().toString().length());
114 }
115 }
116 }
117
118 /** 得到每组个数 */
119 public Integer getEachLength() {
120 return eachLength;
121 }
122
123 /** 设置每组个数 */
124 public void setEachLength(Integer eachLength) {
125 this.eachLength = eachLength;
126 }
127
128 /** 得到间隔符 */
129 public String getDelimiter() {
130 return delimiter;
131 }
132
133 /** 设置间隔符 */
134 public void setDelimiter(String delimiter) {
135 this.delimiter = delimiter;
136 }
137
138 }

上面代码实现逻辑:在TextWatcher的onTextChanged方法中判断当前输入的字符,然后没4位添加一个空格,组成新的字符

@Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
// 统计个数
int len = s.length();
if (len < eachLength)// 长度小于要求的数
return;
if (count > 1) {// 设置新字符串的时候,直接返回
return;
}
// 如果包含空格,就清除
char[] chars = s.toString().replace(" ", "").toCharArray();
len = chars.length;
// 每4个分组,加上空格组合成新的字符串
StringBuffer sb = new StringBuffer();
for (int i = 0; i < len; i++) {
if (i % eachLength == 0 && i != 0)// 每次遍历到4的倍数,就添加一个空格
{
sb.append(" ");
sb.append(chars[i]);// 添加字符
} else {
sb.append(chars[i]);// 添加字符
}
}
// 设置新的字符到文本
// System.out.println("*************" + sb.toString());
text = sb.toString();
setText(text);
setSelection(text.length());
}

还有其他两个自定义控件也在项目中,这里界面没体现出来,我已经放在项目中了;
欢迎大家找出代码中的存在bug!!!!
最后附上代码下载地址:http://www.eoeandroid.com/forum.php?mod=attachment&aid=MTIwMDM1fDM5NTYzZjQ3fDEzOTY0Mjc4NDF8NzU4MzI1fDMyODQyNw%3D%3D
介绍几个好用的android自定义控件的更多相关文章
- Android自定义控件之自定义ViewGroup实现标签云
前言: 前面几篇讲了自定义控件绘制原理Android自定义控件之基本原理(一),自定义属性Android自定义控件之自定义属性(二),自定义组合控件Android自定义控件之自定义组合控件(三),常言 ...
- Android自定义控件之自定义组合控件
前言: 前两篇介绍了自定义控件的基础原理Android自定义控件之基本原理(一).自定义属性Android自定义控件之自定义属性(二).今天重点介绍一下如何通过自定义组合控件来提高布局的复用,降低开发 ...
- Android自定义控件之自定义属性
前言: 上篇介绍了自定义控件的基本要求以及绘制的基本原理,本篇文章主要介绍如何给自定义控件自定义一些属性.本篇文章将继续以上篇文章自定义圆形百分比为例进行讲解.有关原理知识请参考Android自定义控 ...
- Android自定义控件之基本原理
前言: 在日常的Android开发中会经常和控件打交道,有时Android提供的控件未必能满足业务的需求,这个时候就需要我们实现自定义一些控件,今天先大致了解一下自定义控件的要求和实现的基本原理. 自 ...
- Android自定义控件1
概述 Android已经为我们提供了大量的View供我们使用,但是可能有时候这些组件不能满足我们的需求,这时候就需要自定义控件了.自定义控件对于初学者总是感觉是一种复杂的技术.因为里面涉及到的知识点会 ...
- 一起来学习Android自定义控件1
概述 Android已经为我们提供了大量的View供我们使用,但是可能有时候这些组件不能满足我们的需求,这时候就需要自定义控件了.自定义控件对于初学者总是感觉是一种复杂的技术.因为里面涉及到的知识点会 ...
- [Xamarin.Android] 自定义控件
[Xamarin.Android] 自定义控件 前言 软件项目开发的过程中,免不了遇到一些无法使用内建控件就能满足的客户需求,例如:时速表.折线图...等等.这时开发人员可以透过自定义控件的方式,为项 ...
- android自定义控件实现TextView按下后字体颜色改变
今天跟大家分享一下Android自定义控件入门,先介绍一个简单的效果TextView,按下改变字体颜色,后期慢慢扩展更强大的功能 直接看图片 第一张是按下后截的图,功能很简单, ...
- Android自定义控件:进度条的四种实现方式(Progress Wheel的解析)
最近一直在学习自定义控件,搜了许多大牛们Blog里分享的小教程,也上GitHub找了一些类似的控件进行学习.发现读起来都不太好懂,就想写这么一篇东西作为学习笔记吧. 一.控件介绍: 进度条在App中非 ...
随机推荐
- Docker 自定义网桥
除了默认的 docker0 网桥,用户也可以指定网桥来连接各个容器. 在启动 Docker 服务的时候,使用 -b BRIDGE或--bridge=BRIDGE 来指定使用的网桥. 如果服务已经运行, ...
- NDK编程的一个坑—Arm平台下的类型转换
最近在做DNN定点化相关的工作,DNN定点化就是把float表示的模型压缩成char表示,虽然会损失精度,但是由于DNN训练的模型值比较接近且范围较小,实际上带来的性能损失非常小.DNN定点化的好处是 ...
- hiredis的各种windows版本
hiredis的各种windows版本(金庆的专栏 2016.12)hiredis 是内存数据库 redis 的客户端C库, 不支持Windows.hiredis的Windows移植版本有许多:des ...
- 安卓7.1 新特性Shortcut
介绍 Shortcut 是谷歌在API25提出来的 类似苹果3D touch 但是没有压力感应.在安卓中完全就是长按. 来看下效果吧: 是不是很赞? 那么请随本文一起学习吧 更新 新建项目 在你项目下 ...
- SpringBatch前言
批处理应用程序就是对程序进行批量处理. 特点:批量应用程序处理大量数据而无需人类干预. 用途:可以选择使用批处理程序来计算每月的财务报表.计算统计和索引文件的数据等等. 应用:当银行系统中有很多业务都 ...
- AsyncTask函数化的封装,AsyncTask函数式的调用
AsyncTask在本专栏已经做过详细的解析,但是AsyncTask函数式的调用这个概念对大多数人来说比较陌生.其实本质就是自己封装AsyncTask,让暴露的方法,看不到一点AsyncTask的身影 ...
- Dynamics CRM2016 Web API之删除
相比之前的增改查,删除就显得简单的多了. 这里的request的type为delete,删除成功的status为204,404则是要删除的记录不存在 var id = 'BAD90A95-7FEA-E ...
- FORM调用FORM(标准调客户化&客户化调标准)并执行查询的实现研究
一.先来个比较简单的,标准FORM调用客户话FORM并执行查询 1.修改CUSTOM.PLL,使用 fnd_function.execute实现打开和传递参数 参考例子如下 PROCEDURE eve ...
- 带你深入理解STL之Vector容器
C++内置了数组的类型,在使用数组的时候,必须指定数组的长度,一旦配置了就不能改变了,通常我们的做法是:尽量配置一个大的空间,以免不够用,这样做的缺点是比较浪费空间,预估空间不当会引起很多不便. ST ...
- 控制成本,控制成本知识点,挣值和实际成本、EAC,ETC.TCPI解析表