Android网络:开发浏览器(四)——功能完善之长按网页图片菜单

    上述的历史和书签的功能已经实现。不过如果我们长时间按住图片,并不会出现如同UC中的一系列选项,我们可以来看看UC中的长按图片出现的菜单。

   

图10.2.9    UC中的长按图片菜单

   

    我们可以看到UC中可以识别出这个网页中的图片,那么它是如何做到的呢?

   

    我们仔细观察,可以发现它是触发了长时间按的事件,我的手机可以清楚的感受到在触发事件的同时有一个震动感,不知道各位的有没有。

   

    其实,WebView已经帮我们封装了一个函数,这个函数可以轻松的获取到我们点击的目标类型,包括一些额外的信息。这些额外的信息是什么?比如说,图片的额外信息就是这张图片的地址,手机号码的额外信息就是手机号,电子邮件的额外信息就是电子邮件字符串等等。

   

    现在我们要做的就是获取图片,包括的操作有查看图片、保存图片和查看属性这三项。其实我们可以通过创建上下文菜单来轻松的创建菜单,不过我不满足这些个效果,我更想要的是UC的那种效果。

   

   

    那么我们还是可以通过popupwindow这个类来实现弹出菜单的效果。

   

    我们将之前的ItemLongClickedPopWindow这个类进行修改:

   

package com.example.other;
 
import com.example.androidstudy_web.R;
 
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.PopupWindow;
 
public class ItemLongClickedPopWindow extends PopupWindow{
  
   /**
    * 书签条目弹出菜单
    * @value
    * {@value}
    * */
   public static final int FAVORITES_ITEM_POPUPWINDOW = 0;
   /**
    * 书签页面弹出菜单
    * @value
    * {@value}
    * */
   public static final int FAVORITES_VIEW_POPUPWINDOW = 1;
   /**
    * 历史条目弹出菜单
    * @value
    * {@value}
    * */
   public static final int HISTORY_ITEM_POPUPWINDOW = 3;
   /**
    * 历史页面弹出菜单
    * @value
    * {@value}
    * */
   public static final int HISTORY_VIEW_POPUPWINDOW = 4;
   /**
    * 图片项目弹出菜单
    * @value
    * {@value}
    * */
   public static final int IMAGE_VIEW_POPUPWINDOW = 5;
   /**
    * 超链接项目弹出菜单
    * @value
    * {@value}
    * */
   public static final int ACHOR_VIEW_POPUPWINDOW = 6;
  
    private LayoutInflater itemLongClickedPopWindowInflater;
    private View itemLongClickedPopWindowView;
    private Context context;
   
    private int type;
   
    /**
     * 构造函数
     * @param context 上下文
     * @param width 宽度
     * @param height 高度
     * */
    publicItemLongClickedPopWindow(Context context, int type, int width, int height){
       super(context);
       this.context = context;
       this.type = type;
      
       //创建
       this.initTab();
      
       //设置默认选项
       setWidth(width);
       setHeight(height);
       setContentView(this.itemLongClickedPopWindowView);
       setOutsideTouchable(true);
       setFocusable(true);
    }
   
   
    //实例化
    private void initTab(){
       this.itemLongClickedPopWindowInflater = LayoutInflater.from(this.context);
       switch(type){
       case FAVORITES_ITEM_POPUPWINDOW:
          this.itemLongClickedPopWindowView = this.itemLongClickedPopWindowInflater.inflate(R.layout.list_item_longclicked_favorites, null);
          break;
       case FAVORITES_VIEW_POPUPWINDOW:
          //对于书签内容弹出菜单,未作处理
          break;
       case HISTORY_ITEM_POPUPWINDOW:
          this.itemLongClickedPopWindowView = this.itemLongClickedPopWindowInflater.inflate(R.layout.list_item_longclicked_history, null);
          break;
       case HISTORY_VIEW_POPUPWINDOW:
          //对于历史内容弹出菜单,未作处理
          break;
       case ACHOR_VIEW_POPUPWINDOW:
          //超链接
          break;
       case IMAGE_VIEW_POPUPWINDOW:
          //图片
          this.itemLongClickedPopWindowView = this.itemLongClickedPopWindowInflater.inflate(R.layout.list_item_longclicked_img, null);
          break;
       }
      
}
 
