Android WebView 与HttpClient 共用本地cookie问题

我是为了解决:WebView 缓存下来的cookie可以用于HttpClient,因为我的HttpClient单独需要取一些数据,但是依赖于本地的cookie。如果没有cookie返回来的是登录页面 [html] view plaincopy在CODE上查看代码片派生到我的代码片 核心代码: mainActivity.java public void onCreate(Bundle savedInstanceState) { View v = inflater.inflate(R.layout.main_fragment, container, false); mWebView = (WebView) v.findViewById(R.id.webview); MyWebViewClient webviewClient = new MyWebViewClient(); mWebView.setWebViewClient(webviewClient); WebSettings webset = mWebView.getSettings(); webset.setJavaScriptEnabled(true); mWebView.loadUrl(Constants.TALKGROUP_URL); return v; } private class MyWebViewClient extends WebViewClient { @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); IWLog.d(TAG, “onPageFinished() url is:”+url); /* 将cookie保存起来*/ String c = CookieManager.getInstance().getCookie(url); DataCenter.setCookie(c); CookieSyncManager.getInstance().sync(); } @Override public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { IWLog.d(TAG, “onReceivedError() errorCode:” + errorCode+”—-failingUrl”+failingUrl); super.onReceivedError(view, errorCode, description, failingUrl); } ...

2014年12月5日 · 2 分钟 · 天边的星星

Android(安卓)WebView设置cookie

最近两天一直想用安卓模拟登陆,利用新的WebView显示登陆后可以访问的页面,但是不管怎么访问需要登陆后才能访问的页面,还是跳回到登陆页,后来网上看了下是cookie没有设置,找了半天才到到合适的设置方法: 登陆方法: private Cookie cookie; public static HttpContext localContext; <span style="color: #ff0000;">**public static List cookies;//此为保存的cookie**</span> public String cookieStr; // public static Cookie cookie = null; /** * 登陆时保存cookie * @param url * @param data * @return */ public String login(String url,String data[]){ HttpClient client = null; String html = null; try { client = new DefaultHttpClient(); <span style="color: #ff0000;">**// 创建cookie store的本地实例 CookieStore cookieStore = new BasicCookieStore(); localContext = new BasicHttpContext(); // 绑定定制的cookie store到本地内容中 localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore); **</span> HttpPost post = new HttpPost(url); List parameters = new ArrayList(); parameters.add(new BasicNameValuePair("username", data[0])); parameters.add(new BasicNameValuePair("passwd", data[1])); parameters.add(new BasicNameValuePair("login", "%B5%C7%A1%A1%C2%BC")); UrlEncodedFormEntity entity = new UrlEncodedFormEntity(parameters,"utf-8"); post.setEntity(entity); HttpResponse response = client.execute(post<span style="color: #ff0000;">,localContext</span>); if(response.getStatusLine().getStatusCode() == 200){ InputStream content = response.getEntity().getContent(); BufferedReader buffer = new BufferedReader(new InputStreamReader(content,"gbk")); String line = null; while((line=buffer.readLine())!=null){ html+=line; } <span style="color: #ff0000;">** cookies = cookieStore.getCookies();**</span> System.out.println("cookies.size():"+cookies.size()); if (!cookies.isEmpty()) { for(int i=0;i&lt;cookies.size();i++){ system.out.println("-="" "+cookies.get(i).tostring());="" }="" buffer.close();="" }else{="" system.out.println("utilslogin:"+response.getstatusline().getstatuscode());="" catch="" (exception="" e)="" {="" e.printstacktrace();="" }finally{="" if(client!="null){" client.getconnectionmanager().shutdown();="" return="" html;="" }&lt;="" pre=""&gt; ...

2014年12月5日 · 2 分钟 · 天边的星星

Sqlite删除列方法

sqlite中是不支持删除列操作的,所以网上alter table table_name drop column col_name这个语句在sqlite中是无效的,而替代的方法可以如下: 1.根据原表创建一张新表 2.删除原表 3.将新表重名为旧表的名称 示例例子如下 1.创建一张旧表Student,包含id(主码),name, tel create table student ( id integer primary key, name text, tel text ) 2.给旧表插入两个值 insert into student(id,name,tel) values(101,”Jack”,”110″) insert into student(id,name,tel) values(102,”Rose”,”119″) 结果如图 3.接下来我们删除电话这个列,首先根据student表创建一张新表teacher create table teacher as select id,name from student 结果如图 可以看到tel这一列已经没有了 4.然后我们删除student这个表 drop table if exists student 5.将teacher这个表重命名为student alter table teacher rename to student 结果演示: select * from student order by name desc(desc降序, asc升序) ...

2014年12月5日 · 1 分钟 · 天边的星星

【安卓】从源码的角度深入分析Scroller

