Android 可显示左上右下Drawable的TextView
改编自Trinea的CompoundDrawablesTextView,thanks
概述
在android的TextView中为我们提供了很方便的在TextView的周围画Drawable
setCompoundDrawables(Drawable left, Drawable top, Drawable right, Drawable bottom)
或者
android:drawableLeft=””
android:drawableTop=””
android:drawableRight=””
android:drawableBottom=”“
但是,并没有对外提供触控事件,而我们需要其点击事件,对于这种情况,就需要了解Android的事件分发机制了
Android事件分发
参考:(Trinea)https://github.com/android-cn/android-open-project-analysis/tree/master/tech/touch-event
事件传递过程Activity.dispatchTouchEvent() -> ViewGroup.dispatchTouchEvent() -> View.onTouchEvent()
因此我们只需要重写onTouchEvent()即可。
/** * 设置OnClickListener为当前的listener,即调用{@link CompoundDrawablesTextView#onClick(View)}函数 **/ private void init() { super.setOnClickListener(this); } @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); } } }
实现原理
Rect对象rect有一个contains方法,只要我们把坐标传进去,就可以通过返回值来得到该坐标是否在该
rect对象所表示的矩形区域了。因此我们可以通过这个方法来进行判断我们所触摸的是哪一个Drawable或者是TextView的text
ps:left drawale
/** * 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,是用来扩大响应范围的。
这里用了一个自定义的接口来处理点击事件 的回调
/** * 图片点击的监听器 * * @author Trinea 2012-5-3 下午11:45:41 */ public interface DrawableClickListener { /** * 图片的位置 */ enum DrawablePosition { /** * 图片在TextView的左部 **/ LEFT, /** * 图片在TextView的上部 **/ TOP, /** * 图片在TextView的右部 **/ RIGHT, /** * 图片在TextView的底部 **/ BOTTOM, /** * 点击的是文字 */ TEXT }
Theme
这里我们通过theme来该改变控件的默认appearance,如果不了解通过theme改变控件属性可参见:
深入解析Android declare-styleable attr style theme(中)
- attrs.xml
<!--CompoundDrawablesTextView的style--> <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</item> </style> <style name="Widget" /> <style name="Widget.cdtStyle"> <item name="android:gravity">center</item> <item name="android:textColor">#fab</item> </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</item> </style> <style name="Widget.cdtStyle.CustomcdtStyle"> <item name="android:drawablePadding">10dp</item> <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" /> <!--layout.xml--> <?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; } } }
效果图:
CompoundDrawablesTextView.java@[Github]
完整demo :
CompoundDrawablesTextViewActivity.java@[Github]
更多相关文章
- Android事件处理之监听事件
- android photoview 图片放大缩放功能 ImageView
- Android图片太大导致无法正常显示
- 不停地切换两张图片ViewFlipper
- android一些不常用的事件
- Android实现图片缩放与旋转
- Android Studio点击按钮更换背景图片
- android图片放大 缩小 旋转