仿火币排序按钮,三种排序状态切换

最近在重构公司app,产品经理设计了一种排序方式,类似火币pro行情页,京东行情页那种排序按钮,有三种状态,如下图:

排序按钮状态图

其中各个排序分类是互斥的,每个排序分类有三种状态:默认、升序、降序。

如果通过布局写的话也能实现,但是比较不方便,如果动态增加排序状态比较麻烦,所以给封装成了控件,仿照RadioGroup可以动态增加排序分类。

核心代码见:SortRadioGroup.java

public class SortRadioGroupextends RelativeLayout {

// holds the checked id; the selection is empty by default

    private int mCheckedId = -1;

// tracks children radio buttons checked state

    private SortRadioButton.OnCheckedChangeListenermChildOnCheckedChangeListener;

// when true, mOnCheckedChangeListener discards events

    private boolean mProtectFromCheckedChange =false;

private OnCheckedChangeListenermOnCheckedChangeListener;

private PassThroughHierarchyChangeListenermPassThroughListener;

/**

    * {@inheritDoc}

*/

    public SortRadioGroup(Context context) {

super(context);

init();

}

/**

    * {@inheritDoc}

*/

    public SortRadioGroup(Context context, AttributeSet attrs) {

super(context, attrs);

init();

}

private void init() {

//setOrientation(HORIZONTAL);

        mChildOnCheckedChangeListener =new CheckedStateTracker();

mPassThroughListener =new PassThroughHierarchyChangeListener();

super.setOnHierarchyChangeListener(mPassThroughListener);

}

/**

    * {@inheritDoc}

*/

    @Override

    public void setOnHierarchyChangeListener(OnHierarchyChangeListener listener) {

// the user listener is delegated to our pass-through listener

        mPassThroughListener.mOnHierarchyChangeListener = listener;

}

/**

    * {@inheritDoc}

*/

    @Override

    protected void onFinishInflate() {

super.onFinishInflate();

// checks the appropriate radio button as requested in the XML file

        if (mCheckedId != -1) {

mProtectFromCheckedChange =true;

setCheckedStateForView(mCheckedId,true);

mProtectFromCheckedChange =false;

}

}

@Override

    public void addView(View child,int index, ViewGroup.LayoutParams params) {

if (childinstanceof SortRadioButton) {

final SortRadioButton button = (SortRadioButton) child;

if (button.isChecked()) {

mProtectFromCheckedChange =true;

if (mCheckedId != -1) {

setCheckedStateForView(mCheckedId,false);

}

mProtectFromCheckedChange =false;

}

}

super.addView(child, index, params);

}

/**

    *

Sets the selection to the radio button whose identifier is passed in

* parameter. Using -1 as the selection identifier clears the selection;

    * such an operation is equivalent to invoking {@link #clearCheck()}.

*

    * @param id the unique id of the radio button to select in this group

    * @see #getCheckedRadioButtonId()

    * @see #clearCheck()

*/

    public void check(int id) {

// don't even bother

        if (id != -1 && (id ==mCheckedId)) {

return;

}

if (mCheckedId != -1) {

setCheckedStateForView(mCheckedId,false);

}

if (id != -1) {

setCheckedStateForView(id,true);

}

setCheckedId(id);

}

private void setCheckedId(int id) {

mCheckedId = id;

}

public OnCheckedChangeListener getOnCheckedChangeListener() {

return mOnCheckedChangeListener;

}

public interface OnCheckedChangeListener {

/**

        *

Called when the checked radio button has changed. When the

        * selection is cleared, checkedId is -1.

*

        * @param group    the group in which the checked radio button has changed

        * @param checkedId the unique identifier of the newly checked radio button

*/

        public void onCheckedChanged(SortRadioGroup group,@IdRes int checkedId,int orientation);

}

private void setCheckedStateForView(int viewId,boolean checked) {

View checkedView = findViewById(viewId);

if (checkedView !=null && checkedViewinstanceof SortRadioButton) {

SortRadioButton radioButton = (SortRadioButton) checkedView;

((SortRadioButton) checkedView).setChecked(checked, radioButton.isOrientation());

}

}

/**

    *

Returns the identifier of the selected radio button in this group.

    * Upon empty selection, the returned value is -1.

*

    * @return the unique id of the selected radio button in this group

    * @attr ref android.R.styleable#RadioGroup_checkedButton

    * @see #clearCheck()

*/