这篇文章我将从源码的角度深入分析Scroller类。在阅读的时候,建议大家打开源码对照着看,否则可能看的云里雾里。 **一.Scroller的用途** ** ** 熟悉android的同学必然对Scroller不陌生,Scroller是一个**弹性滑动对象**,可以制作很多酷炫的滑动效果,Lancher中的滑屏效果就有使用到Scroller。 我们知道,View类中的scrollTo和scrollBy方法提供了滑动操作,但是这种滑动操作是瞬间完成的,就是说你为scrollTo提供终点坐标,该方法只要一调用,我们就会发现已经滚动到目的地了,这种方式很显然用户体验是不好的,因而android工程师为我们封装了Scroller类,这个类可以为View带来**缓慢移动的效果**。 具体使用方式通常是通过在你自定义的View中调用Scroller的startScroll并刷新视图,另外需重写computeScroll方法(刷新视图过程中会调用此方法),在该方法中调用Scroller的computeScrollOffset计算应该滚动到的位置,然后使用scrollTo滚动到该位置,再调用invalidate刷新,就可以实现滚动效果了(不了解的同学建议先去熟悉Scroller用法)。 Scroller使用示例(代码片段): **[java]** [view plain](http://blog.csdn.net/chdjj/article/details/41678897#)[copy](http://blog.csdn.net/chdjj/article/details/41678897#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/539577)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/539577/fork) <div> </div> </div> </div> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">public</span> <span class="keyword" style="font-weight: bold; color: #006699;">class</span> MyView <span class="keyword" style="font-weight: bold; color: #006699;">extends</span> LinearLayout </span> - <span style="color: black;">{ </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">private</span> Scroller mScroller; </span> - <span style="color: black;"> &#8230; &#8230; </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">private</span> <span class="keyword" style="font-weight: bold; color: #006699;">void</span> smoothScrollTo(<span class="keyword" style="font-weight: bold; color: #006699;">int</span> destX,<span class="keyword" style="font-weight: bold; color: #006699;">int</span> destY) </span> - <span style="color: black;"> { </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">int</span> scrollX = getScrollX(); </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">int</span> scrollY = getScrollY(); </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">int</span> deltaX = destX-scrollX; </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">int</span> deltaY = destY-scrollY; </span> - <span style="color: black;"> mScroller.startScroll(scrollX,scrollY,deltaX, deltaY, <span class="number" style="color: #c00000;">1000</span>); </span> - <span style="color: black;"> invalidate(); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> <span class="annotation" style="color: #646464;">@Override</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">public</span> <span class="keyword" style="font-weight: bold; color: #006699;">void</span> computeScroll() </span> - <span style="color: black;"> { </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">if</span>(mScroller != <span class="keyword" style="font-weight: bold; color: #006699;">null</span>) </span> - <span style="color: black;"> { </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">if</span>(mScroller.computeScrollOffset()) </span> - <span style="color: black;"> { </span> - <span style="color: black;"> scrollTo(mScroller.getCurrX(),mScroller.getCurrY()); </span> - <span style="color: black;"> Log.d(TAG,<span class="string" style="color: blue;">&#8220;scrollX=&#8221;</span>+getScrollX()+<span class="string" style="color: blue;">&#8220;,scrollY=&#8221;</span>+getScrollY()); </span> - <span style="color: black;"> postInvalidate(); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> } </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;"> </span> - <span style="color: black;">} </span> **二.ScrollTo、ScrollBy、getScrollX、getScrollY方法分析** ** ** 在分析Scroller源码之前,我们必须先了解ScrollTo,ScrollBy,getScrollX,getScrollY这几个方法的作用。这四个方法都是View类提供的,这点先明确。 我们先分析getScrollX和getScrollY方法,查看源码实现: **[java]** [view plain](http://blog.csdn.net/chdjj/article/details/41678897#)[copy](http://blog.csdn.net/chdjj/article/details/41678897#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/539577)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/539577/fork) <div> </div> </div> </div> - <span style="color: black;"><span class="comment" style="color: #008200;">/**</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> * Return the scrolled left position of this view. This is the left edge of</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> * the displayed part of your view. You do not need to draw any pixels</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> * farther left, since those are outside of the frame of your view on</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> * screen.</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> *</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> * @return The left edge of the displayed part of your view, in pixels.</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> */</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">public</span> <span class="keyword" style="font-weight: bold; color: #006699;">final</span> <span class="keyword" style="font-weight: bold; color: #006699;">int</span> getScrollX() { </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">return</span> mScrollX; </span> - <span style="color: black;"> } </span> - <span style="color: black;"> <span class="comment" style="color: #008200;">/**</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> * Return the scrolled top position of this view. This is the top edge of</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> * the displayed part of your view. You do not need to draw any pixels above</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> * it, since those are outside of the frame of your view on screen.</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> *</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> * @return The top edge of the displayed part of your view, in pixels.</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> */</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">public</span> <span class="keyword" style="font-weight: bold; color: #006699;">final</span> <span class="keyword" style="font-weight: bold; color: #006699;">int</span> getScrollY() { </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">return</span> mScrollY; </span> - <span style="color: black;"> } </span> </div> <div> <div> getScrollX和getScrollY方法返回的是mScrollX和mScrollY变量。这两个变量是什么呢? </div> <div> </div> <div> 这里我直接告诉大家,**mScrollX和mScrollY指的是视图内容相对于视图原始起始坐标的偏移量**,mScrollX和mScrollY的默认值为0,因为默认是没有偏移的。另外需注意偏移量的正负问题,因为是相对视图起始坐标的,所以如果你是**向右偏移那么mScrollX应该是负数,而向左偏移mScrollX为正数**。再举个例子,比如你定义了一个ImageView,其左上角的坐标为(100,80),此时mScrollX和mScrollY值都为0(没有偏移),现在你要把该ImageView移到(120,100)处,也就是右下方,那么你的mScrollX应该是100-120=-20,mScrollY应该是80-100=-20,这下你该明白了吧。 </div> </div> <div> 明白了这个问题,scrollBy和scrollTo也就不在话下了,我们查看源码: </div> <div> </div> <div class="dp-highlighter bg_java"> <div class="bar"> <div class="tools" style="color: silver;"> **[java]** [view plain](http://blog.csdn.net/chdjj/article/details/41678897#)[copy](http://blog.csdn.net/chdjj/article/details/41678897#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/539577)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/539577/fork) <div> </div> </div> </div> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">public</span> <span class="keyword" style="font-weight: bold; color: #006699;">void</span> scrollTo(<span class="keyword" style="font-weight: bold; color: #006699;">int</span> x, <span class="keyword" style="font-weight: bold; color: #006699;">int</span> y) { </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">if</span> (mScrollX != x || mScrollY != y) { </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">int</span> oldX = mScrollX; </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">int</span> oldY = mScrollY; </span> - <span style="color: black;"> mScrollX = x; </span> - <span style="color: black;"> mScrollY = y; </span> - <span style="color: black;"> invalidateParentCaches(); </span> - <span style="color: black;"> onScrollChanged(mScrollX, mScrollY, oldX, oldY); </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">if</span> (!awakenScrollBars()) { </span> - <span style="color: black;"> postInvalidateOnAnimation(); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> } </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">public</span> <span class="keyword" style="font-weight: bold; color: #006699;">void</span> scrollBy(<span class="keyword" style="font-weight: bold; color: #006699;">int</span> x, <span class="keyword" style="font-weight: bold; color: #006699;">int</span> y) { </span> - <span style="color: black;"> scrollTo(mScrollX + x, mScrollY + y); </span> - <span style="color: black;"> } </span> </div> <div> 先看scrollTo方法,它首先判断x,y方向的偏移量(即mScrollX,mScrollY)是否和传进来的偏移量(即x,y)相同,如果相同那么直接返回,否则我们将更新mScrollX和mScrollY,并且通知界面发生改变请求重绘。通过这种方式就可以实现滚动效果了,只是是瞬间移动的。再看这个scrollBy,直接调用的是scrollTo,根据参数很容易发现,这个方法的作用是在当前偏移基础上,再继续偏移(x,y)单位。需要注意的是这两个方法的**参数是偏移量而不是实际位置**哦! </div> <div> </div> <div> 这里还有一点需要注意,那就是你**调用一个View的scrollTo方法进行滚动时,滚动的并不是该View本身,而是该View的内容。**比如你要对一个Button进行滚动的话,应该在Button外面包一个ViewGroup,然后调用ViewGroup的scrollTo方法。这一点也很重要,大家需要注意下! </div> <div> </div> <div> **三.Scroller源码分析** </div> <div> ** ** </div> <div> Scroller的精华在于computeScrollOffset和startScroll方法,所以我们重点分析这两个方法。 </div> <div> 分析之前,先看这个类中定义的一些变量: </div> <div class="dp-highlighter bg_java"> <div class="bar"> <div class="tools" style="color: silver;"> **[java]** [view plain](http://blog.csdn.net/chdjj/article/details/41678897#)[copy](http://blog.csdn.net/chdjj/article/details/41678897#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/539577)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/539577/fork) <div> </div> </div> </div> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">private</span> <span class="keyword" style="font-weight: bold; color: #006699;">int</span> mMode;<span class="comment" style="color: #008200;">//模式,有SCROLL_MODE和FLING_MODE</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">private</span> <span class="keyword" style="font-weight: bold; color: #006699;">int</span> mStartX;<span class="comment" style="color: #008200;">//起始x方向偏移</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">private</span> <span class="keyword" style="font-weight: bold; color: #006699;">int</span> mStartY;<span class="comment" style="color: #008200;">//起始y方向偏移</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">private</span> <span class="keyword" style="font-weight: bold; color: #006699;">int</span> mFinalX;<span class="comment" style="color: #008200;">//终点x方向偏移</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">private</span> <span class="keyword" style="font-weight: bold; color: #006699;">int</span> mFinalY;<span class="comment" style="color: #008200;">//终点y方向偏移</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">private</span> <span class="keyword" style="font-weight: bold; color: #006699;">int</span> mCurrX;<span class="comment" style="color: #008200;">//当前x方向偏移</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">private</span> <span class="keyword" style="font-weight: bold; color: #006699;">int</span> mCurrY;<span class="comment" style="color: #008200;">//当前y方向偏移</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">private</span> <span class="keyword" style="font-weight: bold; color: #006699;">long</span> mStartTime;<span class="comment" style="color: #008200;">//起始时间</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">private</span> <span class="keyword" style="font-weight: bold; color: #006699;">int</span> mDuration;<span class="comment" style="color: #008200;">//滚动持续时间</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">private</span> <span class="keyword" style="font-weight: bold; color: #006699;">float</span> mDurationReciprocal;<span class="comment" style="color: #008200;">//持续时间的倒数</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">private</span> <span class="keyword" style="font-weight: bold; color: #006699;">float</span> mDeltaX;<span class="comment" style="color: #008200;">//x方向应该滚动的距离,mDeltaX=mFinalX-mStartX</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">private</span> <span class="keyword" style="font-weight: bold; color: #006699;">float</span> mDeltaY;<span class="comment" style="color: #008200;">//y方向应该滚动的距离,mDeltaY=mFinalY-mStartY</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">private</span> <span class="keyword" style="font-weight: bold; color: #006699;">boolean</span> mFinished;<span class="comment" style="color: #008200;">//是否结束</span> </span> </div> 对这些变量有个大致印象之后,我们就开始看startScroll源码了: **[java]** [view plain](http://blog.csdn.net/chdjj/article/details/41678897#)[copy](http://blog.csdn.net/chdjj/article/details/41678897#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/539577)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/539577/fork) <div> </div> </div> </div> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">public</span> <span class="keyword" style="font-weight: bold; color: #006699;">void</span> startScroll(<span class="keyword" style="font-weight: bold; color: #006699;">int</span> startX, <span class="keyword" style="font-weight: bold; color: #006699;">int</span> startY, <span class="keyword" style="font-weight: bold; color: #006699;">int</span> dx, <span class="keyword" style="font-weight: bold; color: #006699;">int</span> dy) { </span> - <span style="color: black;"> startScroll(startX, startY, dx, dy, DEFAULT_DURATION); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">public</span> <span class="keyword" style="font-weight: bold; color: #006699;">void</span> startScroll(<span class="keyword" style="font-weight: bold; color: #006699;">int</span> startX, <span class="keyword" style="font-weight: bold; color: #006699;">int</span> startY, <span class="keyword" style="font-weight: bold; color: #006699;">int</span> dx, <span class="keyword" style="font-weight: bold; color: #006699;">int</span> dy, <span class="keyword" style="font-weight: bold; color: #006699;">int</span> duration) { </span> - <span style="color: black;"> mMode = SCROLL_MODE; </span> - <span style="color: black;"> mFinished = <span class="keyword" style="font-weight: bold; color: #006699;">false</span>; </span> - <span style="color: black;"> mDuration = duration; </span> - <span style="color: black;"> mStartTime = AnimationUtils.currentAnimationTimeMillis(); </span> - <span style="color: black;"> mStartX = startX; </span> - <span style="color: black;"> mStartY = startY; </span> - <span style="color: black;"> mFinalX = startX + dx; </span> - <span style="color: black;"> mFinalY = startY + dy; </span> - <span style="color: black;"> mDeltaX = dx; </span> - <span style="color: black;"> mDeltaY = dy; </span> - <span style="color: black;"> mDurationReciprocal = <span class="number" style="color: #c00000;">1</span>.0f / (<span class="keyword" style="font-weight: bold; color: #006699;">float</span>) mDuration; </span> - <span style="color: black;"> } </span> </div> <div> 这个所谓的startScroll方法里面全部是对上面那些变量赋值的,比如将当前模式置为SCROLL_MODE,设置持续时间,起点终点偏移,起始时间等等。这个方法似乎并没有触发start scroll,恩,的确是这样的。那么到底怎么触发scroll呢?我们将这个问题留到下一个部分分析。 </div> <div> 为了让大家理解这些变量的作用,我画了一张图。 </div> ![](http://img.blog.csdn.net/20141202145628031?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2hkamo=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)</div> <div> <div> 解释下,图中我们假设从A点滚动到B点,那么,**如果知道mStartX,mStartY(由startScroll的startX和startY参数得到)和mDeltaX,mDeltaY(由startScroll的dx和dy参数得到)。那么,mFinalX和mFinalY就很容易得到了。此外在加上duration持续时间,那么我们就可以根据(当前时间-mStartTime)占duration的比例来算出当前位置,也即mCurrX和mCurrY。**我不会告诉你,这就是computeScrollOffset的作用!通过上面分析我们发现,**startScroll方法其实相当于一个预处理,为computeScrollOffset提供数据。** </div> <div> </div> <div> 下面我们查看computeScrollOffset源码: </div> <div class="dp-highlighter bg_java"> <div class="bar"> <div class="tools" style="color: silver;"> **[java]** [view plain](http://blog.csdn.net/chdjj/article/details/41678897#)[copy](http://blog.csdn.net/chdjj/article/details/41678897#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/539577)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/539577/fork) <div> </div> </div> </div> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">public</span> <span class="keyword" style="font-weight: bold; color: #006699;">boolean</span> computeScrollOffset() { </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">if</span> (mFinished) { </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">return</span> <span class="keyword" style="font-weight: bold; color: #006699;">false</span>; </span> - <span style="color: black;"> } </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">int</span> timePassed = (<span class="keyword" style="font-weight: bold; color: #006699;">int</span>)(AnimationUtils.currentAnimationTimeMillis() &#8211; mStartTime); </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">if</span> (timePassed < mDuration) { </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">switch</span> (mMode) { </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">case</span> SCROLL_MODE: </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">final</span> <span class="keyword" style="font-weight: bold; color: #006699;">float</span> x = mInterpolator.getInterpolation(timePassed * mDurationReciprocal); </span> - <span style="color: black;"> mCurrX = mStartX + Math.round(x * mDeltaX); </span> - <span style="color: black;"> mCurrY = mStartY + Math.round(x * mDeltaY); </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">break</span>; </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">case</span> FLING_MODE: </span> - <span style="color: black;"> &#8230; &#8230; </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">break</span>; </span> - <span style="color: black;"> } </span> - <span style="color: black;"> } </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">else</span> { </span> - <span style="color: black;"> mCurrX = mFinalX; </span> - <span style="color: black;"> mCurrY = mFinalY; </span> - <span style="color: black;"> mFinished = <span class="keyword" style="font-weight: bold; color: #006699;">true</span>; </span> - <span style="color: black;"> } </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">return</span> <span class="keyword" style="font-weight: bold; color: #006699;">true</span>; </span> - <span style="color: black;"> } </span> </div> <div> 看,是不是很好理解了。**首先判断是否结束(mFinished==true?),如果没有结束,那么程序继续向下跑,计算timePassed,即当前时间减去开始时间,如果小于mDuration,那么就可以根据比例计算出当前位置,当然了,这里使用了Interpolator来控制动画的效果,加速或者减速等等。如果已经超过了mDuration了,那么滚动应该停止了,所以将mFinished置为ture,下次调用computeScrollOffset就会返回false了。** </div> <div> ** ** </div> <div> 到这里,我们把Scroller中的重要部分都分析完了,但是我们发现这两个方法都没有涉及具体滚动。那么滚动到底是如何触发的呢?下面我们将对整个流程进行源码分析。 </div> <div> </div> <div> **四.滚动流程分析** </div> <div> ** ** </div> <div> 在第一部分中,我给出了一个Scroller的使用示例,在smoothScrollTo方法中我们调用了Scroller的startScroll,然后调用了invalidate方法刷新视图,这个滚动效果就是由invalidate触发的!我们知道,调用了invalidate方法将会引起整个view系统的重绘,所以我们得从View的绘制说起。有经验的同学都应该知道,View的绘制包括三个主要过程,分别是measure,layout和draw。下面我们看View类的draw方法源码: </div> <div> </div> <div class="dp-highlighter bg_java"> <div class="bar"> <div class="tools" style="color: silver;"> **[java]** [view plain](http://blog.csdn.net/chdjj/article/details/41678897#)[copy](http://blog.csdn.net/chdjj/article/details/41678897#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/539577)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/539577/fork) <div> </div> </div> </div> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">public</span> <span class="keyword" style="font-weight: bold; color: #006699;">void</span> draw(Canvas canvas) { </span> - <span style="color: black;"> &#8230; &#8230; </span> - <span style="color: black;"> <span class="comment" style="color: #008200;">/*</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> * Draw traversal performs several drawing steps which must be executed</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> * in the appropriate order:</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> *</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> * 1. Draw the background</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> * 2. If necessary, save the canvas&#8217; layers to prepare for fading</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> * 3. Draw view&#8217;s content</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> * 4. Draw children</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> * 5. If necessary, draw the fading edges and restore layers</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> * 6. Draw decorations (scrollbars for instance)</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> */</span> </span> - <span style="color: black;"> <span class="comment" style="color: #008200;">// Step 1, draw the background, if needed</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">int</span> saveCount; </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">if</span> (!dirtyOpaque) { </span> - <span style="color: black;"> drawBackground(canvas); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> &#8230; &#8230; </span> - <span style="color: black;"> <span class="comment" style="color: #008200;">// Step 2, save the canvas&#8217; layers</span> </span> - <span style="color: black;"> &#8230; &#8230; </span> - <span style="color: black;"> <span class="comment" style="color: #008200;">// Step 3, draw the content</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">if</span> (!dirtyOpaque) onDraw(canvas); </span> - <span style="color: black;"> <span class="comment" style="color: #008200;">// Step 4, draw the children</span> </span> - <span style="color: black;"> dispatchDraw(canvas); </span> - <span style="color: black;"> <span class="comment" style="color: #008200;">// Step 5, draw the fade effect and restore layers</span> </span> - <span style="color: black;"> &#8230; &#8230; </span> - <span style="color: black;"> } </span> </div> draw方法将绘制分成了六步,其中第三步是调用onDraw去绘制内容,第四步是调用dispatchDraw去绘制子视图。我们看下dispatchDraw方法: <div class="dp-highlighter bg_java"> <div class="bar"> <div class="tools" style="color: silver;"> **[java]** [view plain](http://blog.csdn.net/chdjj/article/details/41678897#)[copy](http://blog.csdn.net/chdjj/article/details/41678897#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/539577)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/539577/fork) <div> </div> </div> </div> - <span style="color: black;"><span class="comment" style="color: #008200;">/**</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> * Called by draw to draw the child views. This may be overridden</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> * by derived classes to gain control just before its children are drawn</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> * (but after its own view has been drawn).</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> * @param canvas the canvas on which to draw the view</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> */</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">protected</span> <span class="keyword" style="font-weight: bold; color: #006699;">void</span> dispatchDraw(Canvas canvas) { </span> - <span style="color: black;"> } </span> </div> 恩,没错,是个空方法,因为只有ViewGroup才有子视图,所以我们来到ViewGroup中,找到dispatchDraw: <div class="dp-highlighter bg_java"> <div class="bar"> <div class="tools" style="color: silver;"> **[java]** [view plain](http://blog.csdn.net/chdjj/article/details/41678897#)[copy](http://blog.csdn.net/chdjj/article/details/41678897#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/539577)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/539577/fork) <div> </div> </div> </div> - <span style="color: black;"><span class="annotation" style="color: #646464;">@Override</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">protected</span> <span class="keyword" style="font-weight: bold; color: #006699;">void</span> dispatchDraw(Canvas canvas) { </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">boolean</span> usingRenderNodeProperties = canvas.isRecordingFor(mRenderNode); </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">final</span> <span class="keyword" style="font-weight: bold; color: #006699;">int</span> childrenCount = mChildrenCount; </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">final</span> View[] children = mChildren; </span> - <span style="color: black;"> &#8230; &#8230; </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">for</span> (<span class="keyword" style="font-weight: bold; color: #006699;">int</span> i = <span class="number" style="color: #c00000;"></span>; i < childrenCount; i++) { </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">int</span> childIndex = customOrder ? getChildDrawingOrder(childrenCount, i) : i; </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">final</span> View child = (preorderedList == <span class="keyword" style="font-weight: bold; color: #006699;">null</span>) </span> - <span style="color: black;"> ? children[childIndex] : preorderedList.get(childIndex); </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">if</span> ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE || child.getAnimation() != <span class="keyword" style="font-weight: bold; color: #006699;">null</span>) { </span> - <span style="color: black;"> more |= drawChild(canvas, child, drawingTime); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> } </span> - <span style="color: black;"> } </span> </div> 代码也是极其长的,这里截取了一部分。我们看到这个方法中调用了drawChild方法,从名字上就可以看出这个方法是用来绘制子视图的,找到其实现: <div class="dp-highlighter bg_java"> <div class="bar"> <div class="tools" style="color: silver;"> **[java]** [view plain](http://blog.csdn.net/chdjj/article/details/41678897#)[copy](http://blog.csdn.net/chdjj/article/details/41678897#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/539577)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/539577/fork) <div> </div> </div> </div> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">protected</span> <span class="keyword" style="font-weight: bold; color: #006699;">boolean</span> drawChild(Canvas canvas, View child, <span class="keyword" style="font-weight: bold; color: #006699;">long</span> drawingTime) { </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">return</span> child.draw(canvas, <span class="keyword" style="font-weight: bold; color: #006699;">this</span>, drawingTime); </span> - <span style="color: black;"> } </span> </div> 这里调用了view的draw方法,当然,这个draw方法跟上面那个draw不一样,因为它有三个参数!那还等什么,我们回到View的代码中找到这个含有三个参数的draw方法: <div class="dp-highlighter bg_java"> <div class="bar"> <div class="tools" style="color: silver;"> **[java]** [view plain](http://blog.csdn.net/chdjj/article/details/41678897#)[copy](http://blog.csdn.net/chdjj/article/details/41678897#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/539577)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/539577/fork) <div> </div> </div> </div> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">boolean</span> draw(Canvas canvas, ViewGroup parent, <span class="keyword" style="font-weight: bold; color: #006699;">long</span> drawingTime) { </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">boolean</span> more = <span class="keyword" style="font-weight: bold; color: #006699;">false</span>; </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">final</span> <span class="keyword" style="font-weight: bold; color: #006699;">boolean</span> childHasIdentityMatrix = hasIdentityMatrix(); </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">final</span> <span class="keyword" style="font-weight: bold; color: #006699;">int</span> flags = parent.mGroupFlags; </span> - <span style="color: black;"> &#8230; &#8230; </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">int</span> sx = <span class="number" style="color: #c00000;"></span>; </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">int</span> sy = <span class="number" style="color: #c00000;"></span>; </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">if</span> (!hasDisplayList) { </span> - <span style="color: black;"> computeScroll();<span class="comment" style="color: #008200;">//终于找到了computeScroll</span> </span> - <span style="color: black;"> sx = mScrollX; </span> - <span style="color: black;"> sy = mScrollY; </span> - <span style="color: black;"> } </span> - <span style="color: black;"> &#8230; &#8230; </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">return</span> more; </span> - <span style="color: black;"> } </span> </div> <div> 在其中,我们找到了computeScroll方法!当然View中的computeScroll方法是空的,需要我们根据场景自己复写。 </div> <div> 比如,我发现,TextView中就有复写这个方法: </div> <div class="dp-highlighter bg_java"> <div class="bar"> <div class="tools" style="color: silver;"> **[java]** [view plain](http://blog.csdn.net/chdjj/article/details/41678897#)[copy](http://blog.csdn.net/chdjj/article/details/41678897#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/539577)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/539577/fork) <div> </div> </div> </div> - <span style="color: black;"><span class="annotation" style="color: #646464;">@Override</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">public</span> <span class="keyword" style="font-weight: bold; color: #006699;">void</span> computeScroll() { </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">if</span> (mScroller != <span class="keyword" style="font-weight: bold; color: #006699;">null</span>) { </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">if</span> (mScroller.computeScrollOffset()) { </span> - <span style="color: black;"> mScrollX = mScroller.getCurrX(); </span> - <span style="color: black;"> mScrollY = mScroller.getCurrY(); </span> - <span style="color: black;"> invalidateParentCaches(); </span> - <span style="color: black;"> postInvalidate(); <span class="comment" style="color: #008200;">// So we draw again</span> </span> - <span style="color: black;"> } </span> - <span style="color: black;"> } </span> - <span style="color: black;"> } </span> </div> <div> 好了,折腾了这么久,**<span style="color: #000080;">下面我们再回顾下这个过程:我们在自定义view中调用了startScroll方法为滚动设置了一些基本数据,然后通过invalidate由上而下刷新view视图,首先是根视图(通常是ViewGroup)的draw方法被调用,然后调用onDraw绘制视图内容,接着dispatchDraw方法被调用去绘制子视图,dispatchDraw方法会对每个子视图调用drawChild方法,而drawChild方法会调用该子View的draw方法(三个参数),在draw方法中会调用computeScroll方法进行滚动,而computeScroll方法是被复写的,视场景而定,通常是根据computeScrollOffset来判断是否需要滑动,如果需要的话,接着调用postInvalidate再由上至下重新绘制,如此一来便实现了平滑滚动的效果!</span>** </div> <div> ok,到这里总算是把Scroller讲清楚了! </div> <div> </div> <div> **五.实例分析** </div> <div> ** ** </div> <div> 为了便于理解,我这里写了一个小例子,通过打印日志的形式让大家理解上面所讲的内容。 </div> <div> 首先是几个自定义的view: </div> <div> </div> <div> MyLinearLayout: </div> <div class="dp-highlighter bg_java"> <div class="bar"> <div class="tools" style="color: silver;"> **[java]** [view plain](http://blog.csdn.net/chdjj/article/details/41678897#)[copy](http://blog.csdn.net/chdjj/article/details/41678897#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/539577)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/539577/fork) <div> </div> </div> </div> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">package</span> com.example.scrollerdemo; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">import</span> android.content.Context; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">import</span> android.graphics.Canvas; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">import</span> android.util.AttributeSet; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">import</span> android.util.Log; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">import</span> android.widget.LinearLayout; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">public</span> <span class="keyword" style="font-weight: bold; color: #006699;">class</span> MyLinearLayout <span class="keyword" style="font-weight: bold; color: #006699;">extends</span> LinearLayout </span> - <span style="color: black;">{ </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">private</span> <span class="keyword" style="font-weight: bold; color: #006699;">static</span> <span class="keyword" style="font-weight: bold; color: #006699;">final</span> String TAG = <span class="string" style="color: blue;">&#8220;TEST&#8221;</span>; </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">public</span> MyLinearLayout(Context context) </span> - <span style="color: black;"> { </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">super</span>(context); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">public</span> MyLinearLayout(Context context, AttributeSet attrs) </span> - <span style="color: black;"> { </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">super</span>(context, attrs); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> <span class="annotation" style="color: #646464;">@Override</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">public</span> <span class="keyword" style="font-weight: bold; color: #006699;">void</span> draw(Canvas canvas) </span> - <span style="color: black;"> { </span> - <span style="color: black;"> Log.i(TAG, <span class="string" style="color: blue;">&#8220;MyLinearLayout&#8212;>draw&#8221;</span>); </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">super</span>.draw(canvas); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> <span class="annotation" style="color: #646464;">@Override</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">protected</span> <span class="keyword" style="font-weight: bold; color: #006699;">void</span> onDraw(Canvas canvas) </span> - <span style="color: black;"> { </span> - <span style="color: black;"> Log.i(TAG, <span class="string" style="color: blue;">&#8220;MyLinearLayout&#8212;>onDraw&#8221;</span>); </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">super</span>.onDraw(canvas); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> <span class="annotation" style="color: #646464;">@Override</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">public</span> <span class="keyword" style="font-weight: bold; color: #006699;">void</span> computeScroll() </span> - <span style="color: black;"> { </span> - <span style="color: black;"> Log.i(TAG, <span class="string" style="color: blue;">&#8220;MyLinearLayout&#8212;>computeScroll&#8221;</span>); </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">super</span>.computeScroll(); </span> - <span style="color: black;"> } </span> - <span style="color: black;">} </span> </div> MyView(实现了平滑滚动效果): <div class="dp-highlighter bg_java"> <div class="bar"> <div class="tools" style="color: silver;"> **[java]** [view plain](http://blog.csdn.net/chdjj/article/details/41678897#)[copy](http://blog.csdn.net/chdjj/article/details/41678897#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/539577)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/539577/fork) <div> </div> </div> </div> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">package</span> com.example.scrollerdemo; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">import</span> android.content.Context; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">import</span> android.graphics.Canvas; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">import</span> android.util.AttributeSet; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">import</span> android.util.Log; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">import</span> android.view.View; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">import</span> android.widget.LinearLayout; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">import</span> android.widget.Scroller; </span> - <span style="color: black;"><span class="comment" style="color: #008200;">/**</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> * @author Rowandjj</span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> * </span> </span> - <span style="color: black;"><span class="comment" style="color: #008200;"> */</span> </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">public</span> <span class="keyword" style="font-weight: bold; color: #006699;">class</span> MyView <span class="keyword" style="font-weight: bold; color: #006699;">extends</span> LinearLayout </span> - <span style="color: black;">{ </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">private</span> <span class="keyword" style="font-weight: bold; color: #006699;">static</span> <span class="keyword" style="font-weight: bold; color: #006699;">final</span> String TAG = <span class="string" style="color: blue;">&#8220;TEST&#8221;</span>; </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">private</span> Scroller mScroller; </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">public</span> MyView(Context context) </span> - <span style="color: black;"> { </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">super</span>(context); </span> - <span style="color: black;"> init(); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">public</span> MyView(Context context, AttributeSet attrs) </span> - <span style="color: black;"> { </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">super</span>(context, attrs); </span> - <span style="color: black;"> init(); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">private</span> <span class="keyword" style="font-weight: bold; color: #006699;">void</span> init() </span> - <span style="color: black;"> { </span> - <span style="color: black;"> mScroller = <span class="keyword" style="font-weight: bold; color: #006699;">new</span> Scroller(getContext()); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">public</span> <span class="keyword" style="font-weight: bold; color: #006699;">void</span> testSmoothScroll() </span> - <span style="color: black;"> { </span> - <span style="color: black;"> <span class="comment" style="color: #008200;">//向右下方平滑滚动(向右偏移100,向下偏移100)</span> </span> - <span style="color: black;"> smoothScrollTo(-<span class="number" style="color: #c00000;">100</span>,-<span class="number" style="color: #c00000;">100</span>); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">private</span> <span class="keyword" style="font-weight: bold; color: #006699;">void</span> smoothScrollTo(<span class="keyword" style="font-weight: bold; color: #006699;">int</span> destX,<span class="keyword" style="font-weight: bold; color: #006699;">int</span> destY) </span> - <span style="color: black;"> { </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">int</span> scrollX = getScrollX(); </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">int</span> scrollY = getScrollY(); </span> - <span style="color: black;"> Log.d(TAG,<span class="string" style="color: blue;">&#8220;scrollX=&#8221;</span>+scrollX+<span class="string" style="color: blue;">&#8220;,scrollY=&#8221;</span>+scrollY); </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">int</span> deltaX = destX-scrollX; </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">int</span> deltaY = destY-scrollY; </span> - <span style="color: black;"> mScroller.startScroll(scrollX,scrollY,deltaX, deltaY, <span class="number" style="color: #c00000;">1000</span>); </span> - <span style="color: black;"> invalidate(); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> <span class="annotation" style="color: #646464;">@Override</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">public</span> <span class="keyword" style="font-weight: bold; color: #006699;">void</span> draw(Canvas canvas) </span> - <span style="color: black;"> { </span> - <span style="color: black;"> Log.i(TAG,<span class="string" style="color: blue;">&#8220;MyView&#8212;&#8212;>draw run&#8221;</span>); </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">super</span>.draw(canvas); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> <span class="annotation" style="color: #646464;">@Override</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">protected</span> <span class="keyword" style="font-weight: bold; color: #006699;">void</span> onDraw(Canvas canvas) </span> - <span style="color: black;"> { </span> - <span style="color: black;"> Log.i(TAG,<span class="string" style="color: blue;">&#8220;MyView&#8212;&#8212;>onDraw run&#8221;</span>); </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">super</span>.onDraw(canvas); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="annotation" style="color: #646464;">@Override</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">protected</span> <span class="keyword" style="font-weight: bold; color: #006699;">void</span> dispatchDraw(Canvas canvas) </span> - <span style="color: black;"> { </span> - <span style="color: black;"> Log.i(TAG,<span class="string" style="color: blue;">&#8220;MyView&#8212;&#8212;>dispatchDraw run&#8221;</span>); </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">super</span>.dispatchDraw(canvas); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="annotation" style="color: #646464;">@Override</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">protected</span> <span class="keyword" style="font-weight: bold; color: #006699;">boolean</span> drawChild(Canvas canvas, View child, <span class="keyword" style="font-weight: bold; color: #006699;">long</span> drawingTime) </span> - <span style="color: black;"> { </span> - <span style="color: black;"> Log.i(TAG,<span class="string" style="color: blue;">&#8220;MyView&#8212;&#8212;>drawChild run&#8221;</span>); </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">return</span> <span class="keyword" style="font-weight: bold; color: #006699;">super</span>.drawChild(canvas, child, drawingTime); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="annotation" style="color: #646464;">@Override</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">public</span> <span class="keyword" style="font-weight: bold; color: #006699;">void</span> computeScroll() </span> - <span style="color: black;"> { </span> - <span style="color: black;"> Log.i(TAG,<span class="string" style="color: blue;">&#8220;MyView&#8212;&#8212;>computeScroll run&#8221;</span>); </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">if</span>(mScroller != <span class="keyword" style="font-weight: bold; color: #006699;">null</span>) </span> - <span style="color: black;"> { </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">if</span>(mScroller.computeScrollOffset()) </span> - <span style="color: black;"> { </span> - <span style="color: black;"> scrollTo(mScroller.getCurrX(),mScroller.getCurrY()); </span> - <span style="color: black;"> Log.d(TAG,<span class="string" style="color: blue;">&#8220;scrollX=&#8221;</span>+getScrollX()+<span class="string" style="color: blue;">&#8220;,scrollY=&#8221;</span>+getScrollY()); </span> - <span style="color: black;"> postInvalidate(); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> } </span> - <span style="color: black;"> } </span> - <span style="color: black;">} </span> </div> MyImageView: <div class="dp-highlighter bg_java"> <div class="bar"> <div class="tools" style="color: silver;"> **[java]** [view plain](http://blog.csdn.net/chdjj/article/details/41678897#)[copy](http://blog.csdn.net/chdjj/article/details/41678897#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/539577)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/539577/fork) <div> </div> </div> </div> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">package</span> com.example.scrollerdemo; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">import</span> android.content.Context; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">import</span> android.graphics.Canvas; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">import</span> android.util.AttributeSet; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">import</span> android.util.Log; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">import</span> android.widget.ImageView; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">public</span> <span class="keyword" style="font-weight: bold; color: #006699;">class</span> MyImageView <span class="keyword" style="font-weight: bold; color: #006699;">extends</span> ImageView </span> - <span style="color: black;">{ </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">private</span> <span class="keyword" style="font-weight: bold; color: #006699;">static</span> <span class="keyword" style="font-weight: bold; color: #006699;">final</span> String TAG = <span class="string" style="color: blue;">&#8220;TEST&#8221;</span>; </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">public</span> MyImageView(Context context) </span> - <span style="color: black;"> { </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">super</span>(context); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">public</span> MyImageView(Context context, AttributeSet attrs) </span> - <span style="color: black;"> { </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">super</span>(context, attrs); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> <span class="annotation" style="color: #646464;">@Override</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">protected</span> <span class="keyword" style="font-weight: bold; color: #006699;">void</span> onDraw(Canvas canvas) </span> - <span style="color: black;"> { </span> - <span style="color: black;"> Log.i(TAG,<span class="string" style="color: blue;">&#8220;myImageView&#8212;->onDraw run&#8221;</span>); </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">super</span>.onDraw(canvas); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="annotation" style="color: #646464;">@Override</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">public</span> <span class="keyword" style="font-weight: bold; color: #006699;">void</span> computeScroll() </span> - <span style="color: black;"> { </span> - <span style="color: black;"> Log.i(TAG,<span class="string" style="color: blue;">&#8220;myImageView&#8212;->computeScroll run&#8221;</span>); </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">super</span>.computeScroll(); </span> - <span style="color: black;"> } </span> - <span style="color: black;">} </span> </div> <div> 我们根据上面三个自定义view做一个布局,外层是MyLinearLayout,中间是MyView,最里面是一个MyImageView. </div> <div> activity_main.xml: </div> <div class="dp-highlighter bg_java"> <div class="bar"> <div class="tools" style="color: silver;"> **[java]** [view plain](http://blog.csdn.net/chdjj/article/details/41678897#)[copy](http://blog.csdn.net/chdjj/article/details/41678897#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/539577)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/539577/fork) <div> </div> </div> </div> - <span style="color: black;"><LinearLayout xmlns:android=<span class="string" style="color: blue;">&#8220;http://schemas.android.com/apk/res/android&#8221;</span> </span> - <span style="color: black;"> android:layout_width=<span class="string" style="color: blue;">&#8220;match_parent&#8221;</span> </span> - <span style="color: black;"> android:layout_height=<span class="string" style="color: blue;">&#8220;match_parent&#8221;</span> </span> - <span style="color: black;"> android:orientation=<span class="string" style="color: blue;">&#8220;vertical&#8221;</span> > </span> - <span style="color: black;"> <com.example.scrollerdemo.MyLinearLayout </span> - <span style="color: black;"> xmlns:tools=<span class="string" style="color: blue;">&#8220;http://schemas.android.com/tools&#8221;</span> </span> - <span style="color: black;"> android:layout_width=<span class="string" style="color: blue;">&#8220;match_parent&#8221;</span> </span> - <span style="color: black;"> android:layout_height=<span class="string" style="color: blue;">&#8220;match_parent&#8221;</span> </span> - <span style="color: black;"> android:background=<span class="string" style="color: blue;">&#8220;#ffaaff&#8221;</span> </span> - <span style="color: black;"> tools:context=<span class="string" style="color: blue;">&#8220;com.example.scrollerdemo.MainActivity&#8221;</span> > </span> - <span style="color: black;"> <com.example.scrollerdemo.MyView </span> - <span style="color: black;"> android:id=<span class="string" style="color: blue;">&#8220;@+id/mv&#8221;</span> </span> - <span style="color: black;"> android:layout_width=<span class="string" style="color: blue;">&#8220;200dp&#8221;</span> </span> - <span style="color: black;"> android:layout_height=<span class="string" style="color: blue;">&#8220;200dp&#8221;</span> </span> - <span style="color: black;"> android:layout_marginLeft=<span class="string" style="color: blue;">&#8220;50dp&#8221;</span> </span> - <span style="color: black;"> android:layout_marginTop=<span class="string" style="color: blue;">&#8220;100dp&#8221;</span> </span> - <span style="color: black;"> android:background=<span class="string" style="color: blue;">&#8220;@android:color/darker_gray&#8221;</span> </span> - <span style="color: black;"> android:orientation=<span class="string" style="color: blue;">&#8220;vertical&#8221;</span> > </span> - <span style="color: black;"> <com.example.scrollerdemo.MyImageView </span> - <span style="color: black;"> android:layout_width=<span class="string" style="color: blue;">&#8220;wrap_content&#8221;</span> </span> - <span style="color: black;"> android:layout_height=<span class="string" style="color: blue;">&#8220;wrap_content&#8221;</span> </span> - <span style="color: black;"> android:src=<span class="string" style="color: blue;">&#8220;@drawable/ic_launcher&#8221;</span> /> </span> - <span style="color: black;"> </com.example.scrollerdemo.MyView> </span> - <span style="color: black;"> </com.example.scrollerdemo.MyLinearLayout> </span> - <span style="color: black;"></LinearLayout> </span> </div> 下面是MainActivity的代码: <div class="dp-highlighter bg_java"> <div class="bar"> <div class="tools" style="color: silver;"> **[java]** [view plain](http://blog.csdn.net/chdjj/article/details/41678897#)[copy](http://blog.csdn.net/chdjj/article/details/41678897#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/539577)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/539577/fork) <div> </div> </div> </div> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">package</span> com.example.scrollerdemo; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">import</span> android.app.Activity; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">import</span> android.os.Bundle; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">import</span> android.view.View; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">import</span> android.view.View.OnClickListener; </span> - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">public</span> <span class="keyword" style="font-weight: bold; color: #006699;">class</span> MainActivity <span class="keyword" style="font-weight: bold; color: #006699;">extends</span> Activity <span class="keyword" style="font-weight: bold; color: #006699;">implements</span> OnClickListener </span> - <span style="color: black;">{ </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">private</span> MyView mv = <span class="keyword" style="font-weight: bold; color: #006699;">null</span>; </span> - <span style="color: black;"> </span> - <span style="color: black;"> <span class="annotation" style="color: #646464;">@Override</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">protected</span> <span class="keyword" style="font-weight: bold; color: #006699;">void</span> onCreate(Bundle savedInstanceState) </span> - <span style="color: black;"> { </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">super</span>.onCreate(savedInstanceState); </span> - <span style="color: black;"> setContentView(R.layout.activity_main); </span> - <span style="color: black;"> </span> - <span style="color: black;"> mv = (MyView) findViewById(R.id.mv); </span> - <span style="color: black;"> mv.setOnClickListener(<span class="keyword" style="font-weight: bold; color: #006699;">this</span>); </span> - <span style="color: black;"> } </span> - <span style="color: black;"> <span class="annotation" style="color: #646464;">@Override</span> </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">public</span> <span class="keyword" style="font-weight: bold; color: #006699;">void</span> onClick(View v) </span> - <span style="color: black;"> { </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">switch</span> (v.getId()) </span> - <span style="color: black;"> { </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">case</span> R.id.mv:<span class="comment" style="color: #008200;">//点击时触发滚动效果</span> </span> - <span style="color: black;"> mv.testSmoothScroll(); </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">break</span>; </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">default</span>: </span> - <span style="color: black;"> <span class="keyword" style="font-weight: bold; color: #006699;">break</span>; </span> - <span style="color: black;"> } </span> - <span style="color: black;"> } </span> - <span style="color: black;">} </span> </div> 代码很简单,不必过多介绍,下面看显示效果: </div> <div> ![](http://img.blog.csdn.net/20141202145938259?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2hkamo=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 打开logcat查看日志: ...

2014年12月3日 · 25 分钟 · 天边的星星

Android 文字环绕 图文混排 支持Span折叠

先直接上效果图 上图为实现目标,实现了Android图文混排,文字环绕,支持Span的识别,表情的嵌入,支持文字字体大小的设置等。 由于项目中需要用到图文混排技术,在此稍微研究了两天,出来一个效果还算不错的东西 图文混排技术,在不少Android应用中都已经实现,说穿了其实就是两个TextView加一个ImageView的布局罢了,代码里面实现下String的剪切就可以了,不过我这里的这个除了要实现混排效果外,还要支持Span,支持表情等,这就有点麻烦了。下面慢慢分解。先贴出RichTextImageView的布局。 <?xml version=”1.0″ encoding=”utf-8″?> <com.demonzym.richtextdemo.RichTextImageView xmlns:android=”http://schemas.android.com/apk/res/android” android:layout_width=”fill_parent” android:layout_height=”fill_parent” android:orientation=”vertical” android:id=”@+id/richview” > <LinearLayout android:id=”@+id/linearLayout1″ android:layout_width=”fill_parent” android:layout_height=”wrap_content” > <RelativeLayout android:id=”@+id/layout_preimage_isgif_left” android:layout_width=”wrap_content” android:layout_height=”wrap_content” android:layout_weight=”0″ android:visibility=”gone” > ...

2014年12月3日 · 3 分钟 · 天边的星星

Android onTouchEvent, onClick及onLongClick的调用机制

针对屏幕上的一个View控件,Android如何区分应当触发onTouchEvent,还是onClick,亦或是onLongClick事件? 在Android中,一次用户操作可以被不同的View按次序分别处理,并将完全响应了用户一次UI操作称之为消费了该事件(consume),那么Android是按什么次序将事件传递的呢?又在什么情况下判定为消费了该事件? 搞清楚这些问题对于编写出能正确响应UI操作的代码是很重要的,尤其当屏幕上的不同View需要针对此次UI操作做出各种不同响应的时候更是如此,一个典型例子就是用户在桌面上放置了一个Widget,那么当用户针对widget做各种操作时,桌面本身有的时候要对用户的操作做出响应,有时忽略。只有搞清楚事件触发和传递的机制才有可能保证在界面布局非常复杂的情况下,UI控件仍然能正确响应用户操作。 1. onTouchEvent onTouchEvent中要处理的最常用的3个事件就是:ACTION_DOWN、ACTION_MOVE、ACTION_UP。 这三个事件标识出了最基本的用户触摸屏幕的操作,含义也很清楚。虽然大家天天都在用它们,但是有一点请留意,ACTION_DOWN事件作为起始事件,它的重要性是要超过ACTION_MOVE和ACTION_UP的,如果发生了ACTION_MOVE或者ACTION_UP,那么一定曾经发生了ACTION_DOWN。 从Android的源代码中能看到基于这种不同重要性的理解而实现的一些交互机制,SDK中也有明确的提及,例如在ViewGroup的onInterceptTouchEvent方法中,如果在ACTION_DOWN事件中返回了true,那么后续的事件将直接发给onTouchEvent,而不是继续发给onInterceptTouchEvent。 2. onClick、onLongClick与onTouchEvent 曾经看过一篇帖子提到,如果在View中处理了onTouchEvent,那么就不用再处理onClick了,因为Android只会触发其中一个方法。这个理解是不太正确的,针对某个view,用户完成了一次触碰操作,显然从传感器上得到的信号是手指按下和抬起两个操作,我们可以理解为一次Click,也可以理解为发生了一次ACTION_DOWN和ACTION_UP,那么Android是如何理解和处理的呢? 在Android中,onClick、onLongClick的触发是和ACTION_DOWN及ACTION_UP相关的,在时序上,如果我们在一个View中同时覆写了onClick、onLongClick及onTouchEvent的话,onTouchEvent是最先捕捉到ACTION_DOWN和ACTION_UP事件的,其次才可能触发onClick或者onLongClick。主要的逻辑在View.java中的onTouchEvent方法中实现的: case MotionEvent.ACTION_DOWN: mPrivateFlags |= PRESSED; refreshDrawableState(); if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) { postCheckForLongClick(); } break; case MotionEvent.ACTION_UP: if ((mPrivateFlags & PRESSED) != 0) { boolean focusTaken = false; if (isFocusable() && isFocusableInTouchMode() && !isFocused()) { focusTaken = requestFocus(); } if (!mHasPerformedLongPress) { if (mPendingCheckForLongPress != null) { removeCallbacks(mPendingCheckForLongPress); } if (!focusTaken) { performClick(); } } … break; 可以看到,Click的触发是在系统捕捉到ACTION_UP后发生并由performClick()执行的,performClick里会调用先前注册的监听器的onClick()方法: public boolean performClick() { … if (mOnClickListener != null) { playSoundEffect(SoundEffectConstants.CLICK); mOnClickListener.onClick(this); return true; ...

2014年12月2日 · 2 分钟 · 天边的星星

在Android實作HTML TextView與AutoLink使用的建議方式

Android的TextView除了可以用來顯示文字資料之外,還可以使用HTML語法來調整文字的樣式和文字超連結,無需特地去使用WebView。只是一旦使用TextView製作超連結,該TextView就會變得難以控制,因此有幾個特性應該是設計師必須事先知道的。 TextView顯示HTML 要使用TextView顯示HTML的作法很簡單,只要用以下方式來setText即可。 ``` textView.setText(Html.fromHtml("HTML語法字串")); ``` 例如: ``` textView.setText(Html.fromHtml("歡迎大家來到<big><font color=\"#FF0000\"><b>MagicLen</b></font></big>,本站網址如下:<br/><br/><a href=\"http://magiclen.org/\">http://magiclen.org/</a>")); ``` 結果如下: ...

2014年12月1日 · 14 分钟 · 天边的星星

Android 上的 HttpClient 的 Cookie 存取策略

`BasicHttpParams params = ``new` `BasicHttpParams();` `// Set the timeout in milliseconds until a connection is established. ` `HttpConnectionParams.setConnectionTimeout(params, TIMEOUT_CONNECTION);` `// Set the default socket timeout (SO_TIMEOUT) ` `// in milliseconds which is the timeout for waiting for data. ` `HttpConnectionParams.setSoTimeout(params, TIMEOUT_SOCKET); ` `ConnManagerParams.setMaxTotalConnections(params, ``5``);` `ConnManagerParams.setTimeout(params, TIMEOUT_TOTAL);` `client = ``new` `DefaultHttpClient(params);` `CookieStore cookieStore = ``new` `BasicCookieStore();` `//Bind custom cookie store to the local context` `client.setCookieStore(cookieStore);` `CookieSpecFactory csf = ``new` `CookieSpecFactory() { ` `public` `CookieSpec newInstance(HttpParams params) {` ` ``return` `new` `BrowserCompatSpec() {` ` ``@Override` ` ``public` `void` `validate(Cookie cookie, CookieOrigin origin) ``throws` `MalformedCookieException ` ` ``{` ` ``// Oh, I am easy` ` ``// allow all cookies` ` ``//log.debug("custom validate");` ` ``}` ` ``};` `}` `};` `client.getCookieSpecs().register(``"oschina"``, csf);` `client.getParams().setParameter(ClientPNames.COOKIE_POLICY, ``"oschina"``);` `client.getParams().setParameter(CookieSpecPNames.SINGLE_COOKIE_HEADER, ``true``);` 当然下面设置也可以,直接运行下就能看到结果。。 /** * <span class="s1">@param</span> url * :交互服务器的URL地址 * <span class="s1">@param</span> pairs * :交互所带的参数 * <span class="s1">@return</span> JSONObject:从服务器获取的字符串 */ <span class="s2">public</span> <span class="s2">static</span> String httpServicePostString(String url, List<BasicNameValuePair> pairs, Context context) { HttpPost httpPost = <span class="s2">new</span> HttpPost(url); DefaultHttpClient httpClient = <span class="s2">new</span> DefaultHttpClient(); Log.d(<span class="s3">&#8220;cat&#8221;</span>, <span class="s3">&#8220;out response=&#8221;</span> + httpPost.getURI() + <span class="s3">&#8221; &#8220;</span> + pairs.toString()); <span class="s2">try</span> { httpPost.setEntity(<span class="s2">new</span> UrlEncodedFormEntity(pairs, HTTP.<span class="s4">UTF_8</span>)); } <span class="s2">catch</span> (UnsupportedEncodingException e) { e.printStackTrace(); } CookieStore cookieStore = <span class="s2">new</span> BasicCookieStore(); httpClient.setCookieStore(cookieStore); <span class="s2">try</span> { HttpResponse response = httpClient.execute(httpPost); <span class="s2">if</span> (response.getStatusLine().getStatusCode() == HttpStatus.<span class="s4">SC_OK</span>) { HttpEntity httpEntity = response.getEntity(); <span class="s2">if</span> (httpEntity != <span class="s2">null</span>) { CookieStore c = httpClient.getCookieStore(); List<Cookie> list = c.getCookies(); <span class="s2">for</span> (Cookie cookie : list) { Log.e(HttpService.<span class="s2">class</span>.getName(), <span class="s3">&#8220;cookie=&#8221;</span> + cookie.getName()); Log.e(HttpService.<span class="s2">class</span>.getName(), Log.e(HttpService.<span class="s2">class</span>.getName(), SharedPreferencesUtils sharePrefenrences = <span class="s2">new</span> SharedPreferencesUtils(); sharePrefenrences.saveCookie(context, cookie.getValue()); } Header[] headers = response.getAllHeaders(); <span class="s2">for</span> (Header header : headers) { Log.e(HttpService.<span class="s2">class</span>.getName(), <span class="s3">&#8220;head=&#8221;</span> + header.getName()); } <span class="s2">if</span> (response.getFirstHeader(<span class="s3">&#8220;Set-Cookie&#8221;</span>) != <span class="s2">null</span>) { String set_cookie = response.getFirstHeader( <span class="s3">&#8220;Set-Cookie&#8221;</span>).getValue(); Log.e(HttpService.<span class="s2">class</span>.getName(), <span class="s3">&#8220;set_cookie=&#8221;</span> + set_cookie); SharedPreferencesUtils sharePrefenrences = <span class="s2">new</span> SharedPreferencesUtils(); sharePrefenrences.saveCookie(context, set_cookie); } InputStream inputStream = httpEntity.getContent(); BufferedReader bufferReader = <span class="s2">new</span> BufferedReader( <span class="s2">new</span> InputStreamReader(inputStream), <span class="s4">i</span>); String returnStr = <span class="s3">&#8220;&#8221;</span>; String readLine = <span class="s2">null</span>; <span class="s2">while</span> ((readLine = bufferReader.readLine()) != <span class="s2">null</span>) { returnStr = returnStr + readLine; } inputStream.close(); bufferReader.close(); Log.d(<span class="s3">&#8220;cat&#8221;</span>, <span class="s3">&#8220;returnStr=&#8221;</span> + returnStr); <span class="s2">return</span> returnStr; } } } <span class="s2">catch</span> (ClientProtocolException e) { e.printStackTrace(); returnnull<span class="s5">;</span> } <span class="s2">catch</span> (IOException e) { e.printStackTrace(); returnnull<span class="s5">;</span> } returnnull<span class="s5">;</span> }

2014年11月23日 · 2 分钟 · 天边的星星

Android获得手机所有应用(非系统)、正在运行的Service和Activity

Android中获得系统运行的进程、获得当前正在运行的service、 获得当前正在运行的activity、 获得最近运行的应用、获取手机内所有应用(非系统应用) 直接上代码,布局文件就是一个TextView 直接创建Activity后删除Activity中所有内容,复制下面代码直接就能运行 private TextView txtDes = null; @Override protected void onCreate(Bundle savedInstanceState) { // setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);//竖屏 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);// 强制为横屏 super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); txtDes = (TextView) findViewById(R.id.textdes); } @Override protected void onResume() { super.onResume(); Log.w(“sss”, “onResume”); StringBuffer str = new StringBuffer(); List listData = getAllApps(this); str.append(“应用数量:” + listData.size()); str.append(“\n”); for (PackageInfo packageInfo : listData) { str.append(“” + packageInfo.packageName); str.append(“\n”); str.append(“” packageInfo.applicationInfo .loadLabel(getPackageManager())); str.append(“\n”); ActivityInfo[] list; try { list = getPackageManager().getPackageInfo( packageInfo.packageName, PackageManager.GET_ACTIVITIES).activities; if (list != null) { str.append(“Activity数量:” + list.length); str.append(“\n”); for (ActivityInfo activityInfo : list) { str.append(activityInfo.packageName); str.append(“\n”); str.append(activityInfo.name); str.append(“\n”); str.append(“activityInfo.screenOrientation=” activityInfo.screenOrientation); str.append(“\n”); str.append(“activityInfo.configChanges=” activityInfo.configChanges); str.append(“\n”); } } } catch (NameNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } } txtDes.setText(str); } @Override public void onConfigurationChanged(Configuration newConfig) { // TODO Auto-generated method stub super.onConfigurationChanged(newConfig); StringBuffer str = new StringBuffer(); List listData = getAllApps(this); str.append(“应用数量:” + listData.size()); str.append(“\n”); for (PackageInfo packageInfo : listData) { str.append(“” + packageInfo.packageName); str.append(“\n”); str.append(“” ...

2014年11月21日 · 2 分钟 · 天边的星星

Android 网络编程之—HttpClient 与 HttpURLConnection 共用cookie

HttpClient 与 HttpURLConnection 共用 SessionId HttpClient 与 HttpUrlConnection 是Android 中HTTP操作最常见的访问方式。在一个应用程序中有时候会用到这两种方式,如何能让他们共用Cookie,让客户端访问服务器保持Session进行通信。 针对httpClient 和HttpUrlConnection 获取和发送Cookie,主要是sessionID的共享。 httpClient获取及发送Session 值: **[java]** [view plain](http://blog.csdn.net/jmq_0000/article/details/24921983#)[copy](http://blog.csdn.net/jmq_0000/article/details/24921983#)[print](http://blog.csdn.net/jmq_0000/article/details/24921983#)[?](http://blog.csdn.net/jmq_0000/article/details/24921983#) <div> </div> </div> - <span style="color: #ffffff;"> </span> - <span style="color: #ffffff;"> </span> - <span style="color: #ffffff;"> HttpPost httpPost = <span class="keyword" style="font-weight: bold; color: #00cc00;">new</span> HttpPost(url); </span> - <span style="color: #ffffff;"> </span> - <span style="color: #ffffff;"> <span class="comment" style="color: #cccccc;">// 将SessionId发给服务器</span> </span> - <span style="color: #ffffff;"> <span class="keyword" style="font-weight: bold; color: #00cc00;">if</span>(<span class="keyword" style="font-weight: bold; color: #00cc00;">null</span> != mSESSIONID){ </span> - <span style="color: #ffffff;"> httpPost.setHeader(<span class="string" style="color: #ff9900;">&#8220;Cookie&#8221;</span>, <span class="string" style="color: #ff9900;">&#8220;SESSIONID=&#8221;</span> + mSESSIONID); </span> - <span style="color: #ffffff;"> } </span> - <span style="color: #ffffff;"> </span> - <span style="color: #ffffff;"> DefaultHttpClient httpClient = <span class="keyword" style="font-weight: bold; color: #00cc00;">new</span> DefaultHttpClient(); </span> - <span style="color: #ffffff;"> httpResponse = httpClient.execute(httpPost); </span> - <span style="color: #ffffff;"> <span class="keyword" style="font-weight: bold; color: #00cc00;">if</span> (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { </span> - <span style="color: #ffffff;"> HttpEntity entity = httpResponse.getEntity(); </span> - <span style="color: #ffffff;"> </span> - <span style="color: #ffffff;"> CookieStore mCookieStore = httpClient.getCookieStore(); </span> - <span style="color: #ffffff;"> List<Cookie> cookies = mCookieStore.getCookies(); </span> - <span style="color: #ffffff;"> <span class="comment" style="color: #cccccc;">//这里是读取指定Cookie 的值</span> </span> - <span style="color: #ffffff;"> <span class="keyword" style="font-weight: bold; color: #00cc00;">for</span> (<span class="keyword" style="font-weight: bold; color: #00cc00;">int</span> i = <span class="number" style="color: #c00000;"></span>; i < cookies.size(); i++) { </span> - <span style="color: #ffffff;"> <span class="keyword" style="font-weight: bold; color: #00cc00;">if</span> (<span class="string" style="color: #ff9900;">&#8220;SESSIONID&#8221;</span>.equals(cookies.get(i).getName())) { </span> - <span style="color: #ffffff;"> mSESSIONID = cookies.get(i).getValue(); </span> - <span style="color: #ffffff;"> <span class="keyword" style="font-weight: bold; color: #00cc00;">break</span>; </span> - <span style="color: #ffffff;"> } </span> - <span style="color: #ffffff;"> </span> - <span style="color: #ffffff;"> } </span> - <span style="color: #ffffff;">} </span> 在程序中保存上面的sessionId ,或用全局变量,或者SharedPreferences 保存,看这个sessionId 的会话时间及程序业务。 ...

2014年11月21日 · 3 分钟 · 天边的星星