How to switch button image from on to off and vice versa upon click?

北战南征 提交于 2019-12-06 00:22:05

I agree with @Chronos, it sounds more like a ToggleButton with two states. Keep it simple, here's mine you can use as an example. No code necessary, just xml.

here's the xml for my layout:

<ToggleButton
        android:id="@+id/btnHeadache"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_centerHorizontal="true"
        android:background="@drawable/headache_button"
        android:paddingTop="25sp"
        android:text="@string/headache"
        android:textOn=""
        android:textOff="" />

Now here's the xml for the different state's, that is of course inside my drawable folder with the images. This is named headache_button.xml in case its not clear above.:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/check"  android:state_checked="true"/> <!-- currently pressed turning the toggle on -->
    <item android:drawable="@drawable/headache" android:state_checked="false" /> <!-- currently pressed turning the toggle off   -->
</selector>

If I understand fine you need a ToggleButton, a button with two states.

And use a selector like this one:

<?xml version="1.0" encoding="UTF-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:drawable="@drawable/btn_normal" android:state_checked="false"/>
    <item android:drawable="@drawable/btn_pressed" android:state_checked="true"/>

</selector>

You can do this in code using:

// Declare button
// Set its original background image
button.setBackground(getResources().getDrawable(R.drawable.original_button_image));

button.setOnClickListener(new OnClickListener() {

    @Override
    public void onClick(View v) {

        // Choose whichever image for pressed state
        v.setBackground(getResources().getDrawable(R.drawable.button_is_pressed)); 

        new Handler().postDelayed(new Runnable() {

            public void run() {

                v.setBackground(getResources().getDrawable(R.drawable.original_button_image));

                // Button Click Code Here
            }

        }, 100L);    // Change this value to whatever is suitable

    }

});

Edit 1:

<ImageButton
        android:id="@+id/menu_button"
        android:layout_width="30dp"
        android:layout_height="48.5dp"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:background="@android:color/transparent"
        android:src="@drawable/testdrawable"
        android:paddingRight="24dp" />

Since the button has only two states, try testdrawable instead of the one you posted in your question:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item 
        android:state_selected="true" 
        android:drawable="@drawable/overflow_pressed" />
    <item 
        android:drawable="@drawable/overflow" />
</selector>

Change your onClick(View) to:

@Override
public void onClick(final View view) {
    switch (view.getId()) {
        case R.id.justin_menu_button:

            if (button.isSelected()) {
                button.setSelected(false);
                isPreferences = false;
                mPreferencesMenuHelper.hideMenu();
                Log.i("ImageButtonCheck", "Button is not selected anymore");
            } else {
                button.setSelected(true);
                final Activity activity = getActivity();
                final int actionBarHeight = activity.findViewById(R.id.title_main_container).getHeight();
                final int menuBarHeight = activity.findViewById(R.id.justin_top_bar_container).getHeight();
                mPreferencesMenuHelper.showMenu(actionBarHeight + menuBarHeight, Gravity.RIGHT, R.style.MenuDialogAnimation);
                isPreferences = true;
                Log.i("ImageButtonCheck", "Button is in selected state");
            }

            break;
        default:
            break;
    }
}

Change onMenuItemClicked(int) to:

@Override
public void onMenuItemClicked(final int position) {
    if (isPreferences) {
        switch (position) {
            case PreferenceMenuItems.JUSTIN_PREFERENCES_POSITION:
                PreferencesActivity.newInstance(getActivity());
                break;
            default:
                break;
        }
        isPreferences = false;
        button.setSelected(false);
        mPreferencesMenuHelper.hideMenu();
        Log.i("ImageButtonCheck", "Button is not in a selected state because of a menu item click");
    } else {
        switch (position) {
            case DeleteMenuItems.DELETE_POSITION:
                final DialogFragment dialog = new DeleteFromDialogFragment();
                final Bundle bundle = new Bundle();
                bundle.putString(JUSTIN_ID, mJustinID);
                dialog.setArguments(bundle);
                dialog.show(getFragmentManager(), DELETE_FROM_JUSTIN );
                break;
            default:
                break;
        }
        mDeleteMenuHelper.hideMenu();
    }
}

I think the problem here is that when the button is first pressed, the selected state is achieved and the menu is shown. But, clicking the button again, while the menu is shown, does not call the onClick(View) method. I have included 3 log statements in the code above. Let me know of the output you see in logcat when you click the button once to show the menu and click the menu again to hide it. The output from these two clicks should be "Button is in selected state" and "Button is not selected anymore".

