2012-10-30 10 views
51

के ड्रायबल दाएं के लिए ऑनक्लिक लिस्टनर सेट करना मेरे ऐप में मेरे पास EditText दाएं तरफ एक खोज आइकन है। मैंने नीचे दिए गए कोड का इस्तेमाल किया।एडिटटेक्स्ट

<EditText 
     android:id="@+id/search" 
     android:layout_width="0dp" 
     android:layout_height="match_parent" 
     android:layout_margin="4dip" 
     android:layout_weight="1" 
     android:background="@drawable/textfield_search1" 
     android:drawableLeft="@drawable/logo" 
     android:drawableRight="@drawable/search_icon" 
     android:hint="Search Anything..." 
     android:padding="4dip" 
     android:singleLine="true" /> 

मैं EditText के अधिकार drawable करने के लिए सौंपा खोज आइकन छवि के लिए onClickListner सेट करना चाहते हैं। यह कैसे संभव है ?

+1

dupplicate http://stackoverflow.com/questions/3554377/handling-click-events-on -a-drawable-in-an-edittext – Tobrun

+0

Android प्रदान किए गए सरल समाधान का उपयोग API http://stackoverflow.com/a/26269435/185022 :-) –

+0

यह सबसे अच्छा जवाब है http://stackoverflow.com/a/37032927/34630 9 – JPM

उत्तर

74
public class CustomEditText extends EditText { 

    private Drawable drawableRight; 
    private Drawable drawableLeft; 
    private Drawable drawableTop; 
    private Drawable drawableBottom; 

    int actionX, actionY; 

    private DrawableClickListener clickListener; 

    public CustomEditText (Context context, AttributeSet attrs) { 
     super(context, attrs); 
     // this Contructure required when you are using this view in xml 
    } 