    public int getCheckedRadioButtonId() {

return mCheckedId;

}

/**

    *

Clears the selection. When the selection is cleared, no radio button

    * in this group is selected and {@link #getCheckedRadioButtonId()} returns

    * null.

*

    * @see #getCheckedRadioButtonId()

*/

    public void clearCheck() {

check(-1);

}

/**

    *

Register a callback to be invoked when the checked radio button

    * changes in this group.

*

    * @param listener the callback to call on checked state change

*/

    public void setOnCheckedChangeListener(OnCheckedChangeListener listener) {

mOnCheckedChangeListener = listener;

}

private class CheckedStateTrackerimplements SortRadioButton.OnCheckedChangeListener {

public void onCheckedChanged(SortRadioButton buttonView,boolean isChecked) {

// prevents from infinite r ecursion

            if (mProtectFromCheckedChange) {

return;

}

mProtectFromCheckedChange =true;

if (mCheckedId != -1) {

setCheckedStateForView(mCheckedId,false);

}

mProtectFromCheckedChange =false;

int id = buttonView.getId();

setCheckedId(id);

}

}

/**

    *

A pass-through listener acts upon the events and dispatches them

* to another listener. This allows the table layout to set its own internal

    * hierarchy change listener without preventing the user to setup his.

*/

    private class PassThroughHierarchyChangeListenerimplements

            OnHierarchyChangeListener {

private OnHierarchyChangeListenermOnHierarchyChangeListener;

/**

        * {@inheritDoc}

*/

        public void onChildViewAdded(View parent, View child) {

if (parent == SortRadioGroup.this && childinstanceof SortRadioButton) {

int id = child.getId();

// generates an id if it's missing

                if (id == View.NO_ID) {

throw new RuntimeException("SoftRadioButton must set Id");

}

((SortRadioButton) child).setOnCheckedChangeWidgetListener(mChildOnCheckedChangeListener);

}

if (mOnHierarchyChangeListener !=null) {

mOnHierarchyChangeListener.onChildViewAdded(parent, child);

}

}

/**

        * {@inheritDoc}

*/

        public void onChildViewRemoved(View parent, View child) {

if (mOnHierarchyChangeListener !=null) {

mOnHierarchyChangeListener.onChildViewRemoved(parent, child);

}

}

}

public interface SortCheckable {

/**

        * @param checked      true 或 false

        * @param isOrientation 0默认 ,1上, 2下

*/

        void setChecked(boolean checked,int isOrientation);

/**

        * @return The current checked state of the view

*/

        boolean isChecked();

/**

* Change the checked state of the view to the inverse of its current state

*/

        void toggle();

}

}

核心代码见:SortRadioButton.java

public class SortRadioButtonextends FrameLayoutimplements SortRadioGroup.SortCheckable {

/**

* down  false  up true

*/

    private boolean mBroadcasting;

private int orientation =0;

private TextViewmTv_checkable_text;

private ImageViewmIv_checkable_up;

private ImageViewmIv_checkable_down;

private OnCheckedChangeListenermOnCheckedChangeWidgetListener;

private int textColor = Color.BLACK;

private int textColorChecked = Color.RED;

private int upImageRes,upImageResChecked,downImageRes,downImageResChecked;

private SortRadioButton(Context context) {

super(context);

}

public SortRadioButton(Context context, AttributeSet attrs) {

super(context, attrs);

initView(attrs);

}

public SortRadioButton(Context context, AttributeSet attrs,int defStyleAttr) {

super(context, attrs, defStyleAttr);

initView(attrs);

}

private void initView(AttributeSet attrs) {

TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.SortRadioButton);

String text = ta.getString(R.styleable.SortRadioButton_text);

textColor = ta.getColor(R.styleable.SortRadioButton_textColor,textColor);

textColorChecked = ta.getColor(R.styleable.SortRadioButton_textColorChecked,textColorChecked);

upImageRes = ta.getResourceId(R.styleable.SortRadioButton_upImage,0);

downImageRes = ta.getResourceId(R.styleable.SortRadioButton_downImage,0);

upImageResChecked = ta.getResourceId(R.styleable.SortRadioButton_upImageChecked,0);

downImageResChecked = ta.getResourceId(R.styleable.SortRadioButton_downImageChecked,0);

ta.recycle();

LayoutInflater inflate = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);

