2011-11-07 21 views
16

जिस ऐप पर मैं वर्तमान में काम कर रहा हूं वह बटन के रूप में बहुत सारे छवि दृश्यों का उपयोग करता है। इन बटनों पर ग्राफिक्स बटन के किनारों को फीका करने के लिए अल्फा चैनल का उपयोग करते हैं और उन्हें अनियमित दिखते हैं। वर्तमान में, हमें प्रत्येक बटन के लिए 2 ग्राफिक्स (चयनित/केंद्रित/दबाए गए राज्य के लिए और दूसरा डिफ़ॉल्ट अचयनित स्थिति के लिए) उत्पन्न करना होगा और प्रत्येक बटन के लिए एक XML फ़ाइल में परिभाषित एक StateListDrawable का उपयोग करना होगा।स्पर्श पर टिंट/मंद खींचने योग्य

हालांकि यह ठीक काम करता है, यह बेहद अपर्याप्त लगता है क्योंकि सभी चयनित ग्राफिक्स अचयनित बटनों के बस रंग वाले संस्करण हैं। इन्हें उत्पादन करने में समय लगता है (हालांकि थोड़ा) और अंतिम एपीके में जगह लेना। ऐसा लगता है कि इसे स्वचालित रूप से एक आसान तरीका होना चाहिए।

ऐसा लगता है कि सही समाधान, प्रत्येक बटन के लिए ImageViews का उपयोग करना है और इसकी रंगीन विशेषता को रंगस्टेटलिस्ट में निर्दिष्ट करना है। इस दृष्टिकोण का लाभ यह है कि सभी बटनों के लिए केवल एक ही एक्सएमएल कलरस्टेटलिस्ट की आवश्यकता होती है (जो एक ही टिंट साझा करते हैं)। हालांकि यह काम नहीं करता है। जैसा कि here का उल्लेख किया गया है, छवि दृश्य एक संख्याफॉर्मेट अपवाद फेंकता है जब टिंट को प्रदान किया गया मान एक रंग के अलावा कुछ भी है।

मेरा अगला प्रयास चयनित ड्रॉइंग के लिए लेयर ड्रायबल का उपयोग करना था। परत सूची के अंदर, हमारे पास अर्ध-पारदर्शी आयताकार द्वारा ढेर स्टैक के नीचे मूल छवि होगी। यह बटन ग्राफिक के ठोस भागों पर काम किया। हालांकि किनारों को पूरी तरह से पारदर्शी माना जाता था, अब शीर्ष परत के समान रंग थे।

क्या किसी को भी इस समस्या का सामना करना पड़ा है और उचित समाधान मिला है? मैं एक्सएमएल दृष्टिकोणों के साथ रहना चाहता हूं लेकिन संभवतः एक साधारण छवि दृश्य उप-वर्ग को कोडित करूंगा जो कोड में आवश्यक टिनटिंग करेगा।

उत्तर

6

आप इसके लिए StateListDrawable और LayerDrawable जोड़ सकते हैं।

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; 
} 

मैं अपने रंग मानता हूं।एक्सएमएल तरह लग रहा है इस

<?xml version="1.0" encoding="utf-8"?> 
<resources> 
    <color name="translucent_black">#80000000</color> 
</resources> 
+0

मैं इसे 9-पैच फ़ाइलों के लिए कैसे अच्छी तरह से काम कर सकता हूं, ताकि छवि के पूरे गैर-पारदर्शी क्षेत्र को स्पर्श घटनाओं पर अंधेरा कर दिया जा सके? वर्तमान में यह 9-पैच छवियों के साथ क्या करता है केवल उस भाग को बदलना है जिसे छवि की सामग्री के रूप में परिभाषित किया गया है, न कि पूरी छवि स्वयं ... –

17

उन लोगों के लिए जिन्होंने समान आवश्यकता का सामना किया है, कोड में इसे हल करना काफी साफ है। यहां एक नमूना है:

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); 
    } 
} 

यह समाप्त नहीं हुआ है लेकिन अवधारणा के सबूत के रूप में अच्छी तरह से काम करता है।

+0

यह आईएमएचओ, सबसे अच्छा समाधान है, और स्वीकार्य उत्तर होना चाहिए, क्योंकि यह अच्छी तरह से काम करता है, और फिर से उपयोग करने योग्य घटक बनाता है जिसे किसी छवि लेआउट को प्रतिस्थापित करने के लिए किसी लेआउट में उपयोग किया जा सकता है। अच्छा समाधान! – GreyBeardedGeek

+1