    public CustomEditText(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle);   
    } 

    protected void onDraw(Canvas canvas) { 
     super.onDraw(canvas); 

    } 

    @Override 
    protected void onSizeChanged(int w, int h, int oldw, int oldh) { 
     super.onSizeChanged(w, h, oldw, oldh); 
    } 

    @Override 
    public void setCompoundDrawables(Drawable left, Drawable top, 
      Drawable right, Drawable bottom) { 
     if (left != null) { 
      drawableLeft = left; 
     } 
     if (right != null) { 
      drawableRight = right; 
     } 
     if (top != null) { 
      drawableTop = top; 
     } 
     if (bottom != null) { 
      drawableBottom = bottom; 
     } 
     super.setCompoundDrawables(left, top, right, bottom); 
    } 

    @Override 
    public boolean onTouchEvent(MotionEvent event) { 
     Rect bounds; 
     if (event.getAction() == MotionEvent.ACTION_DOWN) { 
      actionX = (int) event.getX(); 
      actionY = (int) event.getY(); 
      if (drawableBottom != null 
        && drawableBottom.getBounds().contains(actionX, actionY)) { 
       clickListener.onClick(DrawablePosition.BOTTOM); 
       return super.onTouchEvent(event); 
      } 

      if (drawableTop != null 
        && drawableTop.getBounds().contains(actionX, actionY)) { 
       clickListener.onClick(DrawablePosition.TOP); 
       return super.onTouchEvent(event); 
      } 

      // this works for left since container shares 0,0 origin with bounds 
      if (drawableLeft != null) { 
       bounds = null; 
       bounds = drawableLeft.getBounds(); 

       int x, y; 
       int extraTapArea = (int) (13 * getResources().getDisplayMetrics().density + 0.5); 

       x = actionX; 
       y = actionY; 

       if (!bounds.contains(actionX, actionY)) { 
        /** Gives the +20 area for tapping. */ 
        x = (int) (actionX - extraTapArea); 
        y = (int) (actionY - extraTapArea); 

        if (x <= 0) 
         x = actionX; 
        if (y <= 0) 
         y = actionY; 

        /** Creates square from the smallest value */ 
        if (x < y) { 
         y = x; 
        } 
       } 

       if (bounds.contains(x, y) && clickListener != null) { 
        clickListener 
          .onClick(DrawableClickListener.DrawablePosition.LEFT); 
        event.setAction(MotionEvent.ACTION_CANCEL); 
        return false; 

       } 
      } 

      if (drawableRight != null) { 

       bounds = null; 
       bounds = drawableRight.getBounds(); 

       int x, y; 
       int extraTapArea = 13; 

       /** 
       * IF USER CLICKS JUST OUT SIDE THE RECTANGLE OF THE DRAWABLE 
       * THAN ADD X AND SUBTRACT THE Y WITH SOME VALUE SO THAT AFTER 
       * CALCULATING X AND Y CO-ORDINATE LIES INTO THE DRAWBABLE 
       * BOUND. - this process help to increase the tappable area of 
       * the rectangle. 
       */ 
       x = (int) (actionX + extraTapArea); 
       y = (int) (actionY - extraTapArea); 

       /**Since this is right drawable subtract the value of x from the width 
       * of view. so that width - tappedarea will result in x co-ordinate in drawable bound. 
       */ 
       x = getWidth() - x; 

       /*x can be negative if user taps at x co-ordinate just near the width. 
       * e.g views width = 300 and user taps 290. Then as per previous calculation 
       * 290 + 13 = 303. So subtract X from getWidth() will result in negative value. 
       * So to avoid this add the value previous added when x goes negative. 
       */ 

       if(x <= 0){ 
        x += extraTapArea; 
       } 

       /* If result after calculating for extra tappable area is negative. 
       * assign the original value so that after subtracting 
       * extratapping area value doesn't go into negative value. 
       */    

       if (y <= 0) 
        y = actionY;     

       /**If drawble bounds contains the x and y points then move ahead.*/ 
       if (bounds.contains(x, y) && clickListener != null) { 
        clickListener 
          .onClick(DrawableClickListener.DrawablePosition.RIGHT); 
        event.setAction(MotionEvent.ACTION_CANCEL); 
        return false; 
       } 
       return super.onTouchEvent(event); 
      }   

     } 
     return super.onTouchEvent(event); 
    } 

    @Override 
    protected void finalize() throws Throwable { 
     drawableRight = null; 
     drawableBottom = null; 
     drawableLeft = null; 
     drawableTop = null; 
     super.finalize(); 
    } 

    public void setDrawableClickListener(DrawableClickListener listener) { 
     this.clickListener = listener; 
    } 

} 

इसके अलावा

public interface DrawableClickListener { 

    public static enum DrawablePosition { TOP, BOTTOM, LEFT, RIGHT }; 
    public void onClick(DrawablePosition target); 
    } 

फिर भी अगर यू की जरूरत के साथ एक अंतरफलक बनाएं कोई मदद, टिप्पणी

गतिविधि फ़ाइल में दृश्य पर drawableClickListener भी सेट करें।

editText.setDrawableClickListener(new DrawableClickListener() { 


     public void onClick(DrawablePosition target) { 
      switch (target) { 
      case LEFT: 
       //Do something here 
       break; 

      default: 
       break; 
      } 
     } 

    }); 
+0

को संभालने जैसी चीजें हैं, मैंने एडिटेक्स्ट को कॉलबैक के पैरामीटर के रूप में भी पारित किया होगा। लेकिन एक अच्छा जवाब कभी कम नहीं है। – st0le

+0

मैंने कस्टम संपादन टेक्स्ट बनाया है। अगर मैं ऑन टचमोवमेंट विधि पर जा रहा हूं तो कहीं भी स्पर्श करता हूं। लेकिन "अगर (bounds.contains (एक्स, वाई) && clickListener = अशक्त!) यहां के लिए चला जाता है कभी नहीं { clickListener .onClick (DrawableClickListener.DrawablePosition.RIGHT); event.setAction (MotionEvent.ACTION_CANCEL); वापसी झूठी; } " – user965071

