`

不带布局的RadioGroup——NoLayoutRadioGroup

 
阅读更多

虽然android的源码也时不时的会去看,但大部分还是只能看懂部分。这里只把能完全看懂的源码上传了。 

android.widget.AnalogClock 
这个类比较简单,如果想要创建自己的View,可以从参考这个类开始。像TextView这种将近一万行的源码就太多了。还有一个比这个稍微难一点的是ImageView,也可以看那个类 

Java代码  收藏代码
  1. public class AnalogClock extends View {  
  2.     private Time mCalendar;  
  3.       
  4.     /** 时针背景 */  
  5.     private Drawable mHourHand;  
  6.     /** 分针背景 */  
  7.     private Drawable mMinuteHand;  
  8.     /** 表盘背景 */  
  9.     private Drawable mDial;  
  10.       
  11.     /** 表盘宽度 */  
  12.     private int mDialWidth;  
  13.     /** 表盘高度 */  
  14.     private int mDialHeight;  
  15.   
  16.     /** 是否添加到WindowManager中 */  
  17.     private boolean mAttached;  
  18.   
  19.     private final Handler mHandler = new Handler();  
  20.     private float mMinutes;  
  21.     private float mHour;  
  22.     /** 时间是否改变了 */  
  23.     private boolean mChanged;  
  24.   
  25.     public AnalogClock(Context context) {  
  26.         this(context, null);  
  27.     }  
  28.   
  29.     public AnalogClock(Context context, AttributeSet attrs) {  
  30.         this(context, attrs, 0);  
  31.     }  
  32.   
  33.     public AnalogClock(Context context, AttributeSet attrs,  
  34.                        int defStyle) {  
  35.         super(context, attrs, defStyle);  
  36.         Resources r = mContext.getResources();  
  37.         TypedArray a =  
  38.                 context.obtainStyledAttributes(  
  39.                         attrs, com.android.internal.R.styleable.AnalogClock, defStyle, 0);  
  40.   
  41.         mDial = a.getDrawable(com.android.internal.R.styleable.AnalogClock_dial);  
  42.         if (mDial == null) {  
  43.             mDial = r.getDrawable(com.android.internal.R.drawable.clock_dial);  
  44.         }  
  45.   
  46.         mHourHand = a.getDrawable(com.android.internal.R.styleable.AnalogClock_hand_hour);  
  47.         if (mHourHand == null) {  
  48.             mHourHand = r.getDrawable(com.android.internal.R.drawable.clock_hand_hour);  
  49.         }  
  50.   
  51.         mMinuteHand = a.getDrawable(com.android.internal.R.styleable.AnalogClock_hand_minute);  
  52.         if (mMinuteHand == null) {  
  53.             mMinuteHand = r.getDrawable(com.android.internal.R.drawable.clock_hand_minute);  
  54.         }  
  55.   
  56.         mCalendar = new Time();  
  57.   
  58.         mDialWidth = mDial.getIntrinsicWidth();  
  59.         mDialHeight = mDial.getIntrinsicHeight();  
  60.     }  
  61.   
  62.     @Override  
  63.     protected void onAttachedToWindow() {  
  64.         super.onAttachedToWindow();  
  65.   
  66.         if (!mAttached) {  
  67.             mAttached = true;  
  68.             IntentFilter filter = new IntentFilter();  
  69.   
  70.             filter.addAction(Intent.ACTION_TIME_TICK);  
  71.             filter.addAction(Intent.ACTION_TIME_CHANGED);  
  72.             filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);  
  73.   
  74.             getContext().registerReceiver(mIntentReceiver, filter, null, mHandler);  
  75.         }  
  76.   
  77.         // NOTE: It's safe to do these after registering the receiver since the receiver always runs  
  78.         // in the main thread, therefore the receiver can't run before this method returns.  
  79.   
  80.         // The time zone may have changed while the receiver wasn't registered, so update the Time  
  81.         mCalendar = new Time();  
  82.   
  83.         // Make sure we update to the current time  
  84.         onTimeChanged();  
  85.     }  
  86.   
  87.     @Override  
  88.     protected void onDetachedFromWindow() {  
  89.         super.onDetachedFromWindow();  
  90.         if (mAttached) {  
  91.             getContext().unregisterReceiver(mIntentReceiver);  
  92.             mAttached = false;  
  93.         }  
  94.     }  
  95.   
  96.     @Override  
  97.     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
  98.   
  99.         int widthMode = MeasureSpec.getMode(widthMeasureSpec);  
  100.         // layout提供的可用Width  
  101.         int widthSize =  MeasureSpec.getSize(widthMeasureSpec);  
  102.         int heightMode = MeasureSpec.getMode(heightMeasureSpec);  
  103.         // layout提供的可用Height  
  104.         int heightSize =  MeasureSpec.getSize(heightMeasureSpec);  
  105.   
  106.         float hScale = 1.0f;  
  107.         float vScale = 1.0f;  
  108.   
  109.         // 如果layout_width和layout_height是指定了值的  
  110.         if (widthMode != MeasureSpec.UNSPECIFIED && widthSize < mDialWidth) {  
  111.             hScale = (float) widthSize / (float) mDialWidth;  
  112.         }  
  113.   
  114.         if (heightMode != MeasureSpec.UNSPECIFIED && heightSize < mDialHeight) {  
  115.             vScale = (float )heightSize / (float) mDialHeight;  
  116.         }  
  117.   
  118.         // 按照缩的比较小的缩放  
  119.         float scale = Math.min(hScale, vScale);  
  120.   
  121.         setMeasuredDimension(resolveSize((int) (mDialWidth * scale), widthMeasureSpec),  
  122.                 resolveSize((int) (mDialHeight * scale), heightMeasureSpec));  
  123.     }  
  124.   
  125.     @Override  
  126.     protected void onSizeChanged(int w, int h, int oldw, int oldh) {  
  127.         super.onSizeChanged(w, h, oldw, oldh);  
  128.         mChanged = true;  
  129.     }  
  130.   
  131.     @Override  
  132.     protected void onDraw(Canvas canvas) {  
  133.         super.onDraw(canvas);  
  134.   
  135.         boolean changed = mChanged;  
  136.         if (changed) {  
  137.             mChanged = false;  
  138.         }  
  139.   
  140.         int availableWidth = mRight - mLeft;  
  141.         int availableHeight = mBottom - mTop;  
  142.   
  143.         // 居中  
  144.         int x = availableWidth / 2;  
  145.         int y = availableHeight / 2;  
  146.   
  147.         final Drawable dial = mDial;  
  148.         int w = dial.getIntrinsicWidth();  
  149.         int h = dial.getIntrinsicHeight();  
  150.   
  151.         boolean scaled = false;  
  152.   
  153.         // 图片实际宽高比view的宽高大时,要对图片缩放  
  154.         if (availableWidth < w || availableHeight < h) {  
  155.             scaled = true;  
  156.             float scale = Math.min((float) availableWidth / (float) w,  
  157.                                    (float) availableHeight / (float) h);  
  158.             canvas.save();  
  159.             canvas.scale(scale, scale, x, y);  
  160.         }  
  161.   
  162.         if (changed) {  
  163.             dial.setBounds(x - (w / 2), y - (h / 2), x + (w / 2), y + (h / 2));  
  164.         }  
  165.         dial.draw(canvas);  
  166.   
  167.         // 绘制时针  
  168.         canvas.save();  
  169.         canvas.rotate(mHour / 12.0f * 360.0f, x, y);  
  170.         final Drawable hourHand = mHourHand;  
  171.         if (changed) {  
  172.             w = hourHand.getIntrinsicWidth();  
  173.             h = hourHand.getIntrinsicHeight();  
  174.             hourHand.setBounds(x - (w / 2), y - (h / 2), x + (w / 2), y + (h / 2));  
  175.         }  
  176.         hourHand.draw(canvas);  
  177.         canvas.restore();  
  178.   
  179.         // 绘制分针  
  180.         canvas.save();  
  181.         canvas.rotate(mMinutes / 60.0f * 360.0f, x, y);  
  182.   
  183.         final Drawable minuteHand = mMinuteHand;  
  184.         if (changed) {  
  185.             w = minuteHand.getIntrinsicWidth();  
  186.             h = minuteHand.getIntrinsicHeight();  
  187.             minuteHand.setBounds(x - (w / 2), y - (h / 2), x + (w / 2), y + (h / 2));  
  188.         }  
  189.         minuteHand.draw(canvas);  
  190.         canvas.restore();  
  191.   
  192.         // 结束  
  193.         if (scaled) {  
  194.             canvas.restore();  
  195.         }  
  196.     }  
  197.   
  198.     private void onTimeChanged() {  
  199.         mCalendar.setToNow();  
  200.   
  201.         int hour = mCalendar.hour;  
  202.         int minute = mCalendar.minute;  
  203.         int second = mCalendar.second;  
  204.   
  205.         mMinutes = minute + second / 60.0f;  
  206.         mHour = hour + mMinutes / 60.0f;  
  207.         mChanged = true;  
  208.     }  
  209.   
  210.     private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {  
  211.         @Override  
  212.         public void onReceive(Context context, Intent intent) {  
  213.             if (intent.getAction().equals(Intent.ACTION_TIMEZONE_CHANGED)) {  
  214.                 String tz = intent.getStringExtra("time-zone");  
  215.                 mCalendar = new Time(TimeZone.getTimeZone(tz).getID());  
  216.             }  
  217.   
  218.             onTimeChanged();  
  219.               
  220.             invalidate();  
  221.         }  
  222.     };  
  223. }  




不带布局的RadioGroup——NoLayoutRadioGroup 
android提供的RadioGroup是一个LinearLayout,有时我们要在像TableLayout中的每个行使用一个RadioButton的话,RadioGroup就不太好用,所以参考RadioGroup实现了一个不带布局的RadioGroup. 

Java代码  收藏代码
  1. /*** 
  2.  * 使用了这个类,RadioButton的OnCheckedChangeListener会被覆盖掉,所以 
  3.  * 要使用监听器的话,使用这边的NonLayoutRadioGroup.OnCheckedChangeListener 
  4.  */  
  5. public class NonLayoutRadioGroup {  
  6.     public interface OnCheckedChangeListener {  
  7.         /*** 
  8.          * @param group 触发该事件的NonLayoutRadioGroup 
  9.          * @param view 触发该事件的RadioButton, 当调用clearCheck时,view的值为null 
  10.          */  
  11.         public void onCheckedChanged(NonLayoutRadioGroup group, RadioButton view);  
  12.     }  
  13.       
  14.     private List<RadioButton> mRadioButtons = new ArrayList<RadioButton>();  
  15.       
  16.     private RadioButton mCheckButton;  
  17.       
  18.     private OnCheckedChangeListener mListener;  
  19.       
  20.     private CompoundButton.OnCheckedChangeListener mCheckedListener =  
  21.             new CompoundButton.OnCheckedChangeListener() {  
  22.         @Override  
  23.         public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {  
  24.             if (!isChecked) {  
  25.                 mCheckButton = null;  
  26.                 return;  
  27.             }  
  28.             if (mCheckButton != null) {  
  29.                 mCheckButton.setChecked(false);  
  30.             }  
  31.               
  32.             setCheckedButton((RadioButton) buttonView);  
  33.         }  
  34.     };  
  35.       
  36.     public void addRadioButton(RadioButton button) {  
  37.         // 不能添加null  
  38.         // 为没有id的RadioButton生成一个Id  
  39.         if (button.getId() == View.NO_ID) {  
  40.             button.setId(button.hashCode());  
  41.         }  
  42.         button.setOnCheckedChangeListener(null);  
  43.         if (button.isChecked()) {  
  44.             // 移除原来的  
  45.             if (mCheckButton != null) {  
  46.                 mCheckButton.setChecked(false);  
  47.             }  
  48.               
  49.             setCheckedButton(button);  
  50.         }  
  51.         button.setOnCheckedChangeListener(mCheckedListener);  
  52.         mRadioButtons.add(button);  
  53.     }  
  54.       
  55.     public void removeRadioButton(RadioButton button) {  
  56.         // 添加到这里面的移除时,才需要清除其OnCheckedChangeListener  
  57.         if (mRadioButtons.contains(button)) {  
  58.             button.setOnCheckedChangeListener(null);  
  59.             mRadioButtons.remove(button);  
  60.         }  
  61.     }  
  62.       
  63.     public void setOnCheckedChangeListener(OnCheckedChangeListener listener) {  
  64.         mListener = listener;  
  65.     }  
  66.       
  67.     public void check(RadioButton button) {  
  68.         // check原来选中的  
  69.         if (button != null && mCheckButton == button) {  
  70.             return;  
  71.         }  
  72.         // 移除选中的  
  73.         if (mCheckButton != null) {  
  74.             mCheckButton.setChecked(false);  
  75.         }  
  76.         // 设置选中的  
  77.         if (button != null) {  
  78.             button.setChecked(true);  
  79.         }  
  80.         // 触发监听器  
  81.         setCheckedButton(button);  
  82.     }  
  83.       
  84.     public void clearCheck() {  
  85.         check(null);  
  86.     }  
  87.       
  88.     public RadioButton getCheckedRadioButton() {  
  89.         return mCheckButton;  
  90.     }  
  91.       
  92.     // ////////////////////////////////////////////////  
  93.     /*** 
  94.      * 设置选中的RadioButton 
  95.      */  
  96.     private void setCheckedButton(RadioButton button) {  
  97.         mCheckButton = button;  
  98.         if (mListener != null) {  
  99.             if (button != null) {  
  100.                 mListener.onCheckedChanged(this, button);  
  101.             }  
  102.             else {  
  103.                 mListener.onCheckedChanged(thisnull);  
  104.             }  
  105.         }  
  106.     }  
  107. }  
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics