appwidget左右滑动更新

来源:互联网 发布:易语言会员系统源码 编辑:程序博客网 时间:2024/05/20 16:41

  上一篇讲了如何用代码的方式把appwidget添加到桌面上,如果没看的话可以看一下http://blog.csdn.net/so_strange/article/details/51014151

          前面我把appwidget添加到桌面上后,客户又提出了要添加左右滑动翻页的要求.我们知道,appwidget用的是RemoteViews,我又用了GridView,想要滑动翻页,必须要对事件做处理,RemoteViews有不支持自定义的view,目前对我来讲,我还没有找到让RemoteViews支持自定义view的方法.所以我只能在appwidget的父view上面想办法.先上代码:

  

public class RecommendationWidgetLayout extends RelativeLayout {    private static final String WIDGET_TURN_TO_PREV_PAGE_ACTION = "com.android.bookstore.provider.BUT_PREV_PAGE_ACTION";    private static final String WIDGET_TURN_TO_NEXT_PAGE_ACTION = "com.android.bookstore.provider.BUT_NEXT_PAGE_ACTION";    private float lastX;    public RecommendationWidgetLayout(Context context) {        this(context, null);    }    public RecommendationWidgetLayout(Context context, AttributeSet attrs) {        super(context, attrs);    }    @Override    public boolean onInterceptTouchEvent(MotionEvent ev) {        switch(ev.getActionMasked()) {            case MotionEvent.ACTION_DOWN:                lastX = ev.getX();                break;            case MotionEvent.ACTION_MOVE:                return detectDirection(ev) != PageTurningDirection.None;            case MotionEvent.ACTION_UP:            default:                break;        }        return false;    }    @Override    public boolean onTouchEvent(MotionEvent event) {        switch (event.getActionMasked()) {            case MotionEvent.ACTION_DOWN:                lastX = event.getX();                break;            case MotionEvent.ACTION_UP:                PageTurningDirection direction = detectDirection(event);                if (direction == PageTurningDirection.Left) {                    turnToPrevPage();                } else if (direction == PageTurningDirection.Right) {                    turnToNextPage();                }                break;            default:                break;        }        return true;    }    private void turnToPrevPage() {        sendUpdateWidgetBroadcast(WIDGET_TURN_TO_PREV_PAGE_ACTION);    }    private void turnToNextPage() {        sendUpdateWidgetBroadcast(WIDGET_TURN_TO_NEXT_PAGE_ACTION);    }    private PageTurningDirection detectDirection(MotionEvent currentEvent) {        return PageTurningDetector.detectLeftOrRight(getContext(), (int) (currentEvent.getX() - lastX));    }    private void sendUpdateWidgetBroadcast(String action) {        getContext().sendBroadcast(new Intent(action));    }}
public abstract class PageTurningDetector {    public static PageTurningDirection detectLeftOrRight(Context context, int deltaX)    {        int x_DELTA_THRESHOLD = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20, context.getResources().getDisplayMetrics());        if (Math.abs(deltaX) < x_DELTA_THRESHOLD) {            return PageTurningDirection.None;        }        return deltaX > 0 ? PageTurningDirection.Left : PageTurningDirection.Right;    }
 
  首先自定义的layout继承RelativeLayout,因为这里只是简单的添加一个AppWidgetHostView,所以只需要重写onInterceptTouchEvent和onTouchEvent这两个方法.onInterceptTouchEvent是viewgroup的方法,目的是在系统向该ViewGroup及其各个childView触发onTouchEvent()之前对相关事件进行一次拦截,Android这么设计的想法也很好理解,由于ViewGroup会包含若干childView,因此需要能够统一监控各种touch事件的机会,因此纯粹的不能包含子view的控件是没有这个方法的,如LinearLayout就有,TextView就没有。
  onInterceptTouchEvent()使用也很简单,如果在ViewGroup里覆写了该方法,那么就可以对各种touch事件加以拦截。但是如何拦截,是否所有的touch事件都需要拦截则是比较复杂的,touch事件在onInterceptTouchEvent()和onTouchEvent以及各个childView间的传递机制完全取决于onInterceptTouchEvent()和onTouchEvent()的返回值。并且,针对down事件处理的返回值直接影响到后续move和up事件的接收和传递。

  关于返回值的问题,基本规则很清楚,如果return true,那么表示该方法消费了此次事件,如果return false,那么表示该方法并未处理完全,该事件仍然需要以某种方式传递下去继续等待处理。

  1.down事件首先会传递到onInterceptTouchEvent()方法

  2.如果该ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后return false,那么后续的move, up等事件将继续会先传递给该ViewGroup,之后才和down事件一样传递给最终的目标view的onTouchEvent()处理。

  3.如果该ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后return true,那么后续的move, up等事件将不再传递给onInterceptTouchEvent(),而是和down事件一样传递给该ViewGroup的onTouchEvent()处理,注意,目标view将接收不到任何事件。

  4.如果最终需要处理事件的view的onTouchEvent()返回了false,那么该事件将被传递至其上一层次的view的onTouchEvent()处理。

  5.如果最终需要处理事件的view 的onTouchEvent()返回了true,那么后续事件将可以继续传递给该view的onTouchEvent()处理。

  上面这段话摘自http://blog.csdn.net/lvxiangan/article/details/9309927,分析的很好,大家一看就明白了,我就不在这里画蛇添足了.(奋斗其实我是菜鸟...你懂的...)

  在detectLeftOrRight()函数里有一个20,这个就是滑动距离的参照,如果滑动的距离小于它,就不算是滑动,不用拦截.当然这个你自己在实际过程中可以自己改动.

  至于更新widget肯定是发广播了,因为本身AppWidgetProvider extends android.content.BroadcastReceiver.需要在onReceive里面处理,这里就不再多说了.不知道的可以查下AppWidgetProvider的说明文档.提醒一下,上面的两个Action一定要在AndroidManifest.xml里面配置哦.本人就犯过这种低级错误.一定要记得配置广播的Action!一定要记得配置广播的Action!一定要记得配置广播的Action!大笑大笑大笑重要的事情说三遍.

  以上的办法其实没有解决根本问题,如何让appwidget自己的view可以实现滑动事件的处理,我还没想到办法,知道的大牛可以告诉我下.Thank you very much !




0 0
原创粉丝点击