Tint / dim drawable on touch

前端 未结 8 1470
别跟我提以往
别跟我提以往 2021-01-31 11:24

The app I\'m currently working on uses a lot of ImageViews as buttons. The graphics on these buttons use the alpha channel to fade out the edges of the button and make them look

相关标签:
8条回答
  • 2021-01-31 11:40

    For those who have encountered a similar need, solving this in code is fairly clean. Here is a sample:

    public class TintableButton extends ImageView {
    
        private boolean mIsSelected;
    
        public TintableButton(Context context) {
            super(context);
            init();
        }   
    
        public TintableButton(Context context, AttributeSet attrs) {
            super(context, attrs);
            init();
        }   
    
        public TintableButton(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
            init();
        }
    
        private void init() {
            mIsSelected = false;
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            if (event.getAction() == MotionEvent.ACTION_DOWN && !mIsSelected) {
                setColorFilter(0x99000000);
                mIsSelected = true;
            } else if (event.getAction() == MotionEvent.ACTION_UP && mIsSelected) {
                setColorFilter(Color.TRANSPARENT);
                mIsSelected = false;
            }
    
            return super.onTouchEvent(event);
        }
    }
    

    It's not finished but works well as a proof of concept.

    0 讨论(0)
  • 2021-01-31 11:43

    I think this solution is simple!

    Step 1: Create res/drawable/dim_image_view.xml

    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:state_focused="true" android:drawable="@drawable/dim_image_view_normal"/> <!-- focused -->
        <item android:state_pressed="true" android:drawable="@drawable/dim_image_view_pressed"/> <!-- pressed -->
        <item android:drawable="@drawable/dim_image_view_normal"/> <!--default -->
    </selector>
    

    Step 2: Create res/drawable/dim_image_view_normal.xml

    <?xml version="1.0" encoding="utf-8"?>
    <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
        <item><bitmap android:src="@mipmap/your_icon"/></item>
    </layer-list>
    

    Step 3: Create res/drawable/dim_image_view_pressed.xml

    <?xml version="1.0" encoding="utf-8"?>
    <layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
        <item><bitmap android:src="@mipmap/your_icon" android:alpha="0.5"></bitmap></item>
    </layer-list>
    

    Step 4: Try setting the image in xml layout as:

    android:src="@drawable/dim_image_view"
    
    0 讨论(0)
  • 2021-01-31 11:47

    Your answer was excellent :)

    However instead of creating a button object, I am only calling an OnTouchlistener to change the state of every view.

    public boolean onTouch(View v, MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            Drawable background =  v.getBackground();
            background.setColorFilter(0xBB000000, PorterDuff.Mode.SCREEN);
            v.setBackgroundDrawable(background);
        } else if (event.getAction() == MotionEvent.ACTION_UP) {
            Drawable background =  v.getBackground();
            background.setColorFilter(null);
            v.setBackgroundDrawable(background);
        }
    
        return true;
    
    }
    

    Gives the same results though

    0 讨论(0)
  • 2021-01-31 11:48

    You can use a class I've created https://github.com/THRESHE/TintableImageButton Not exactly the best solution but it works.

    0 讨论(0)
  • 2021-01-31 11:51

    You can combine StateListDrawable and LayerDrawable for this.

    public Drawable getDimmedDrawable(Drawable drawable) {
            Resources resources = getContext().getResources();
            StateListDrawable stateListDrawable = new StateListDrawable();
            LayerDrawable layerDrawable = new LayerDrawable(new Drawable[]{
                    drawable,
                    new ColorDrawable(resources.getColor(R.color.translucent_black))
            });
            stateListDrawable.addState(new int[]{android.R.attr.state_pressed}, layerDrawable);
            stateListDrawable.addState(new int[]{android.R.attr.state_focused}, layerDrawable);
            stateListDrawable.addState(new int[]{android.R.attr.state_selected}, layerDrawable);
            stateListDrawable.addState(new int[]{}, drawable);
            return stateListDrawable;
    }
    

    I assume our colors.xml looks like this

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <color name="translucent_black">#80000000</color>
    </resources>
    
    0 讨论(0)
  • 2021-01-31 12:02

    I think this solution is simple enough:

        final Drawable drawable = ... ;
        final int darkenValue = 0x3C000000;
        mButton.setOnTouchListener(new OnTouchListener() {
            Rect rect;
            boolean hasColorFilter = false;
    
            @Override
            public boolean onTouch(final View v, final MotionEvent motionEvent) {
                switch (motionEvent.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        rect = new Rect(v.getLeft(), v.getTop(), v.getRight(), v.getBottom());
                        drawable.setColorFilter(darkenValue, Mode.DARKEN);
                        hasColorFilter = true;
                        break;
                    case MotionEvent.ACTION_MOVE:
                        if (rect.contains(v.getLeft() + (int) motionEvent.getX(), v.getTop()
                                + (int) motionEvent.getY())) {
                            if (!hasColorFilter)
                                drawable.setColorFilter(darkenValue, Mode.DARKEN);
                            hasColorFilter = true;
                        } else {
                            drawable.setColorFilter(null);
                            hasColorFilter = false;
                        }
                        break;
                    case MotionEvent.ACTION_UP:
                    case MotionEvent.ACTION_CANCEL:
                        drawable.setColorFilter(null);
                        hasColorFilter = false;
                        break;
                }
                return false;
            }
        });
    
    0 讨论(0)
提交回复
热议问题