自定義RadioButton ,單選按鈕

最近在做支付的項目,但是看到美團的支付選擇做的比較好,上圖,於是我就想照着做出來,可是簡單的做,還真沒那麼容易,於是自己重寫了RadioGroup 和 RadioButton,實現效果對比。

美團:我做出的效果:

雖然還是有差距,但是自己做的已經能夠自定義佈局來展示了,就算再複雜的佈局,只需修改部分代碼即可了。

下面上一下代碼:

1、這是自定義的RadioButton類:

package com.jj.radio;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.widget.Checkable;
import android.widget.ImageView;
import android.widget.RadioButton;
import android.widget.RelativeLayout;
import android.widget.TextView;

public class PayRadioPurified extends RelativeLayout implements Checkable {
	
	private ImageView payLogo;
	private TextView payTitle;
	private TextView payDesc;
	private RadioButton payChecked;
	
	private boolean mChecked;	////狀態是否選中
    private boolean mBroadcasting;
	private int id;
    private OnCheckedChangeListener mOnCheckedChangeWidgetListener;

	public PayRadioPurified(Context context, AttributeSet attrs) {
		super(context, attrs);
		LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		inflater.inflate(R.layout.payment_list_item,this);	
		
		payLogo = (ImageView) findViewById(R.id.pay_icon);
		payTitle = (TextView) findViewById(R.id.pay_name);
		payDesc = (TextView) findViewById(R.id.pay_desc);
		payChecked = (RadioButton) findViewById(R.id.pay_check);
		
		TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.PayRidioButton);
		
		Drawable d = array.getDrawable(R.styleable.PayRidioButton_radio);
		if (d != null) {
			payChecked.setButtonDrawable(d);
		}
		
		String title = array.getString(R.styleable.PayRidioButton_title);
		if (title != null) {
			setTextTitle(title);
		}
		
		String str = array.getString(R.styleable.PayRidioButton_desc);
		if (str != null) {
			setTextDesc(str);
		}
		
		Drawable logo = array.getDrawable(R.styleable.PayRidioButton_logo);
		if (logo != null) {
			setDrawableLogo(logo);
		}
		
		boolean checked = array.getBoolean(R.styleable.PayRidioButton_checked, false);
		payChecked.setChecked(checked);
		
		array.recycle();
		setClickable(true);
		
		id = getId();
	}
	
	@Override
	public boolean isChecked() {
		// TODO Auto-generated method stub
		return mChecked;
	}

	@Override
	public void setChecked(boolean checked) {
		// TODO Auto-generated method stub
		if (mChecked != checked) {
            mChecked = checked;
            payChecked.refreshDrawableState();

            // Avoid infinite recursions if setChecked() is called from a listener
            if (mBroadcasting) {
                return;
            }

            mBroadcasting = true;
            if (mOnCheckedChangeWidgetListener != null) {
                mOnCheckedChangeWidgetListener.onCheckedChanged(this, mChecked);
            }
            mBroadcasting = false;            
        }
	}

	@Override
	public void toggle() {
		// TODO Auto-generated method stub
		if (!isChecked()) {
			setChecked(!mChecked);
		}
	}
	
	@Override
	public boolean performClick() {
		// TODO Auto-generated method stub
		/*
         * XXX: These are tiny, need some surrounding 'expanded touch area',
         * which will need to be implemented in Button if we only override
         * performClick()
         */

        /* When clicked, toggle the state */
        toggle();
		return super.performClick();
	}

    /**
     * Register a callback to be invoked when the checked state of this button
     * changes. This callback is used for internal purpose only.
     *
     * @param listener the callback to call on checked state change
     * @hide
     */
    void setOnCheckedChangeWidgetListener(OnCheckedChangeListener listener) {
        mOnCheckedChangeWidgetListener = listener;
    }
    
    /**
     * Interface definition for a callback to be invoked when the checked state
     * of a compound button changed.
     */
    public static interface OnCheckedChangeListener {
        /**
         * Called when the checked state of a compound button has changed.
         *
         * @param buttonView The compound button view whose state has changed.
         * @param isChecked  The new checked state of buttonView.
         */
        void onCheckedChanged(PayRadioPurified buttonView, boolean isChecked);
    }
    
    public void setTextDesc(String s) {
    	if (s != null) {
    		payDesc.setText(s);
        }
    }
    
    public void setTextTitle(String s) {
		if (s != null) {
			payTitle.setText(s);
		}
	}
    
    public String getTextTitle() {
    	String s = payTitle.getText().toString();
		return s == null ? "" : s;
	}
    
    public void setDrawableLogo (Drawable d) {
    	if (d != null) {
    		payLogo.setImageDrawable(d);
    	}
    }
    
    public void setChangeImg(int checkedId) {
    	System.out.println(">>" + checkedId);
    	System.out.println(">>" + id);
		if (checkedId == id) {
			payChecked.setChecked(true);
		} else {
			payChecked.setChecked(false);
		}
	}

}

關鍵點:

(1)把父佈局,具有點擊事件setClickable(true);

(2)還是用RadioButton來監聽部分點擊的變化處理,也就是payChecked

(3)toggle()方法的處理

(4)performClick()事件,必須添加!

(5)在改變RadioButton按鈕背景的時候,我用了getId()的處理,這裏不好,但是自己技術有限,還沒能找到更好的處理辦法,

(6)缺陷:複用性不好!僅作demo。


2、關於RadioGroup的代碼改動的比較少,自己修改下就行了,改動的地方也就是關聯的PayRadioPurified上代碼,

如果不懂的可以下載源碼。

3、Activity代碼:

PayRadioGroup group = (PayRadioGroup) findViewById(R.id.genderGroup);
		group.setOnCheckedChangeListener(new OnCheckedChangeListener() {
			
			@Override
			public void onCheckedChanged(PayRadioGroup group, int checkedId) {
				// TODO Auto-generated method stub
				int radioButtonId = group.getCheckedRadioButtonId();
//				PayRadioButton rb = (PayRadioButton)MainActivity.this.findViewById(radioButtonId);
//				Toast.makeText(MainActivity.this, rb.getText(), Toast.LENGTH_SHORT).show();
				
				PayRadioPurified rl = (PayRadioPurified)MainActivity.this.findViewById(radioButtonId);
				for (int i = 0; i < group.getChildCount(); i++) {
					((PayRadioPurified)group.getChildAt(i)).setChangeImg(checkedId);
				}				
				Toast.makeText(MainActivity.this, rl.getTextTitle(), Toast.LENGTH_SHORT).show();
			}
		});

注:在此Demo實現的時候,改動了最基礎的RadioButton,進行研究,所以源碼中有三個參考類,都是自實現RadioButton的測試代碼。

希望幫到大家:

傳送門:項目源碼


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章