Edit 2:

Include MenuHelper as an inner class in your activity class:

public class MenuHelper implements OnItemClickListener, Dialog.OnDismissListener {

    private final Dialog mMenu;
    private final OnMenuItemClickedListener mMenuItemListener;
    private final ArrayAdapter<String> mAdapter;
    private final int MENU_ITEM_HEIGHT = 40; // Defined in res/layout/menu_item.xml

    private List<Boolean> enabledStates;

    public MenuHelper(final Context context, final List<String> menuItems, final OnMenuItemClickedListener menuItemListener) {
        mMenu = new Dialog(context);
        mMenu.requestWindowFeature(Window.FEATURE_NO_TITLE);
        mMenu.setContentView(R.layout.menu_container);
        mMenu.setOnDismissListener(this);  -------------------------> **add this**
        enabledStates = new ArrayList<Boolean>(menuItems.size());
        for(int i = 0; i < menuItems.size(); i++) {
            enabledStates.add(true);
        }

        final ListView menuList = (ListView) mMenu.findViewById(R.id.menu_list);
        mAdapter = new ArrayAdapter<String>(context, R.layout.menu_item, menuItems) {
            @Override
            public boolean isEnabled(int position) {
                return enabledStates.get(position);
            }

            @Override
            public boolean areAllItemsEnabled() {
                return false;
            }

            @Override
            public View getView(int position, View convertView, ViewGroup parent) {
                View view = super.getView(position, convertView, parent);
                if(enabledStates.get(position)) {
                    ((TextView) view).setTextColor(Application.getAppResources().getColor(R.color.white));
                } else {
                    ((TextView) view).setTextColor(Application.getAppResources().getColor(R.color.disabled_gray));
                }
                if (convertView == null) {
                    convertView = super.getView(position, convertView, parent);
                }

                // check for odd or even to set alternate colors to the row background
                if (position % 2 == 0) {
                    convertView.setBackgroundResource(R.drawable.oddcellcolor);
                } else {
                    convertView.setBackgroundResource(R.drawable.evencellcolor);
                }
                return convertView;
                //return view;
            }
        };
        menuList.setOnItemClickListener(this);
        menuList.setAdapter(mAdapter);
        mMenuItemListener = menuItemListener;
    }

    public void showMenu(final int yPosition, final int horizontalGravity) {
        showMenu(yPosition, horizontalGravity, R.style.MenuDialogAnimation);
    }

    public void setEnabled(int position, boolean isEnabled) {
        enabledStates.set(position, isEnabled);
        mAdapter.notifyDataSetChanged();
    }

    public void setEnabledAll(boolean isEnabled) {
        for(int ii = 0; ii < enabledStates.size(); ii++) {
            enabledStates.set(ii, isEnabled);
        }
        mAdapter.notifyDataSetChanged();
    }

    public int getMenuHeight() {
        if (mMenu != null) {
            return (int) (mAdapter.getCount() * MENU_ITEM_HEIGHT  / Application.getAppResources().getDisplayMetrics().density);
        } else {
            return -1;
        }
    }

    public void showMenu(final float yPosition, final int horizontalGravity, final int animation) {
        final Window window = mMenu.getWindow();
        window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
        if (horizontalGravity != Gravity.CENTER) {
            window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
        }
        final WindowManager.LayoutParams params = window.getAttributes();
        params.gravity = Gravity.TOP | horizontalGravity;
        params.y = Math.round(yPosition);
        params.windowAnimations = animation;
        window.setAttributes(params);
        mMenu.show();
    }

    public void hideMenu() {
        mMenu.hide();
    }

    @Override
    public void onItemClick(final AdapterView<?> adapter, final View view, final int position, final long parent) {
        mMenuItemListener.onMenuItemClicked(position);
    }

    @Override
    public void onDismiss(DialogInterface arg0) {
        button.setSelected(false);
    }

}

It sounds more like you should be using a CheckBox. Regular buttons don't have an "on" state, just pressed and focused. With a checkbox, you'll need to use android:state_checked="true". Clicking the checkbox will switch to the checked state, clicking it again switches it back to default (unchecked).

Try not to add extra java code until you're sure that you can't do something with XML.

If I've understood you right, you want a 'Button' that has two states and taping it toggles between them.

In which case, it looks to more like you want the behavior of a 'ToggleButton', 'CompoundButton' or 'Switch' . You can configure them in xml using 'android :state_checked' as per @Chronos.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!