开发蒙版向导的一些领悟
来源:互联网 发布:ip网络计算 编辑:程序博客网 时间:2024/05/16 09:07
先上效果图!
奉上git地址,还有一些属性和点击事件的设置可以自己封装
https://github.com/mocn26169/Android-GuideHelper
这次主要是使用了自定义Dialog的方式来实现这个效果
主要步骤:
1、创建一个自定义VIew的Dialog
2、复制一个需要高亮显示的View在同样的位置,并完美覆盖(重点)
3、绘制提示图片
1 创建一个自定义VIew的Dialog
guidelayout = new RelativeLayout(activity);//创建Dialog,遮挡状态栏guideDialog = new Dialog(activity, android.R.style.Theme_DeviceDefault_Light_DialogWhenLarge_NoActionBar);//设置背景颜色guideDialog.getWindow().setBackgroundDrawable(new ColorDrawable(0x66000000));//设置自定义的布局guideDialog.setContentView(guidelayout);//设置布局的属性guideDialog.getWindow().setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT);//设置点击不能取消guideDialog.setCancelable(false);//显示DialogguideDialog.show();
2 复制一个需要高亮显示的View在同样的位置,并完美覆盖(重点)
2.1、获取原来的VIew的位置和宽高
//获取view的宽高int vWidth = lightView.getMeasuredWidth();int vHeight = lightView.getMeasuredHeight();//如果宽高都小于等于0,再measure试下获取if (vWidth <= 0 || vHeight <= 0) { ViewGroup.LayoutParams mlayoutParams = lightView.getLayoutParams(); lightView.measure(mlayoutParams.width, mlayoutParams.height); vWidth = lightView.getMeasuredWidth(); vHeight = lightView.getMeasuredHeight();}//获取不到宽高则返回操作if (vWidth <= 0 || vHeight <= 0) { Log.e("GuideHelper", "宽高都小于等于0"); return;}
2.2 获取自定义布局在视图的位置,View的Y轴坐标减去这个位置的Y轴坐标,避免Dialog不是全屏的时候位置偏移,就可以可以实现全局覆盖了
//获取view在屏幕的位置int[] location = new int[2];lightView.getLocationOnScreen(location);//获取layout在屏幕上的位置int layoutOffset[] = new int[2];guidelayout.getLocationOnScreen(layoutOffset);//这里避免dialog不是全屏,导致view的绘制位置不对应location[1] -= layoutOffset[1];
2.3 根据视图缓存获取bitmap
//开启能缓存图片信息lightView.setDrawingCacheEnabled(true);//获取视图缓存lightView.buildDrawingCache();Bitmap LightBitmap = lightView.getDrawingCache();if (LightBitmap != null) { //根据缓存获取Bitmap LightBitmap = Bitmap.createBitmap(LightBitmap);} else { //如果获取不到,则用创建一个view宽高一样的bitmap用canvas把view绘制上去 LightBitmap = Bitmap.createBitmap(vWidth, vHeight, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(LightBitmap); lightView.draw(canvas);}//关闭能缓存图片信息lightView.setDrawingCacheEnabled(false);//释放缓存lightView.destroyDrawingCache();
2.4 创建一个ImageView,设置位置,把bitmap设置为背景,添加到布局
//设置ImageView属性ImageView newLightView = new ImageView(activity);newLightView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);newLightView.setImageBitmap(LightBitmap);//动态设置Viwe的idint imageViewId = R.id.snack;newLightView.setId(imageViewId);//设置位置RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);params.leftMargin = location[0];params.topMargin = location[1];//添加到布局guidelayout.addView(newLightView, params);
到这里就完成对需要高亮的View的复制了,注意的是这个view最好设置背景颜色,不然有可能没有效果。
3 显示提示图片
获取资源的Bitmap,然后创建ImageView,设Bitmap为背景,在指定位置显示
/**********显示提示图片**********///获取提示图片的BitmapBitmap tipBitmap = BitmapFactory.decodeResource(activity.getResources(), tipsImageResourceId);//设置大小RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);int showViewHeight = tipBitmap.getHeight();int showViewWidth = tipBitmap.getWidth();//设置ImageView属性ImageView newTipView = new ImageView(activity);newTipView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);layoutParams.width = showViewWidth;layoutParams.height = showViewHeight;newTipView.setImageBitmap(tipBitmap);//设置间距(可自行封装)//layoutParams.topMargin += dipToPix(activity, 20);//设置相对位置(可自行封装)layoutParams.addRule(RelativeLayout.BELOW, newLightView.getId());layoutParams.addRule(RelativeLayout.ALIGN_LEFT, newLightView.getId());//layoutParams.addRule(RelativeLayout.CENTER_HORIZONTAL);//添加到布局guidelayout.addView(newTipView, layoutParams);
完整代码:
package com.mocn.guidehelper;import android.app.Activity;import android.app.Dialog;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Rect;import android.graphics.drawable.ColorDrawable;import android.os.Build;import android.support.annotation.RequiresApi;import android.util.DisplayMetrics;import android.util.Log;import android.util.TypedValue;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.view.Window;import android.view.WindowManager;import android.widget.ImageView;import android.widget.RelativeLayout;import java.util.List;public class GuideHelper { private List<PageData> pageDatas; private Activity activity; private Dialog guideDialog; private RelativeLayout guidelayout; public GuideHelper(Activity activity, List<PageData> pageDatas) { this.activity = activity; this.pageDatas = pageDatas; } public void show() { if (pageDatas.size() <= 0) { Log.e("GuideHelper", "没有数据"); return; } if (guidelayout == null) { guidelayout = new RelativeLayout(activity); //创建Dialog,不遮挡状态栏 guideDialog = new Dialog(activity, R.style.popupDialog); guideDialog.requestWindowFeature(Window.FEATURE_NO_TITLE); guideDialog.setContentView(guidelayout); guideDialog.setCanceledOnTouchOutside(false); guideDialog.setCancelable(false); guideDialog.getWindow().setBackgroundDrawable(new ColorDrawable(0x66000000)); //设置不遮挡状态栏 WindowManager.LayoutParams lay = guideDialog.getWindow().getAttributes(); DisplayMetrics dm = new DisplayMetrics(); activity.getWindowManager().getDefaultDisplay().getMetrics(dm); Rect rect = new Rect(); View view = activity.getWindow().getDecorView();//decorView是window中的最顶层view,可以从window中获取到decorView view.getWindowVisibleDisplayFrame(rect); lay.height = dm.heightPixels - rect.top; lay.width = dm.widthPixels; guideDialog.show();// //创建Dialog,遮挡状态栏// guideDialog = new Dialog(activity, android.R.style.Theme_DeviceDefault_Light_DialogWhenLarge_NoActionBar);// //设置背景颜色// guideDialog.getWindow().setBackgroundDrawable(new ColorDrawable(0x66000000));// //设置自定义的布局// guideDialog.setContentView(guidelayout);// //设置布局的属性// guideDialog.getWindow().setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT);// //设置点击不能取消// guideDialog.setCancelable(false);// //显示Dialog// guideDialog.show(); } pageDatas.get(0).getLightView().post(new Runnable() { @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1) @Override public void run() { showTip(guidelayout); } }); } private void showTip(final RelativeLayout guidelayout) { View lightView = pageDatas.get(0).getLightView(); int tipsImageResourceId = pageDatas.get(0).getTipsImageResourceId(); /**********显示高亮控件**********/ //获取view的宽高 int vWidth = lightView.getMeasuredWidth(); int vHeight = lightView.getMeasuredHeight(); //如果宽高都小于等于0,再measure试下获取 if (vWidth <= 0 || vHeight <= 0) { ViewGroup.LayoutParams mlayoutParams = lightView.getLayoutParams(); lightView.measure(mlayoutParams.width, mlayoutParams.height); vWidth = lightView.getMeasuredWidth(); vHeight = lightView.getMeasuredHeight(); } //获取不到宽高则返回操作 if (vWidth <= 0 || vHeight <= 0) { Log.e("GuideHelper", "宽高都小于等于0"); return; } //获取view在屏幕的位置 int[] location = new int[2]; lightView.getLocationOnScreen(location); //获取layout在屏幕上的位置 int layoutOffset[] = new int[2]; guidelayout.getLocationOnScreen(layoutOffset); //这里避免dialog不是全屏,导致view的绘制位置不对应 location[1] -= layoutOffset[1]; //开启能缓存图片信息 lightView.setDrawingCacheEnabled(true); //获取视图缓存 lightView.buildDrawingCache(); Bitmap LightBitmap = lightView.getDrawingCache(); if (LightBitmap != null) { //根据缓存获取Bitmap LightBitmap = Bitmap.createBitmap(LightBitmap); } else { //如果获取不到,则用创建一个view宽高一样的bitmap用canvas把view绘制上去 LightBitmap = Bitmap.createBitmap(vWidth, vHeight, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(LightBitmap); lightView.draw(canvas); } //关闭能缓存图片信息 lightView.setDrawingCacheEnabled(false); //释放缓存 lightView.destroyDrawingCache(); //设置ImageView属性 ImageView newLightView = new ImageView(activity); newLightView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); newLightView.setImageBitmap(LightBitmap); //动态设置Viwe的id int imageViewId = R.id.snack; newLightView.setId(imageViewId); //设置位置 RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); params.leftMargin = location[0]; params.topMargin = location[1]; //添加到布局 guidelayout.addView(newLightView, params); /**********显示提示图片**********/ //获取提示图片的Bitmap Bitmap tipBitmap = BitmapFactory.decodeResource(activity.getResources(), tipsImageResourceId); //设置大小 RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); int showViewHeight = tipBitmap.getHeight(); int showViewWidth = tipBitmap.getWidth(); //设置ImageView属性 ImageView newTipView = new ImageView(activity); newTipView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); layoutParams.width = showViewWidth; layoutParams.height = showViewHeight; newTipView.setImageBitmap(tipBitmap); //设置间距(可自行封装) //layoutParams.topMargin += dipToPix(activity, 20); //设置相对位置(可自行封装) layoutParams.addRule(RelativeLayout.BELOW, newLightView.getId()); layoutParams.addRule(RelativeLayout.ALIGN_LEFT, newLightView.getId()); //layoutParams.addRule(RelativeLayout.CENTER_HORIZONTAL); //添加到布局 guidelayout.addView(newTipView, layoutParams); //点击布局执行下一步动作 guidelayout.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //清理布局控件 guidelayout.removeAllViews(); //操作有第二步继续执行 if (pageDatas.size() >= 2) { pageDatas.remove(0); show(); } else { guideDialog.dismiss(); } } }); } public static class PageData { /** * 高亮View */ private View lightView; /** * 提示图片id */ private int tipsImageResourceId; public PageData(View lightView, int tipsImageResourceId) { this.lightView = lightView; this.tipsImageResourceId = tipsImageResourceId; } public View getLightView() { return lightView; } public void setLightView(View lightView) { this.lightView = lightView; } public int getTipsImageResourceId() { return tipsImageResourceId; } public void setTipsImageResourceId(int tipsImageResourceId) { this.tipsImageResourceId = tipsImageResourceId; } } /** * dip转px */ public int dipToPix(Context context, int dip) { int size = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, context.getResources().getDisplayMetrics()); return size; } /** * 实例化布局 * * @param layoutId * @return */ public View inflate(int layoutId) { LayoutInflater inflater = LayoutInflater.from(activity); View view = inflater.inflate(layoutId, null); return view; }}
使用方法:
package com.mocn.guidehelper;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.view.View;import android.widget.Button;import android.widget.TextView;import java.util.ArrayList;import java.util.List;public class GuideHelperActivity extends AppCompatActivity { private TextView tv_first; private Button btn_first; private Button btn_second; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_guide_helper); tv_first = (TextView) findViewById(R.id.tv_first); btn_first = (Button) findViewById(R.id.btn_first); btn_second = (Button) findViewById(R.id.btn_second); btn_first.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { List<GuideHelper.PageData> pageDatas = new ArrayList<GuideHelper.PageData>(); pageDatas.add(new GuideHelper.PageData(btn_first, R.mipmap.tip1)); pageDatas.add(new GuideHelper.PageData(tv_first, R.mipmap.tip1)); pageDatas.add(new GuideHelper.PageData(btn_second, R.mipmap.tip1)); GuideHelper guideHelper = new GuideHelper(GuideHelperActivity.this, pageDatas); guideHelper.show(); } }); }}
在这个例子当中最重要的是复制一个view,而复制一个View的重点又是根据getDrawingCache()获取缓存的Bitmap,并显示在界面上
getDrawingCache()被经常用来做屏幕截图,比如说:
看下手机截图:
截图之后的效果图
可以看到,截取了除状态栏外,标题栏和内容的界面,关键代码如下:
/** * 截取当前程序界面 */ private void saveView() { //DecorView只有一个子元素为LinearLayout。代表整个Window界面,包含通知栏,标题栏,内容显示栏三块区域 View decorView = getWindow().getDecorView(); //开启能缓存图片信息 decorView.setDrawingCacheEnabled(true); //获取视图缓存 decorView.buildDrawingCache(); //根据缓存获取Bitmap Bitmap bmp = decorView.getDrawingCache(); Rect rect = new Rect(); //getWindowVisibleDisplayFrame方法可以获取到程序显示的区域,包括标题栏,但不包括状态栏 decorView.getWindowVisibleDisplayFrame(rect); //获取状态栏高度 int statusBarHeight = rect.top; //获取图片宽高 int width = bmp.getWidth(); int height = bmp.getHeight(); //坐标轴和高度都减去状态栏的高度 Bitmap saveBmp = Bitmap.createBitmap(bmp, 0, statusBarHeight, width, height - statusBarHeight, null, false); //关闭能缓存图片信息 decorView.setDrawingCacheEnabled(false); //释放缓存 decorView.destroyDrawingCache(); //将图片保存到SD卡 saveBitmap("ScreenShot", saveBmp); }
有时候,我们需要截取超过屏幕外的界面,比如说listview和scrollView,就要动态计算加起来的子view的总高度了,效果图如下:
代码如下:
/** * 截取超过程序界面的长图 */ private void saveLongView() { int h = 0; // 获取listView实际高度// for (int i = 0; i < listView.getChildCount(); i++) {// h += listView.getChildAt(i).getHeight();// } // 获取scrollView实际高度 for (int i = 0; i < scrollView.getChildCount(); i++) { h += scrollView.getChildAt(i).getHeight(); } //如果是webView// Picture snapShot = webView.capturePicture();// Bitmap bmp = Bitmap.createBitmap(snapShot.getWidth(), snapShot.getHeight(), Bitmap.Config.ARGB_8888);// Canvas canvas = new Canvas(bmp);// snapShot.draw(canvas); Log.i("ScreenShot", " 高度:" + scrollView.getHeight()); Log.i("ScreenShot", "实际高度:" + h); Bitmap bitmap; // 创建对应大小的bitmap bitmap = Bitmap.createBitmap(scrollView.getWidth(), h, Bitmap.Config.ARGB_8888); final Canvas canvas = new Canvas(bitmap); scrollView.draw(canvas); //将图片保存到SD卡 saveBitmap("ScreenShot", bitmap); }
0 0
- 开发蒙版向导的一些领悟
- 大学毕业有感的一些领悟
- 关于CGD的一些领悟
- MySQL一些痛的领悟
- uc iii的一些领悟
- 向导界面的开发
- 关于一些C++编程的领悟
- 关于SourceAnyWhere问题的一些领悟
- 外围渗透测试的一些小领悟
- 关于Extjs一些重要概念的领悟
- 关于游戏服务器设计的一些领悟
- 关于ListView加载优化的一些领悟
- 关于创建链表的一些领悟
- 开发领悟
- 从ET2开发中领悟到的
- 从ET2开发中领悟到的
- 人生中的一些领悟。。。
- 个人工作13年的一些人生真实领悟
- 移动APP漏洞自动化检测平台建设
- Java面试题集锦
- PopUpWindow使用详解(一)——基本使用
- 网格聚类算法(三)
- Linux基础——PATH环境变量
- 开发蒙版向导的一些领悟
- poj3268~Silver Cow Party(dijkstra+路径反转)
- 获取随机数(max与min之间)
- Java动态代理机制详解(JDK 和CGLIB,Javassist,ASM)
- CoordinatorLayoutt +SwipeRefresh实现刷新加载多标签的咨询页
- android 和 ios中实现类似C#的BackgroundWorker接口
- Java LinkedHashSet
- OpenCV 图像分离颜色通道 split函数和mege函数的运用
- 【Codeforces-402D】-String Game (二分)