2015-03-03 126 views

回答

1

与大多数其他视图一样,WebView可以将自己绘制到提供的画布上。加载页面后,我们可以使用此方法创建呈现页面的截图位图,并将其与网站标题和图标一起添加到GridView中。下面的例子是相当通用的,因为我相信你会想定制它。

我已经将这个功能包装在Fragment中,它只需要引用WebView。在我的简单演示应用程序中,我调用了WebView的WebViewClient的onPageFinished()回调中的片段addCurrentSite()方法,为每个访问的新URL创建一个截图。 Fragment类还提供了一个回调界面,Activity可以实现回应点击截图。另外,长按屏幕截图会将其从列表中删除。

首先,WebShotFragment类:

public class WebShotFragment extends Fragment { 
    private WebView webView; 
    private GridView grid; 
    private SiteMap<String, Site> sites = new SiteMap<String, Site>(); 
    private SiteAdapter adapter; 

    public WebShotFragment() {} 

    public interface OnSiteSelectedListener { 
     public void onSiteSelected(String url); 
    } 

    private OnSiteSelectedListener listener; 
    public void setOnSiteSelectedListener(OnSiteSelectedListener listener) { 
     this.listener = listener; 
    } 

    public void registerWebView(WebView webView) { 
     this.webView = webView; 
    } 

    public void addCurrentSite() { 
     if (!sites.containsKey(webView.getUrl())) { 
      webView.postDelayed(new Runnable() { 
        @Override 
        public void run() { 
         Bitmap bmp = getWebshot(); 
         sites.put(webView.getUrl(), new Site(webView.getTitle(), webView.getUrl(), webView.getFavicon(), bmp)); 
         adapter.notifyDataSetChanged(); 
        } 
       }, 1000); 
     } 
    } 

    private Bitmap getWebshot() { 
     Bitmap bmp = Bitmap.createBitmap(webView.getWidth(), webView.getHeight(), Bitmap.Config.ARGB_8888); 
     Canvas canvas = new Canvas(bmp); 
     webView.draw(canvas); 
     Bitmap res = Bitmap.createBitmap(200, 150, Bitmap.Config.ARGB_8888); 
     canvas = new Canvas(res); 
     canvas.drawBitmap(bmp, 
          new Rect(0, 0, bmp.getWidth(), bmp.getHeight()), 
          new Rect(0, 0, res.getWidth(), res.getHeight()), 
          new Paint()); 

     return res; 
    } 

    @Override 
    public void onAttach(Activity activity) { 
     super.onAttach(activity); 
     adapter = new SiteAdapter(activity, sites); 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     grid = (GridView) inflater.inflate(R.layout.fragment_webshot, container, false); 
     grid.setAdapter(adapter); 
     grid.setOnItemClickListener(new OnItemClickListener() { 
       @Override 
       public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 
        if (listener != null) 
         listener.onSiteSelected(sites.getValue(position).url); 
       } 
      }); 
     grid.setOnItemLongClickListener(new OnItemLongClickListener() { 
       @Override 
       public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { 
        sites.remove(sites.getEntry(position).getKey()); 
        adapter.notifyDataSetChanged(); 
        return true; 
       } 
      }); 
     return grid; 
    } 

    private class SiteAdapter extends BaseAdapter { 
     private LayoutInflater inflater; 
     private SiteMap<String, Site> sites; 

     public SiteAdapter(Context context, SiteMap<String, Site> sites) { 
      this.inflater = LayoutInflater.from(context); 
      this.sites = sites; 
     } 

     @Override 
     public int getCount() { 
      return sites.size(); 
     } 

     @Override 
     public Object getItem(int position) { 
      return sites.getValue(position); 
     } 

     @Override 
     public long getItemId(int position) { 
      return 0; 
     } 

     @Override 
     public View getView(int position, View convertView, ViewGroup parent) { 
      View v = inflater.inflate(R.layout.webshot, null); 

      Site s = (Site) getItem(position); 
      ((ImageView) v.findViewById(R.id.icon)).setImageBitmap(s.icon); 
      ((TextView) v.findViewById(R.id.title)).setText(s.title); 
      ((ImageView) v.findViewById(R.id.shot)).setImageBitmap(s.webshot); 

      return v; 
     } 
    } 

    private class Site { 
     public String title, url; 
     public Bitmap icon, webshot; 

     public Site(String title, String url, Bitmap icon, Bitmap webshot) { 
      this.title = title; 
      this.url = url; 
      this.icon = icon; 
      this.webshot = webshot; 
     } 
    } 

    private class SiteMap<K, V> extends LinkedHashMap<K, V> { 
     public V getValue(int i) { 
      Map.Entry<K, V> entry = this.getEntry(i); 

      if (entry == null) 
       return null; 

      return entry.getValue(); 
     } 

     public Map.Entry<K, V> getEntry(int i) { 
      if (i < 0) 
       throw new IllegalArgumentException("Index cannot be negative"); 

      Set<Map.Entry<K,V>> entries = entrySet(); 

      int j = 0; 
      for (Map.Entry<K, V> entry : entries) 
       if (j++ == i) 
        return entry; 

      return null; 
     } 
    } 
} 

该类使用两个布局文件。在这里,fragment_webshot.xml为GridView:

<GridView xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:background="#ffffff" 
    android:padding="10dp" 
    android:numColumns="auto_fit" 
    android:stretchMode="columnWidth" 
    android:verticalSpacing="10dp" 
    android:horizontalSpacing="10dp" /> 

而且webshot.xml的项目:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:background="#eeeeee" 
    android:padding="5dp" 
    android:orientation="vertical"> 

    <LinearLayout 
     android:layout_width="match_parent" 
     android:layout_height="30dp" 
     android:gravity="center_vertical"> 

     <ImageView android:id="@+id/icon" 
      android:layout_width="24dp" 
      android:layout_height="24dp" 
      android:scaleType="fitXY" /> 

     <Space 
      android:layout_width="10dp" 
      android:layout_height="match_parent" /> 

     <TextView android:id="@+id/title" 
      android:layout_width="0dp" 
      android:layout_height="wrap_content" 
      android:layout_weight="1" 
      android:singleLine="true" /> 

    </LinearLayout> 

    <ImageView android:id="@+id/shot" 
     android:layout_width="match_parent" 
     android:layout_height="0dp" 
     android:layout_weight="1" 
     android:scaleType="fitXY" /> 

</LinearLayout> 

设置在活动是最小的。只需获取对WebView的引用,设置其WebViewClient并将其注册到WebShotFragment。正如所提到的,我只是为了演示而在每个onPageFinished()回调上执行片段的addCurrentSite()方法;你可能想要改变它。

public class MainActivity extends Activity 
    implements WebShotFragment.OnSiteSelectedListener { 
    ... 
    WebView webView; 
    WebShotFragment webShotFragment; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     ... 
     webView = (WebView) findViewById(...); 
     webView.setWebViewClient(new WebViewClient() { 
       public boolean shouldOverrideUrlLoading(WebView webView, String url) { 
        return false; 
       } 

       public void onPageFinished(WebView webView, String url) { 
        webShotFragment.addCurrentSite(); 
       } 
      }); 

     webShotFragment = ... // Instantiate/initialize the Fragment 

     webShotFragment.setOnSiteSelectedListener(this); 
     webShotFragment.registerWebView(webView); 
     ... 
    } 

    @Override 
    public void onSiteSelected(String url) { 
     webView.loadUrl(url); 
    } 
} 

一个示例应用程序的屏幕截图:

screenshot

相关问题