首先看效果图,

看下这两个界面,第一个中用到了一个自定义的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 (parent
== FlowRadioGroup.
this
                    &&
child 
instanceof ViewGroup)
{
//
如果是复合控件
                //
查找并设置id
                setCheckedId((ViewGroup)
child);
            }

  

/** 查找复合控件并设置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自定义控件的更多相关文章

  1. Android自定义控件之自定义ViewGroup实现标签云

    前言: 前面几篇讲了自定义控件绘制原理Android自定义控件之基本原理(一),自定义属性Android自定义控件之自定义属性(二),自定义组合控件Android自定义控件之自定义组合控件(三),常言 ...

  2. Android自定义控件之自定义组合控件

    前言: 前两篇介绍了自定义控件的基础原理Android自定义控件之基本原理(一).自定义属性Android自定义控件之自定义属性(二).今天重点介绍一下如何通过自定义组合控件来提高布局的复用,降低开发 ...

  3. Android自定义控件之自定义属性

    前言: 上篇介绍了自定义控件的基本要求以及绘制的基本原理,本篇文章主要介绍如何给自定义控件自定义一些属性.本篇文章将继续以上篇文章自定义圆形百分比为例进行讲解.有关原理知识请参考Android自定义控 ...

  4. Android自定义控件之基本原理

    前言: 在日常的Android开发中会经常和控件打交道,有时Android提供的控件未必能满足业务的需求,这个时候就需要我们实现自定义一些控件,今天先大致了解一下自定义控件的要求和实现的基本原理. 自 ...

  5. Android自定义控件1

    概述 Android已经为我们提供了大量的View供我们使用,但是可能有时候这些组件不能满足我们的需求,这时候就需要自定义控件了.自定义控件对于初学者总是感觉是一种复杂的技术.因为里面涉及到的知识点会 ...

  6. 一起来学习Android自定义控件1

    概述 Android已经为我们提供了大量的View供我们使用,但是可能有时候这些组件不能满足我们的需求,这时候就需要自定义控件了.自定义控件对于初学者总是感觉是一种复杂的技术.因为里面涉及到的知识点会 ...

  7. [Xamarin.Android] 自定义控件

    [Xamarin.Android] 自定义控件 前言 软件项目开发的过程中,免不了遇到一些无法使用内建控件就能满足的客户需求,例如:时速表.折线图...等等.这时开发人员可以透过自定义控件的方式,为项 ...

  8. android自定义控件实现TextView按下后字体颜色改变

    今天跟大家分享一下Android自定义控件入门,先介绍一个简单的效果TextView,按下改变字体颜色,后期慢慢扩展更强大的功能 直接看图片             第一张是按下后截的图,功能很简单, ...

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

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

随机推荐

  1. MySQL LIKE 子句

    MySQL LIKE 子句 我们知道在MySQL中使用 SQL SELECT 命令来读取数据, 同时我们可以在 SELECT 语句中使用 WHERE 子句来获取指定的记录. WHERE 子句中可以使用 ...

  2. TCP发送源码学习(3)--tcp_transmit_skb

    一.tcp_transmit_skb static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, g ...

  3. Dynamics CRM2011 导入解决方案报根组件插入错误的解决方法

    今天在还原一个老版本的解决方案,在导入时报根组件插入问题"Cannot add a Root Component 38974590-9322-e311-b365-00155d810a00 o ...

  4. android M Launcher之LauncherModel (二)

    上一篇我们通过LauncherModel的创建 ,实例化,以及与LauncherModel之间的沟通方式.初步了解了LauncherModel一些功能及用法,如果对LauncherModel一系列初始 ...

  5. Detailed Item Cost Report (XML) timed out waiting for the Output Post-processor to finish

    In this Document   Symptoms   Cause   Solution   References APPLIES TO: Oracle Cost Management - Ver ...

  6. ANT不完全总结,包含各种命令,ant例子等,转自:http://lavasoft.blog.51cto.com/62575/87306

    ANT不完全总结   好久没有用Ant了,最近让MyEclipse.JBuilder2008逼的重回Ant上了.手生了,写了一个脚本后,重新总结下.参考了官方的文档和网上一些资料.   一.ANT的介 ...

  7. Android TV开发总结(一)构建一个TV app前要知道的事儿

    转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/52792562 前言:近年来,智能 ...

  8. 在一维坐标轴上有n个区间段,求重合区间最长的两个区间段。

    //重叠区间数 #define N 2 typedef struct arrange { int x; int y; } Arrange; //先按左边界排序,若相等再按右边界排序(升序) int c ...

  9. Unsupported major.minor version 52.0

    今天运行项目,切换一下eclipse,运行程序突然发现普通的类main()方法无法运行,报错详细信息如下: Exception in thread "main" java.lang ...

  10. XMPP系列(七)---获取群组列表

    上一篇介绍了如何创建群组,这一篇就介绍一下,如何获取自己的群组列表. 在上一篇有提到,如果我们创建的群组是公共的群组,那么获取自己的群组列表时,会获取到自己的群组列表和那些公共的群组.而实际做社交的应 ...