2012年2月10日星期五

模拟三星通讯录滑动触发开关

三星手机的通讯录中的滑动开关非常方便, 左右滑动即可打电话或者发短信, 而无需点开联系人的详细资料;
   

今天就利用自定义ListView来模拟实现这个功能; 基本思路如下: 基本思路:
  1. 判断动作是否为横向滑动, 是则拦截并执行自己的方法, 不是则按默认执行;
  2. 绑定滑动监听器
  3. 绘制滑动时的效果
先看下模拟的效果:

 

下面就一步一步来实现它:

 1. 创建一个名为TouchListView 的类, 继承自 ListView

public class TouchListView extends ListView { 
    // 判断开关向左还是向右的条件 
    private final float leftOffset = 1f / 3f
    private final float rightOffset = 2f / 3f
    // 判断动作是否为横向滑动的条件 
    private final float xRange = 20f
    private final float yRange = 100f;
    // 当前状态: 是否为滑动 
    private boolean isSliding = false;
    // 手指按下时的位置 
    private float sx, sy
    // 手指移动过程中的位置 
    private float mx, my
    // 手指抬起时的位置 
    private float fx;
    // 滑动动作的目标Item 
    private View touchedView
    // 目标Item在列表中的位置 
    private int position
    // 目标Item在数据库中的id 
    private long id;
    // 滑动开关监听器 
    private TriggerListener tl
    // 绘制文字和彩带用的画笔 
    private Paint textPaint; private Paint mPaint
}

还有个init()方法在构造函数里调用, 用来初始化画笔;
private void init() {
    // 初始化文字画笔 
    textPaint = new Paint();
    textPaint.setColor(Color.WHITE); 
    textPaint.setTextSize(25);
    textPaint.setTextAlign(Align.CENTER); 
    textPaint.setAntiAlias(true);
    // 初始化彩带画笔    
    mPaint = new Paint(); 
    mPaint.setAntiAlias(true); 
}

2. 判断动作是否为横向滑动, 并加以拦截: 
因为和触摸事件有关, 所以我们需要重写 onTouchEvent() 方法;
@Override
public boolean onTouchEvent(MotionEvent ev) {
    // 当手指在屏幕上移动时即时记录手指的位置, 下面很多地方都要用到
    if(ev.getAction() == MotionEvent.ACTION_MOVE) {
        mx = ev.getX();
        my = ev.getY();
    }
    if(isSliding) { // 若状态为滑动则拦截, 并执行滑动时的动作
        sliding(ev);
        // 在传递前将动作设置为"取消"即可实现拦截
        ev.setAction(MotionEvent.ACTION_CANCEL);
    } else {
        // 非滑动状态时检查是否开始滑动
        checkSlide(ev);
    }
    return super.onTouchEvent(ev);
}

3. 判断是否为滑动的方法 checkSlide();
private void checkSlide(MotionEvent ev) { 
    int action = ev.getAction(); 
    switch(action) { 
    case MotionEvent.ACTION_DOWN: 
        // 记录开始位置, 即手指按下的位置 
        sx = ev.getX(); 
        sy = ev.getY(); 
        break
    case MotionEvent.ACTION_MOVE: 
        // 计算当前位移 
        float dx = Math.abs(mx - sx); 
        float dy = Math.abs(my - sy); 
        if(dx > xRange && dy < yRange) {  // 若横向位移大于 xRange, 纵向位移小于 yRange 则算作开始横向滑动 
            // 获得手指按下处的 Item 
            position = pointToPosition((int)sx, (int)sy); 
            int firstPosition = this.getFirstVisiblePosition(); 
            touchedView = getChildAt(position - firstPosition); 
            if(touchedView != null) {   // 只有Item存在时才算作开始滑动, 若在空白处滑动则不算 
                Log.i("Notebook", "开始横向滑动"); 
                // 将滑动状态设置为 true 
                this.isSliding = true
                // 获得 Item 的 id, 设置监听器时要用 
                id = getAdapter().getItemId(position); 
                // ListView 默认是只在上下滚动时才刷新, 所以这里要强制刷新它     
                this.postInvalidate(); 
            } 
        } 
        break
    } 
}

4. 进入滑动状态后要执行的动作 sliding():
private void sliding(MotionEvent ev) { 
    if(ev.getAction() == MotionEvent.ACTION_UP) { // 滑动时, 手指抬起代表滑动结束 
        // 首先, 重置滑动状态为 false 
        this.isSliding = false
        Log.i("Notebook", "滑动结束"); 
        // 记录手指抬起的位置 this.fx = ev.getX(); 
        // 抬起后判断开关的方向, 向左, 向右, 或是空 
        int width = touchedView.getWidth(); 
        int direction = TriggerListener.NONE
        if(fx > width * rightOffset) direction = TriggerListener.RIGHT;     
        else if(fx < width * leftOffset) direction = TriggerListener.LEFT
        // 确定方向后执行监听器定义的方法 
        if(tl != null) { 
            tl.onTrigger(direction, position, id); 
        }
    }
}