    public View getView(int id){
       return this.itemLongClickedPopWindowView.findViewById(id);
    }
}

代码片段10.2.28 弹出菜单的实现

   

    自然需要的xml布局文件也是不可或缺的

   

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="5dp"
    android:orientation="vertical" >
   
    <TextView
       android:id="@+id/item_longclicked_viewImage"
       android:layout_width="match_parent"
       android:layout_height="20dp"
       android:textColor="@android:color/white"
       android:textSize="16sp"
       android:text="@string/viewImage"
       android:layout_marginLeft="15dp"
       android:layout_marginTop="20dp"
       android:layout_marginBottom="5dp"
       />
   
    <TextView
       android:id="@+id/item_longclicked_saveImage"
       android:layout_width="match_parent"
       android:layout_height="20dp"
       android:textColor="@android:color/white"
       android:textSize="16sp"
       android:text="@string/saveImage"
       android:layout_marginLeft="15dp"
       android:layout_marginTop="20dp"
       android:layout_marginBottom="5dp"
       />
   
    <TextView
       android:id="@+id/item_longclicked_viewImageAttributes"
       android:layout_width="match_parent"
       android:layout_height="20dp"
       android:textColor="@android:color/white"
       android:textSize="16sp"
       android:text="@string/viewImageAttributes"
       android:layout_marginLeft="15dp"
       android:layout_marginTop="20dp"
       android:layout_marginBottom="5dp"
       />
 
</LinearLayout>

代码片段10.2.29 xml图片弹出菜单布局文件

   

    这个布局文件的预览图如下:

   

图10.2.10   图片弹出菜单效果预览

   

    好了,定义好了弹出菜单,我们可以来看看如何让他出现了。

   

    之前已经提到过了WebView的getHitTestResult()的函数,现在我们来看下它的一些方法:

   

   

方法

描述

getType()

获取所选中目标的类型,可以是图片,超链接,邮件,电话等等

getExtra()

获取额外的信息

表10.2.1    getHitTestResult()函数的方法

   

    简要说下思路,根据这个函数获得目标类型,之后弹出不同的菜单即可。

    现在我们可以来看下代码,现在的代码比较简单,对布局没有进行判断,指定了布局判断为图片菜单。

   

@Override
      public boolean onLongClick(View v) {
         HitTestResult result = ((WebView) v).getHitTestResult();
         if (null == result)
            return false;
 
         int type = result.getType();
         if (type == WebView.HitTestResult.UNKNOWN_TYPE)
            return false;
 
         if (type == WebView.HitTestResult.EDIT_TEXT_TYPE) {
            // let TextViewhandles context menu
            return true;
         }
        
         final ItemLongClickedPopWindow itemLongClickedPopWindow = newItemLongClickedPopWindow(MainActivity.this, ItemLongClickedPopWindow.IMAGE_VIEW_POPUPWINDOW, 200, 250);
 
         // Setup custom handlingdepending on the type
         switch (type) {
         case WebView.HitTestResult.PHONE_TYPE:
            // 处理拨号
            break;
         case WebView.HitTestResult.EMAIL_TYPE:
            // 处理Email
            break;
         case WebView.HitTestResult.GEO_TYPE:
            // TODO
            break;
         case WebView.HitTestResult.SRC_ANCHOR_TYPE:
            // 超链接
            Log.d(DEG_TAG, "超链接");
            break;
         case WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE:
         case WebView.HitTestResult.IMAGE_TYPE:
            // 处理长按图片的菜单项
            Log.d(DEG_TAG, "图片");
            itemLongClickedPopWindow.showAtLocation(v, Gravity.TOP | Gravity.LEFT, 0, 0);
            break;
         default:
            break;
         }
         return true;
      }

代码片段10.2.30 长按事件的实现。

       

    这里的类似于WebView.HitTestResult.PHONE_TYPE这样的变量所指代的就是目标的类型,根据名字很容易就理解了。

   

    为了更方便各位查询,我在这里总结一下类型:

   

类型名

意义

WebView.HitTestResult.UNKNOWN_TYPE

未知类型

WebView.HitTestResult.PHONE_TYPE

电话类型

WebView.HitTestResult.EMAIL_TYPE

