开发者

Long press definition at XML layout, like android:onClick does

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开发者_StackOverflow中文版.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.


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:

  • I have learned how to do this from this post: http://kevindion.com/2011/01/custom-xml-attributes-for-android-widgets/
  • Snippet for constructor with slight modifications was taken from original android View class.


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.


(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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