+0

कृपया संपादित उत्तर देखें। – Hardik4560

0

चाल नीचे का उपयोग करें:

  • अपने आइकन के साथ एक छवि बनाएं बटन और पारदर्शी होने के लिए अपनी पृष्ठभूमि का रंग निर्धारित किया है।
  • EditText पर छवि बटन लगाएं
  • बटन के 'onclic'k श्रोता को लागू करें अपने कार्य निष्पादित करने के लिए
+0

क्या होगा यदि संपादन टेक्स्ट का आकार बढ़ता है?, यदि मेरे पास कई संपादन टेक्स्ट हैं, जिसके लिए यह आवश्यक है, जो आमतौर पर होता है। – Hardik4560

+0

आपको सवाल समझने की जरूरत है! वह वैकल्पिक समाधान नहीं मांग रहा है। – Nizzy

+0

इस दृष्टिकोण के साथ समस्या यह है कि जैसे ही आप EditText पर टेक्स्ट आकार बदलना शुरू करते हैं। आपको लगता है कि यह केवल डेवलपर की तरफ है, लेकिन यह तब तक नहीं है जब तक डिवाइस में सेटिंग्स में टेक्स्ट आकार नहीं है। आप संपादन टेक्स्ट पर sp के बजाय डीपी का उपयोग करके इससे बच सकते हैं लेकिन यह चीजों को और भी खराब बनाता है। अन्य समस्याएं मल्टीलाइन एडिटटेक्स को संभालने जैसी चीजें हैं – Sotti

6

आप सही छवि के लिए उपयोग जहाँ तक मेरी जानकारी की जरूरत नहीं है, जब तक आप onTouch ईवेंट ओवरराइड करें। मैं एक editText और एक imageView के साथ एक RelativeLayout उपयोग करने के लिए सुझाव है, और नीचे वाले चित्र को देखने से अधिक OnClickListener सेट:

<RelativeLayout 
     android:id="@+id/rlSearch" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:background="@android:drawable/edit_text" 
     android:padding="5dip" > 

     <EditText 
      android:id="@+id/txtSearch" 
      android:layout_width="match_parent" 

      android:layout_height="wrap_content" 
      android:layout_centerVertical="true" 
      android:layout_toLeftOf="@+id/imgSearch" 
      android:background="#00000000" 
      android:ems="10"/> 

     <ImageView 
      android:id="@+id/imgSearch" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:layout_alignParentRight="true" 
      android:layout_centerVertical="true" 
      android:src="@drawable/btnsearch" /> 
    </RelativeLayout> 
+0

इस दृष्टिकोण के साथ समस्या यह है कि जैसे ही आप EditText पर टेक्स्ट आकार बदलना शुरू करते हैं। आपको लगता है कि यह केवल डेवलपर की तरफ है, लेकिन यह तब तक नहीं है जब तक डिवाइस में सेटिंग्स में टेक्स्ट आकार नहीं है। आप संपादन टेक्स्ट पर sp के बजाय डीपी का उपयोग करके इससे बच सकते हैं लेकिन यह चीजों को और भी खराब बनाता है। अन्य समस्याएं मल्टीलाइन एडिटटेक्स – Sotti

-1

मुझे पता है कि यह काफी पुराना है, लेकिन मुझे हाल ही में कुछ ऐसा ही करना पड़ा, और एक बहुत ही सरल समाधान के साथ आया।

यह निम्न चरणों का पालन करने पर निर्भर करता:

  1. कि EditText और छवि
  2. उपवर्ग FrameLayout शामिल एक एक्सएमएल लेआउट बनाएँ और एक्सएमएल लेआउट
  3. बढ़ क्लिक श्रोता और किसी भी अन्य के लिए कोड जोड़ें व्यवहार जो आप चाहते हैं ... क्लिक या किसी अन्य गन्दा कोड की स्थिति के बारे में चिंता किए बिना।