电子邮件类型

WebView.HitTestResult.GEO_TYPE

地图类型

WebView.HitTestResult.SRC_ANCHOR_TYPE

超链接类型

WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE

带有链接的图片类型

WebView.HitTestResult.IMAGE_TYPE

单纯的图片类型

WebView.HitTestResult.EDIT_TEXT_TYPE

选中的文字类型

表10.2.2    HitTestResult各个类型

       

        现在我们可以看看实际的效果。

       

图10.2.11   长按图片弹出菜单效果

       

    我们可以看到这个菜单弹出来的情况,并不如我们预期的是点击哪里在哪个地方弹出来。很显然使我们没有将x,y的值传递给popupwindow。

    那么我们怎么获取x,y的值呢?

    这里我们可以利用一下我们之前所构建的GestureDector类,这个类中,我们之前定义了滑动的事件,在这里同样也有个onLongPress事件。而且,最重要且最有趣的是,这个事件虽然跟我们自定义的长按事件一致,但是前者是先发生的。也就是说,webView是先执行onTouch中的onLongPress事件,后执行OnLongClickedListener中的OnLongClick事件。这就给我们提供了一个方便。

   

    我们可以在onLongPress事件中如下定义:
   

@Override
      public void onLongPress(MotionEvent e) {
         PointerXY.x = (int) e.getX();
         PointerXY.y = (int) e.getY();
      }

代码片段10.2.31 OnLongPress事件

        当然这里的PinterXY是我自己定义的一个类,专门用来存放事件触发的坐标。

       

private static class PointerXY{
      public static int x;
      public static int y;
      public static int getX() {
         return x;
      }
      public static int getY() {
         return y;
      }
     
   }

代码片段10.2.32 PointXY类

       

    好了,定义完了这些。我们就可以轻松的获取到自己想要的东西,将之前展示popupwindow的方法修改如下:

       

itemLongClickedPopWindow.showAtLocation(v, Gravity.TOP | Gravity.LEFT, PointerXY.getX(),PointerXY.getY()+10);

代码片段10.2.33 修改展示方法

       

        现在我们再来看看,与之前的效果想对比(+10是为了修正):

图10.2.12   修改前后的对比

现在展示效果已经完成了,那么其他的就相对简单多了,我们只需要进行功能的实现就行了。

 

case WebView.HitTestResult.IMAGE_TYPE:
            // 处理长按图片的菜单项
            Log.d(DEG_TAG, "图片");
            itemLongClickedPopWindow.showAtLocation(v, Gravity.TOP | Gravity.LEFT, PointerXY.getX(),PointerXY.getY()+10);
            TextView viewImage = (TextView)itemLongClickedPopWindow.getView(R.id.item_longclicked_viewImage);
            TextView saveImage = (TextView)itemLongClickedPopWindow.getView(R.id.item_longclicked_saveImage);
            TextView viewImageAttributes = (TextView)itemLongClickedPopWindow.getView(R.id.item_longclicked_viewImageAttributes);
            popWindowMenu = newPopWindowMenu(result.getType(), result.getExtra());
            viewImage.setOnClickListener(popWindowMenu);
            saveImage.setOnClickListener(popWindowMenu);
            viewImageAttributes.setOnClickListener(popWindowMenu);
            break;

代码片段10.2.34 功能实现图片菜单

 

至于popWindowMenu的实现如下:

 

/**
    * OnClickListener自定义继承类
    * 用来解决菜单功能处理问题
    * */
   private class PopWindowMenu implements OnClickListener{
     
      private int type;
      private String value;
     
      public PopWindowMenu(int type, String value){
         this.type = type;
         this.value = value;
      }
 
      @Override
      public void onClick(View v) {
         if(v.getId()==R.id.item_longclicked_viewImage){
            //图片菜单-查看图片
         }else if(v.getId()==R.id.item_longclicked_saveImage){
            //图片菜单-保存图片
         }else if(v.getId()==R.id.item_longclicked_viewImageAttributes){
            //图片菜单-查看属性
         }
      }
     
   }

代码片段10.2.35 点击事件

 

至于如何实现在下一个版本中实现。

 

案例源码:

AndroidSudty_web_V3.0_by dddd牛仔


声明:转载请注明出处。

 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值