上述的历史和书签的功能已经实现。不过如果我们长时间按住图片,并不会出现如同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牛仔
声明:转载请注明出处。