पूर्ण उदाहरण के लिए यह पोस्ट देखें: Handling click events on a drawable within an EditText

21

यह पहले से ही उत्तर दिया गया है लेकिन मैं इसे सरल बनाने के लिए एक अलग तरह की कोशिश की।

विचार EditText के दाईं तरफ एक ImageButton डालने और इसे करने के लिए नकारात्मक मार्जिन इतना होने कि EditText यह देखने के लिए बटन की तरह EditText में होने की पुष्टि करने ImageButton में बहती उपयोग कर रहा है

enter image description here

<LinearLayout 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:orientation="horizontal"> 
     <EditText 
      android:id="@+id/editText" 
      android:layout_weight="1" 
      android:layout_width="0dp" 
      android:layout_height="wrap_content" 
      android:hint="Enter Pin" 
      android:singleLine="true" 
      android:textSize="25sp" 
      android:paddingRight="60dp" 
      /> 
     <ImageButton 
      android:id="@+id/pastePin" 
      android:layout_marginLeft="-60dp" 
      style="?android:buttonBarButtonStyle" 
      android:paddingBottom="5dp" 
      android:src="@drawable/ic_action_paste" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" /> 
    </LinearLayout> 

इसके अलावा, जैसा कि ऊपर दिखाए गए, तो आप EditText में इसी तरह की चौड़ाई का एक paddingRight उपयोग करें यदि आप पाठ यह ImageButton से अधिक प्रवाहित होना करने के लिए नहीं करना चाहते हैं कर सकते हैं।

मैंने एंड्रॉइड-स्टूडियो के लेआउट डिजाइनर की मदद से मार्जिन आकार का अनुमान लगाया और यह सभी स्क्रीन आकारों में समान दिखता है। अन्यथा आप ImageButton की चौड़ाई की गणना कर सकते हैं और मार्जिन प्रोग्रामेटिक रूप से सेट कर सकते हैं।

+0

यह स्मार्ट काम –

+0

यह आसान चीजें है जो सर्वोत्तम काम करती है। – DariusL

+1

यह एकल खींचने योग्य –

167

सरल समाधान, उपयोग तरीकों कि एंड्रॉयड पहले से ही दे दिया है, बल्कि पुनर्रचना से wheeeeeeeeeel :-)

editComment.setOnTouchListener(new OnTouchListener() { 
     @Override 
     public boolean onTouch(View v, MotionEvent event) { 
      final int DRAWABLE_LEFT = 0; 
      final int DRAWABLE_TOP = 1; 
      final int DRAWABLE_RIGHT = 2; 
      final int DRAWABLE_BOTTOM = 3; 

      if(event.getAction() == MotionEvent.ACTION_UP) { 
       if(event.getRawX() >= (editComment.getRight() - editComment.getCompoundDrawables()[DRAWABLE_RIGHT].getBounds().width())) { 
        // your action here 

       return true; 
       } 
      } 
      return false; 
     } 
    }); 
+0

त्रुटि: java.lang.ArrayIndexOutOfBoundsException: length = 4; इंडेक्स = 2130837593 – user2273146

+1

@ user2273146 यदि आपकी लंबाई 4 है तो आपकी अनुक्रमणिका 3 होनी चाहिए। क्योंकि लंबाई 1 से शुरू होती है, 0 लंबाई नहीं है लेकिन यदि लंबाई 1 है तो सूचकांक 0 –

+3

मेरे लिए काम करता है। बाएं आइकन दबाए जाने के लिए कोड यहां दिया गया है ... अगर (event.getRawX() <= (संपादित करेंमेशन.get कॉम्पाउंड ड्रावेबल्स() [DRAWABLE_LEFT] .getBounds() चौड़ाई()) – kwh

संबंधित मुद्दे