View view = inflate.inflate(R.layout.view_soft_item,this,true);

mTv_checkable_text = (TextView) findViewById(R.id.tv_checkable_text);

mIv_checkable_up = (ImageView) findViewById(R.id.iv_checkable_up);

mIv_checkable_down = (ImageView) findViewById(R.id.iv_checkable_down);

mTv_checkable_text.setText(text);

refreshView();

setOnClickListener(null);

}

private boolean ischecked;

public void setText(CharSequence text) {

mTv_checkable_text.setText(text);

}

public CharSequence getText() {

return mTv_checkable_text.getText();

}

private OnClickListenerml;

@Override

    public void setOnClickListener(@Nullable OnClickListener l) {

ml = l;

super.setOnClickListener(new OnClickListener() {

@Override

            public void onClick(View v) {

if (ml !=null) {

ml.onClick(v);

}

if (orientation ==0) {

orientation =1;

}else if (orientation ==1) {

orientation =2;

}else {

orientation =0;

}

if (isChecked()) {

setChecked(true,orientation);

}else {

setChecked(true,orientation);

}

refreshView();

}

});

}

private SortRadioGroupsoftGroup;

public SortRadioGroup getGroup() {

if (softGroup ==null) {

if (getParent() !=null && getParent()instanceof SortRadioGroup) {

softGroup = (SortRadioGroup) getParent();

}

}

return softGroup;

}

@Override

    public void setChecked(boolean checked,int isOrientation) {

if (checked) {

makeCallBack(isOrientation);

}

if (ischecked != checked) {//刷新其他的

            ischecked = checked;

refreshView();

if (mBroadcasting) {

return;

}

mBroadcasting =true;

if (mOnCheckedChangeWidgetListener !=null) {

mOnCheckedChangeWidgetListener.onCheckedChanged(this,ischecked);

}

mBroadcasting =false;

}else {

if (isOrientation !=orientation) {

refreshView();

if (mBroadcasting) {

return;

}

mBroadcasting =true;

if (mOnCheckedChangeWidgetListener !=null) {

mOnCheckedChangeWidgetListener.onCheckedChanged(this,ischecked);

}

mBroadcasting =false;

}

}

}

private void makeCallBack(int isOrientation) {

SortRadioGroup group = getGroup();

if (group !=null && group.getOnCheckedChangeListener() !=null) {

group.getOnCheckedChangeListener().onCheckedChanged(group, getId(), isOrientation);

}

}

@Override

    public boolean isChecked() {

return ischecked;

}

public int isOrientation() {

return orientation;

}

@Override

    public void toggle() {

ischecked = !ischecked;

refreshView();

}

private void refreshView() {

if (isChecked()) {

if (orientation ==0) {

mIv_checkable_up.setImageResource(upImageRes);

mIv_checkable_down.setImageResource(downImageRes);

}else if (orientation ==1) {

mIv_checkable_up.setImageResource(upImageResChecked);

mIv_checkable_down.setImageResource(downImageRes);

}else {

mIv_checkable_up.setImageResource(upImageRes);

mIv_checkable_down.setImageResource(downImageResChecked);

}

mTv_checkable_text.setTextColor(textColorChecked);

}else {

orientation =0;

mIv_checkable_up.setImageResource(upImageRes);

mIv_checkable_down.setImageResource(downImageRes);

mTv_checkable_text.setTextColor(textColor);

}

}

public void setOnCheckedChangeWidgetListener(OnCheckedChangeListener onCheckedChangeWidgetListener) {

mOnCheckedChangeWidgetListener = onCheckedChangeWidgetListener;

}

public 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(SortRadioButton buttonView,boolean isChecked);

}

}

用法跟radiogroup+radiobutton一样,使用setOnCheckedChangeListener方法,获取切换的事件,orientation代表状态0、1、2分别是默认,升序,降序。

仓促之间写的代码,不足之处请指正。稍后会将代码同步到github。

你可能感兴趣的:(仿火币排序按钮,三种排序状态切换)