改编自Trinea的CompoundDrawablesTextView,thanks

概述

在android的TextView中我们可以通过setCompoundDrawables(Drawable left, Drawable top, Drawable right, Drawable bottom)
或者android:drawableLeft系列属性
来给TextView的周围设置Drawable,省去了在旁边写一个ImageView而造成的多了一层布局.

但是,并没有对外提供触控事件,而有时我们却需要给这样一个drawable设置点击事件

实现原理

要实现这样一个需求,其实思路很简单,就是重写onTouchEvent,并判定点击区域是否在图标范围内,然后回调相应的点击事件即可.

核心代码:

 @Override public boolean onTouchEvent(MotionEvent event) {        // 在event为actionDown时标记用户点击是否在相应的图片范围内        if (event.getAction() == MotionEvent.ACTION_DOWN) {            resetTouchStatus();            if (mDrawableClickListener != null) {                mIsLeftTouched = touchLeftDrawable(event);                mIsTopTouched = touchTopDrawable(event);                mIsRightTouched = touchRightDrawable(event);                mIsBottomTouched = touchBottomDrawable(event);            }        }        return super.onTouchEvent(event);    }    @Override public void onClick(View v) {        /**         * 按照左上右下的顺序响应第一个点击范围内的Drawable         */        if (mDrawableClickListener != null) {            if (mIsLeftTouched) {                mDrawableClickListener.onClick(DrawableClickListener.DrawablePosition.LEFT);            } else if (mIsTopTouched) {                mDrawableClickListener.onClick(DrawableClickListener.DrawablePosition.TOP);            } else if (mIsRightTouched) {                mDrawableClickListener.onClick(DrawableClickListener.DrawablePosition.RIGHT);            } else if (mIsBottomTouched) {                mDrawableClickListener.onClick(DrawableClickListener.DrawablePosition.BOTTOM);            } else {                mDrawableClickListener.onClick(DrawableClickListener.DrawablePosition.TEXT);            }        }    }

本实例代码见:
CompoundDrawablesTextView@[Github]

原理剖析

rect对象所表示一个矩形区域,其有一个contains方法,只要我们把坐标传进去,就可以通过返回值来得到该坐标是否在该范围内 ,因此我们可以通过这个方法来进行判断我们所触摸的是哪一个Drawable或者是TextView的text

如下判断触摸的是否是左边的Drawable

   /** touch左边的Drawable     *     * @param event     * @return 是否在touch范围内     */    private boolean touchLeftDrawable(MotionEvent event) {        if (mLeftDrawable == null) {            return false;        }        // 计算图片点击可响应的范围,计算方法见        http://trinea.iteye.com/blog/1562388        int drawHeight = mLeftDrawable.getIntrinsicHeight();        int drawWidth = mLeftDrawable.getIntrinsicWidth();        int topBottomDis = (mTopDrawable == null ? 0 : mTopDrawable.getIntrinsicHeight())                - (mBottomDrawable == null ? 0 : mBottomDrawable.getIntrinsicHeight());        double imageCenterY = 0.5 * (this.getHeight() + topBottomDis);        Rect imageBounds = new Rect(this.getCompoundDrawablePadding() - mLazyX,                (int) (imageCenterY - 0.5 * drawHeight - mLazyY), this.getCompoundDrawablePadding()                + drawWidth + mLazyX,                (int) (imageCenterY + 0.5 * drawHeight + mLazyY));        return imageBounds.contains((int) event.getX(), (int) event.getY());    }

这里面有两个变量mLazyX,mLazyY,是用来扩大响应范围的,就是我们常说的热区。

Theme

这里我们通过theme来该改变控件的默认appearance,如果不了解通过theme改变控件属性可参考:
Android中的主题和样式

  • attrs.xml
    <attr name="Compound_Drawables_TextView_Style" format="reference" />
  • style.xml
<?xml version="1.0" encoding="utf-8"?><resources>   <style name="Theme.CompoundDrawablesTextViewStyleDefault" parent="android:Theme">        <item name="Compound_Drawables_TextView_Style">@style/Widget.cdtStyle   style>   <style name="Widget" />    <style name="Widget.cdtStyle">        <item name="android:gravity">centeritem>       <item name="android:textColor">#fabitem>    style>resources>
  • 应用
public CompoundDrawablesTextView(Context context, AttributeSet attrs) {        this(context, attrs, R.attr.Compound_Drawables_TextView_Style);    }

测试

  • customstyle.xml
<style name="AppTheme.NoActionBar.Compound_Default"><item name="Compound_Drawables_TextView_Style">@style/Widget.cdtStyle.CustomcdtStyle  style>  <style name="Widget.cdtStyle.CustomcdtStyle">      <item name="android:drawablePadding">10dpitem>       <item name="android:text">"CDT"item>      style>
  • manifes.xml && layout.xml
<activity android:name="com.bobomee.blogdemos.ui.activity.CompoundDrawablesTextViewActivity"android:theme="@style/AppTheme.NoActionBar.Compound_Default" />                      <?xml version="1.0" encoding="utf-8"?><com.bobomee.commonlibrary.widget.CompoundDrawablesTextView xmlns:android="http://schemas.android.com/apk/res/android"              android:layout_width="wrap_content"              android:id="@+id/textWithImage"              android:drawableLeft="@mipmap/ic_launcher"              android:layout_height="wrap_content"/>
  • java code
 @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.compound_drawables_textview_layout);        CompoundDrawablesTextView textWithImage = (CompoundDrawablesTextView)this.findViewById(R.id.textWithImage);        textWithImage.setDrawableClickListener(new ImageClickListener());    }    class ImageClickListener implements CompoundDrawablesTextView.DrawableClickListener {        @Override        public void onClick(DrawablePosition position) {            switch (position) {                case LEFT:                    // 左边图片被点击的响应                    Toast.makeText(CompoundDrawablesTextViewActivity.this, "left", Toast.LENGTH_SHORT).show();                    break;                case RIGHT:                    // 右边图片被点击的响应                    Toast.makeText(CompoundDrawablesTextViewActivity.this, "right", Toast.LENGTH_SHORT).show();                    break;                case BOTTOM:                    // 底部图片被点击的响应                    Toast.makeText(CompoundDrawablesTextViewActivity.this, "bottom", Toast.LENGTH_SHORT).show();                    break;                case TOP:                    // 上边图片被点击的响应                    Toast.makeText(CompoundDrawablesTextViewActivity.this, "top", Toast.LENGTH_SHORT).show();                    break;                case TEXT:                    Toast.makeText(CompoundDrawablesTextViewActivity.this, "TEXT", Toast.LENGTH_SHORT).show();                    break;                default:                    break;            }        }    }

效果图:
Android 可响应drawable点击事件的TextView_第1张图片

更多相关文章

  1. Android 技巧 - listview 里面的图片不能响应onClick事件?
  2. android 已省内存方式把图片加载到内存
  3. Android 列表数据写入到本地Excel文件(包括图片)
  4. Android Retrofit 2.0框架上传图片,视频解决方案
  5. Android matrix 控制图片的旋转、缩放、移动
  6. IM-A820L限制GSM,WCDMA上网的原理(其他泛泰机型可参考)7.13
  7. android WebView 图片缩放功能小结
  8. Android 主流图片库Picasso Glide Fresco对比分析

随机推荐

  1. Android进入页面默认不弹出软键盘
  2. Android Studio 指定DEBUG和RELEASE版本
  3. Android跨进程通信传输大数据
  4. android activity onSearchRequested()
  5. API Demos 2.2 研读笔记(5)——Window Feat
  6. Android动画之 Alpha与Translate结合使用
  7. 2011.09.07(5)——— android 跨进程通信之
  8. Android ProgressDialog的两种用法
  9. Android屏幕尺寸适配注意事项
  10. Tegra Android Development Pack | NVIDI