5. 设置动画效果(向左滑变红, 向右滑变红, 同时透明度改变); 需要重写 drawChild(); 方法
@Override 
protected boolean drawChild(Canvas canvas, View child, long drawingTime) { 
    boolean b = super.drawChild(canvas, child, drawingTime);
    // 画在原来的图像上方 
    if(isSliding) {        // 滑动时则开始绘制 // 若不是目标对象则按默认动作返回 
        if(touchedView != childreturn b; 
        Log.i("Notebook", "开始绘图"); 
        // 得到绘图所需基本数据 
        int top = touchedView.getTop(); 
        int width = touchedView.getWidth(); 
        int height = touchedView.getHeight(); 
        // 生成彩带 
        LinearGradient shader = new LinearGradient(mx - width / 2, 0, mx + width / 2, 0, Color.rgb(11,115,6), Color.RED, Shader.TileMode.CLAMP); 
        mPaint.setShader(shader); 
        // 计算手指偏移量(相对于中心) 
        float offset = Math.abs(mx - width / 2f) / (width / 2f); 
        // 设置透明度 
        textPaint.setAlpha((int) (255 * offset)); 
        mPaint.setAlpha((int) (200 + 55 * offset)); 
        // 移动画布前保存 
        canvas.save(); 
        // 将画布移动到要画的条目处 
        canvas.translate(0, top); 
        // 画彩带; 
        canvas.drawRect(0, 0, width, height, mPaint);
        // 画文字 
        String text = ""
        if(mx > width * rightOffset) text = "编辑"
        else if(mx < width * leftOffset) text = "删除"
        canvas.drawText(text, width / 2f, height / 2f, textPaint); 
        // 还原画布 
        canvas.restore(); 
        // 刷新View 
        this.postInvalidate(); 
    } 
    return b;
}

6. 绑定监听器的方法
/**
 * 绑定滑动监听器到 ListView
 * @param tl 滑动监听器
 */
public void setTriggerListener(TriggerListener tl) {
    this.tl = tl;
}

7. 监听器接口
public interface TriggerListener { 
    public static final int NONE = -1
    public static final int LEFT = 0
    public static final int RIGHT = 1
    /**      
     * 滑动操作的监听器     
     * @param direction 滑动操作的方向, 左, 右, 无     
     * @param Position 该条目在List中的位置     
     * @param id 该条目在数据库中的id     
     */ 
    public void onTrigger(int direction, int Position, long id); 
}

使用时和普通的ListView没什么区别, 只要记得实现TriggerListener接口绑定监听器就行了;

2011年1月21日星期五

Chrome 应用分享

 前 言                                                                                            

      准备写三篇日志, 一篇关于 Chrome 浏览器的, 一篇关于 Google 各项服务的, 还有一篇是 Windows 7 的. 毕竟大家都准备要买电脑了嘛, 我现在就将我使用时发现的一些软件和技巧来与大家分享.

 Chrome                                                                                       

      首先是浏览器, 以我目前使用的 Chrome dev (谷歌浏览器开发者版) 为例.

      一个浏览器是否强大从外观上往往很难看得出来,  尤其是像 Chrome 这样外观简单到极致的浏览器更是如此, 但决不可以就此小看了 Chrome 的能力. 各种插件和应用能使 Chrome 变得几乎无所不能.

 新标签页                                                                                        

      我们从 Chrome 的新标签页开始谈起. 下面是默认的新标签页:

默认的新标签页

      这就是一个典型的 Chrome 式新标签, 浮动的收藏夹加最经常访问的页面, 很直观是不是?可我却不太喜欢这样, 因为这两者在很大程度上是重复了, 网址几乎是相同的. 于是我就将新标签页按照我的习惯进行了重新布置. 下面是现在的样子:

现在的新标签页

      现在新标签页上的主题元素已经变成了应用程序. 或许你认为只有安装在 Windows 下的那些软件才叫应用程序, 但互联网的发展带来了 HTML5, 这就使得我们可以制作基于浏览器的应用程序, 而不必在乎平台的限制. (抱歉, 一不小心扯远了) 下面我就告诉大家如何用各种应用和插件来增强浏览器的性能.

 应用程序简介                                                                                

      也许你目前分不太清应用和插件的区别, 其实应用一般有自己完整的界面, 向用户提供一种或几种服务, 有些甚至可以在没有网络的情况下运行, 你也可以将你喜欢的应用程序做成小图标放在桌面上, 不启动浏览器直接使用, 效果如下:

应用程序图标

而插件则是依附于浏览器, 更像是对浏览器某种形式上的功能的扩充.

      Google 的应用我就不在这篇文章中介绍了, 下面会有一篇文章单独介绍 Google 服务.

 Quick Note                                                                                 

       顾名思义, 这就是个记事本的应用. 但和 Windows 的记事本比起来我更喜欢 Quick Note. 它的数据储存在云端, 所以在任何一台电脑上你都可以随时翻看你做过的记录, 同时它还支持离线使用. 下面我们就来看一下它的主界面:
Quick Note 主界面

      左侧以标题的形式列出了所有的条目, 右侧是条目的具体内容. 如果是做摘录就更简单了, 如图:

截取网络内容摘要


      选中想摘录的内容, 右击, 然后选 Add selection to note 就行了, 就是这么简单. 图像, 超链接, 按钮, 格式 ... 一切都会被原生态地保留下来, 非常实用.

 Ge.tt                                                                                             

       这是一个使用起来超简单的文件分享应用, 只需要注册一个帐号就可以进行文件分享了. 不像那些网盘有各种各样的限制. 它主要有以下几个特点:


            1. 简洁明了, 没有广告, 没有使用限制;
            2. 管理方便, 可以直观地看出文件的情况:
                      (被看了多少次 Views, 有几个人看 Visits, 被 下载了几次 Downlows );
            3.在上传的同时就可以进行分享了, 不必等待上传完成;

      对了, 还有图:

Ge.tt 的主界面, 非常简洁


      总之, 我觉得用起来很方便就是了.

 Office Web App                                                                         

      看图标就知道这是鼎鼎大名的 Microsoft Office 了, 微软要是还不推出点网络应用的话估计网络上的地盘都要被 Google 抢光了.

      言归正传, 这就是微软最新的在线办公应用. 如 果你有Live ID 的话就可以在线使用最新的 Office 2010, 并且可以将文件储存在微软的云上, 整整 25G胃口再大也该够用了吧. 和 Google 的 Google Doc 比起来还是微软的功能更多一些, 毕竟牌子比较老嘛. 下面是界面:

Office 2010 online

      不过我更喜欢用 Google Doc 因为 Microsoft 网站的载入速度实在是太慢了.

 Fixlr Editor                                                                                 

      最后是这个在线图像编辑器, 我以前就推荐过, 现在它也有应用版的了, 先看下界面:

pixlr的工作界面, 功能很全

       其实有很多人电脑上都装了 Photoshop 这样重量级的图像处理软件, 其实我觉得完全没有必要. Photoshop 中的大部分功能都太高端了根本用不到, 何必花力气去装那么一个大家伙.这款在线的图像编辑器, 具备 Ps 的一切常用功能, 启动迅速, 并且支持网络相册, 完全可以满足我们日常甚至某些非日常的工作需要了.

      反正我一直追求的就是 "简单" "快捷", 不管它的名气是大是小只要满足这个条件我就会去用, 毕竟现在好的创意大多来自新兴公司嘛.

      这篇有点长了, 插件还是留到下篇写吧.

2010年8月14日星期六

Chrome 优秀扩展推荐




     为浏览器添加合适的扩展可以成倍提高工作效率, 在烦躁的互联网时代更是如此. 以上的10个扩展是我浏览网页时必不可少的得力工具 (以上扩展均用于 Chrome, 附下载地址).

1. AdBlock                                                                                


      如今上网无论打开那个网站, 一定能看到就是广告. 特别是一些制作拙劣的网站, 广告更是多得眼花缭乱, 页面显得惨不忍睹. 在这种页面里苦苦寻找有用的信息, 想想都觉得累.
      
      于是这样一款优秀扩展便应运而生了, 在启动它的一瞬间我便有预感: 这个世界终于 清. 静. 了.
       
      呵呵, 下面我们来看一下实际效果:        
      
这是华军资讯的一个页面, 映入我们眼帘的是: 
广告 广告 广告 广告 广告 广告 广告 广告 有用信息


开启 AdBlock 后页面有了明显的改观, 广告几乎全都消失了,
 并且上面空出的位置也被填补上了

      因为 AdBlock 在页面载入前就已经开始对广告进行拦截, 所以不但能缩短网页载入的时间, 而且能够使我们将注意力更快地集中到有用的信息上, 而不是被广告所分散.

AdBlock 下载地址

2. AutoPager                                                                            



      烦躁的互联网时代使我们不愿意多等哪怕一秒钟, 那我们干脆把这翻页的一秒也给省了吧.



自动载入下一页的内容

      在我们浏览当前页的内容时, 它就会自动在后台加载下一页的内容. 而我们所要做的就是不停地滑滚轮~ 滑滚轮~ 滑滚轮~ 直到找到我们所需要的信息为止. 当然, 省去了翻页之苦, 看小说或者漫画时等下一页载入时那种抓狂的感觉也就不复存在了.

AutoPager 下载地址

3. Bubble Translate                                                                 


      (虚构)
     老师: 上网时碰到不认识的英文怎么办?
     小A : (挑起) 翻字典!
     老师: 回石器时代去!
     小B : (补充道) 查在线词典.
     老师: 有点麻烦, 有没有更简单的?
     小C : (满怀信心) 用金山词霸的划词翻译.
     老师: 很好, 那要是遇到阿拉伯文呢?
     小C : =_=||||||  , 不...不知道.
       我 : (冷静地起身) Bubble Translate.
     老师: 这才是正解, 不过这也足以表明你又偷偷上网了.
       我 : #-_-  , 答对也有错...


     写得无聊编个小故事玩儿, 编得无聊我也没办法, 因为我本来就是写得无聊才编的啊...
     
     呵呵, 转入正题. 大家都知道 Google 有强大的翻译工具 Google Translator, 不过每次都要新开一个标签, 还要将待翻译内容复制过去的确很麻烦. 要是能直接划词调用 Google Translator 就好了.


     Bubble Translate 的出现完美地实现了我们的愿望:


 任何语言, 只需轻轻一划...

     使用方法: 按住 Ctrl, 选定带翻译内容, 松开 Ctrl.

     这样就再也不必因为出现陌生的语言而转移我们的注意力了.

Bubble Translate 下载地址

4. Google Mail Checker

5. Google Notebook

6. Google Reader Notifier


     以上三个扩展, 介于使用 Google 服务的同学实在太少就不在此介绍了, 如有需要留言即可.

7. SearchPreview for Google                                                  


     相信大家都遇到过这样的情况, 在使用搜索引擎的过程中看到大量的搜索结果, 但其中混杂许多无用链接, 而且必须打开后才能发现.
     
     这无疑白白耗费了我们许多时间(无响应页面尤其如此), 而这款扩展则能使我们在点开连接前就对这条结果的优劣作出预先的判断, 从而减少无效的点击. 




显而易见, 在国内是上不了 Twitter 和 YouTube 的. 
就不必再点开这些链接了.

     有了它我们就再也不必为浪费时间去等一个无响应页面而懊恼了.

SearchPreview for Google  下载地址

8. Screen Capture                                                                                      

     这个截图工具作用很明显, 看看我上面那么多图片就知道了.


     它的优点: 方便快捷, 简单易用.


     它能提供三种截图方式: 
  • 当前可见区域截图;
  • 自定义区域截图;
  • 完整页面截图.

     使用效果如下图:



上不了也得上, 不过 Dakota Fanning 把 Twitter 注销了, Twitter 上就只剩我一个了
后来上了 Twitter 看着那 3 个 0 就觉得冷, 就不上 Twitter 了
再后来... 就没有再后来了...

     重点还是截图工具, 下面提供下载地址:

Screen Capture  下载地址
    
9. QuickSearch                                                                         


     这个重点推荐 ── 其中的一个功能 ── Image Viewer. 
     
     不知道你有没有过这样的经历, 一不小心遇到了这样的照片:


在网上随便找的啦

     想看得舒服点的话只有两种选择:
  • 侧着头看 (5, 6 张都这样脖子就废了);
  • 将显示器顺时针旋转 90° (别人会以为你疯了).
     心中是不是纠结无比? 


     不过有了这个扩展就再也不必纠结了, 不多说了, 直接上图:


脖子终于解放了
    
     单击灰色区域就会关闭照片浏览器, 单击编辑则会打开一个在线图片编辑器 (和 Photoshop 很像哦):

总之用得很顺手啦, 特别是对于我只有 256M 内存的脆弱的电脑来说,
 Photoshop 实在消受不起

     注意: 该扩展与第一个扩展 AdBlock 有冲突, 若出现图片无法打开的情况, 请关闭 AdBlock 后刷新页面重试, 我也向作者提出了这个 bug 希望能在下一个版本里有所改进.

QuickSearch   下载地址


10. 迅雷、快车、旋风专用链自动破解                                            


     这是给喜欢下载的同学准备的. 
    
     看到中意的资源想下的时候突然发现竟然是这个样子:

垄断啊...垄断啊...垄断啊...


     于是某个程序员终于看不下去了, 推出了这个扩展.


     从此, 不管是迅雷高速下载, 还是快车高速下载, 或者是旋风高速下载, 我想怎么下就怎么下. 
    
     世界更美好了一些.


迅雷、快车、旋风专用链自动破解  下载地址     


 End                                                                                           

     以上就是我目前在使用的所有扩展了.
    
     希望可以解决在浏览网页时遇到的一些问题, 提高我们在互联网上的工作效率.


     如果有任何疑问的话尽管留言, 我会尽力解决.


     Bye