17

There is any way to define into XML layout longKeyLongPress definition like onClick does ?.

i.e this is my view

<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:text="Line 1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/message"
android:textSize="15dip"
android:textStyle="bold"
android:textColor="@color/colorblue"
android:shadowDy="1.0"
android:shadowDx="1.0"
android:shadowRadius="1.0"
android:shadowColor="#ffffffff"
android:paddingLeft="10dip"
android:paddingRight="10dip"
android:paddingTop="5dip"
android:lineSpacingExtra="3dip"
android:lineSpacingMultiplier="1.1"
android:singleLine="false"
android:autoLink="web|email|phone|map|all"

android:onClick="clickHandler"
android:clickable="true"

 />

I want something like before but reacting to longpress event.

Note:

  • I don't want to add listener from my code.

  • I tried with android:longClickable.

vsm
  • 3,373
  • 2
  • 25
  • 36

3 Answers3

16

The attribute is not defined, however you can implement it.

  1. Extend TextView and let's call it MyTextView.
  2. Then add file attrs.xml in res/values/ with following content:

    <xml version="1.0" encoding="utf-8"?>
    <resources>
        <declare-styleable name="MyTextView">
            <attr name="onKeyLongPress" format="string"/>
        </declare-styleable>
    </resources>
    
  3. In MyTextView constructor add logic to read data from xml:

    public MyTextView(final Context context, final AttributeSet attrs) {
    super(context, attrs);
    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyTextView);
    
    for (int i = 0; i < a.getIndexCount(); ++i)
    {
        int attr = a.getIndex(i);
        switch (attr)
        {
            case R.styleable.MyTextView_onKeyLongPress: {
                if (context.isRestricted()) {
                    throw new IllegalStateException("The "+getClass().getCanonicalName()+":onKeyLongPress attribute cannot "
                            + "be used within a restricted context");
                }
    
                final String handlerName = a.getString(attr);
                if (handlerName != null) {
                    setOnLongClickListener(new OnLongClickListener() {
                        private Method mHandler;
    
                        @Override
                        public boolean onLongClick(final View p_v) {
                            boolean result = false;
                            if (mHandler == null) {
                                try {
                                    mHandler = getContext().getClass().getMethod(handlerName, View.class);
                                } catch (NoSuchMethodException e) {
                                    int id = getId();
                                    String idText = id == NO_ID ? "" : " with id '"
                                            + getContext().getResources().getResourceEntryName(
                                                id) + "'";
                                    throw new IllegalStateException("Could not find a method " +
                                            handlerName + "(View) in the activity "
                                            + getContext().getClass() + " for onKeyLongPress handler"
                                            + " on view " + MyTextView.this.getClass() + idText, e);
                                }
                            }
    
                            try {
                                mHandler.invoke(getContext(), MyTextView.this);
                                result = true;
                            } catch (IllegalAccessException e) {
                                throw new IllegalStateException("Could not execute non "
                                        + "public method of the activity", e);
                            } catch (InvocationTargetException e) {
                                throw new IllegalStateException("Could not execute "
                                        + "method of the activity", e);
                            }
                            return result;
                        }
                    });
                }
                break;
            }
            default: 
                break;
        }
    }
    a.recycle();
    
    }
    
  4. Use new attribute in your layout xml:

    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:custom="http://schemas.android.com/apk/res/res-auto"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical"
        >
    
        <your.package.MyTextView
            android:id="@+id/theId"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            custom:onKeyLongPress="myDoSomething"
        />
        <!-- Other stuff -->
    </LinearLayout>
    

Credits:

EmmanuelMess
  • 1,025
  • 2
  • 17
  • 31
Aleksander Gralak
  • 1,509
  • 10
  • 26
6

Looking at the current documentation, such an XML parameter does not currently exist. The longClickable is a boolean parameter to define simply whether a View is responds to long clicks or not.

Maximus
  • 8,351
  • 3
  • 29
  • 37
  • 1
    Just been looking at the docs myself and came to the same conclusion, i.e., there doesn't seem to be an XML attribute to set the onLongClickListener and it has to be done with code. – Squonk Apr 18 '11 at 16:58
  • None that I'm aware of... you will have to do what you do not want to do... add the listener to your code. – Maximus Apr 18 '11 at 17:48
3

(10 years later, might be useful to others)

When using Databinding and MVVM you can write a Bindingadapter that works as intended:

   @BindingAdapter("android:onLongClick")
   fun setOnLongClickListener(view: View,block : () -> Unit) {
        view.setOnLongClickListener {
            block()
            return@setOnLongClickListener true
        }
    }

You can then use it like: android:onLongClick="@{() -> vm.yourFunction()}"

You can also return the function and change Unit to boolean if you indend to return false in some cases

Merthan Erdem
  • 5,598
  • 2
  • 22
  • 29