धन्यवाद, बहुत अच्छा! मैंने ऑन टचएवेंट को इस तरह थोड़ा संशोधित किया: और अगर ((event.getAction() == मोशनवेन्ट.एक्शन_UP || event.getAction() == मोशनइवेंट.एक्शन_CANCEL) && mss चयनित) ' यह सुनिश्चित करता है कि टिंट गायब हो जाता है जब उपयोगकर्ता बटन रखता है, तो अपनी अंगुली को बाहर निकाल देता है और रिलीज़ करता है। – Jaykob

+0

'init()' केवल 'टिंटेबल बटन (संदर्भ संदर्भ, विशेषता एसईटी, int defStyle)' कन्स्ट्रक्टर –

6

Your answer उत्कृष्ट था :)

हालांकि बजाय एक बटन वस्तु बनाने के बजाय, मैं केवल एक OnTouchlistener बोल रहा हूँ हर दृश्य की स्थिति बदलने।

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; 

} 

ही परिणाम हालांकि

+2

में भी कहा जाना चाहिए जो यह भी काम करता है। आवश्यक वर्गों को विस्तारित करने का कारण यह है कि कक्षा तैयार होने के बाद मैं इसे लेआउट एक्सएमएल में रख सकता हूं। इस तरह से कोड जो इन टिंटेबल विगेट्स का उपयोग करता है वह कोड से अलग नहीं होता जो मानक घटकों का उपयोग करता है। – zienkikk

1

मैं भी अनियमित देख बटन और रंग की जरूरत देता है। अंत में, मैंने बस अपनी ImageButton पृष्ठभूमि के रूप में एक राज्य रंगसूची होने का सहारा लिया। इंप्रेशन देता है कि बटन रंग प्रेस पर बदल रहा है और बहुत सरल और कम गणना गहन है। मुझे पता है कि यह बिल्कुल एक टिंट नहीं है, लेकिन यह देता है कि यह उपयोगकर्ता को आवश्यक दृश्य प्रतिक्रिया देता है जो आमतौर पर एक क्षणिक क्षण होता है।

<?xml version="1.0" encoding="utf-8"?> 
<selector xmlns:android="http://schemas.android.com/apk/res/android" > 
    <item 
     android:state_pressed="true" 
     android:drawable="@android:color/darker_gray" /> 
    <item android:drawable="@android:color/transparent" /> 
</selector> 
1

आप एक वर्ग मैं https://github.com/THRESHE/TintableImageButton नहीं वास्तव में सबसे अच्छा समाधान बना लिया है उपयोग कर सकते हैं, लेकिन यह काम करता है।

1

Your answer भी उत्कृष्ट था;)

मैं थोड़ा संशोधित कर रहा हूँ, यह आप इस तरह परिणाम दे देंगे:

button_normalbutton_pressed

Rect rect; 
Drawable background; 
boolean hasTouchEventCompleted = false; 

@Override 
public boolean onTouch(View v, MotionEvent event) { 
    if (event.getAction() == MotionEvent.ACTION_DOWN) { 
     rect = new Rect(v.getLeft(), v.getTop(), v.getRight(), 
       v.getBottom()); 
     hasTouchEventCompleted = false; 
     background = v.getBackground(); 
     background.setColorFilter(0x99c7c7c7, 
       android.graphics.PorterDuff.Mode.MULTIPLY); 
     v.setBackgroundDrawable(background); 
    } else if (event.getAction() == MotionEvent.ACTION_UP 
      && !hasTouchEventCompleted) { 
     background.setColorFilter(null); 
     v.setBackgroundDrawable(background); 

    } else if (event.getAction() == MotionEvent.ACTION_MOVE) { 
     if (!rect.contains(v.getLeft() + (int) event.getX(), v.getTop() 
       + (int) event.getY())) { 
      // User moved outside bounds 
      background.setColorFilter(null); 
      v.setBackgroundDrawable(background); 
      hasTouchEventCompleted = true; 
     } 
    } 


    //Must return false, otherwise you need to handle Click events yourself. 
    return false; 
} 
0

मुझे लगता है कि यह समाधान काफी सरल है:

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; 
     } 
    }); 
2

मुझे लगता है कि यह समाधान सरल है!

चरण 1: रेस बनाएं/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> 

चरण 2: 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> 

चरण 3 बनाएँ: res/drawable/dim_image_view_pressed बनाएँ। एक्सएमएल

<?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> 

चरण 4: के रूप में XML लेआउट में छवि सेट करके देखें:

android:src="@drawable/dim_image_view" 
संबंधित मुद्दे