仿uc下部弹出菜单

先说说我怎么会无聊到这种地步去弄这个代码呢,在今年2月份的时候公司本来要做个这种弹出的菜单的,有5个按钮每个都有一个菜单,记得网上有仿UC菜单的源码,就下下来看,结果不符合要求,当时这个菜单由另一个同事在做代码,组长叫我和他考虑界面实现的可行性,我提出这种思路给他,他不采纳,觉得太烦了,他就自己弄,因为我们的项目是车载导航上的一个主控程序上的菜单,屏幕分辨率固定,所以用5张图片就ok了,所以到最后这个都不了了之了,现在也离开了那家公司,应该没有什么公司机密吧,没用到公司项目,而且是我自己下班家里搞得,公开了应该没啥事,而且好像没什么技术含量,就是这个思路不错,发给大家参考下(LZ
BB了这么多废话全是因为今天七夕,"一个人的七夕".equals("死") == true)。
先来看UC菜单的效果

发现没,UC的菜单箭头绝对是对准所点击按钮的,有人可能觉得用不同的图片就行了,对于一种机型可以这么做,android机型千千万,你要怎么配型,这是个很大的工作量,吃力不讨好啊。反编译过UC的人就知道,UC里没有这种图片,那他用的是什么图呢,UC用到下面的3张图片。

我当时就想这3张图怎么在xml里添加进去呢,百撕不得其姐啊,当时公司要弄个翻页时钟(仿墨迹的),那边我用到了图片合成的方法,就想到这边也可以用这种方法,就是必须先把.9图拉伸下。
具体UC是怎么合成的图片,只有问UC去了,我有一种方法也可以合成,就不知道是不是和UC的原理一样了给你们参考下。

先说思路吧,看图

如图所示,可以把菜单的背景分成3部分,这样用上面的3张.9图片根据不同大小进行拉伸组合就能得到想要的效果了。
为啥要把按钮4等份,把其中的2份给图1和图3呢,这是为了防止按钮居左或居右时,解决图1和图3的宽度为NULL情况。

看了上面的分割,这样布局的话,图片2的箭头是不是绝对的对准按钮的中间啊,而且背景的合成是根据button来的,适应性是不是很强,虽然跟按钮的大小位置有关,但是随着button的大小位置的变化,背景图的3块区域也随之变化组合成符合的图片,瞬间智商上的优越感爆棚了

思路说完了,看下实现的方法把,就是以一个bitmap为画布,把另一个绘制到上面就行,这是我的方法,不知道还有没其他的方法,望大能给个更好的方法。

怎么把两个bitmap合成一个呢


01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

/**

         * 以一个Bitmap为画布,画上一个Bitmap

         * @param canvasBitmap 作为画布的Bitmap

         * @param drawBitmap 要被绘制的Bitmap

         * @param top 从画布的距离顶部的top位置开始

         * @param left 从画布的距离左边的left位置开始

         */

         private
void drawbitMap(Bitmap canvasBitmap, Bitmap drawBitmap,
int top,
int left)

         
{

            Canvas localCanvas =
new Canvas(canvasBitmap);//以canvasBitmap生成画布

            localCanvas.drawBitmap(drawBitmap, left, top,
null);//在画布上移left和top左标开始绘制drawBitmap

            localCanvas.save(Canvas.ALL_SAVE_FLAG);//保存

            localCanvas.restore();

            drawBitmap.recycle();//释放掉drawBitmap,防止内存泄漏

         
}

加载资源文件中的图片为Drawable后怎么把它拉伸到需要的大小并转化为bitmap呢,我查了资料(百度,google),自己总结使用了下面的一个方法,也可以看
dyh7077063的博客 :http://dyh7077063.iteye.com/blog/970672,今天才看到的博客,以前怎么没早看到,亏死了,写的不错,很多方法用的上。


01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

/**

         
* 把Drawable生成对应的Bitmap

         
* @param paramRect 生成的Bitmap大小等一些参数

         
* @param drawable 要绘制的drawable

         
* @param canvasBitmap 将drawable绘制到canvasBitmap中

         
*/

         
private void
getBitMap(Rect paramRect, Drawable drawable, Bitmap canvasBitmap)

         
{

               
//中这个方法顾名思义,就是设置边界,

               
//用到的是.9图,所以拉伸图片不会失真,把drawable设置一个left、top点开始拉一个paramRect.right宽

               
//paramRect.bottom高的矩形区域,按我的理解就是弄了这个区域,就是把图片按.9图的设置拉倒相应的

               
//大小填充到矩形区域里去,不明白看  的博客

            drawable.setBounds(0,
0, paramRect.right, paramRect.bottom);

            //用canvasBitmap生成一个画布

            Canvas localCanvas =
new Canvas(canvasBitmap);

            drawable.draw(localCanvas);//使用drawable的draw方法画到画布上

            localCanvas.save(Canvas.ALL_SAVE_FLAG);//保存

            localCanvas.restore();

         
}

我解释下drawable.setBounds这个方法:前面图片里写成其他部分填充白色,这是错误的,是以透明像素来填充的,误导大家了啊,见谅哈,我已修改
有上面的方法,在技术可行性方面就不是问题了。

再来说怎么确定3个图片分别对应的大小呢,其实这个很容易,看上面的图可知,只要能得到那个button(View)就行了,这个还是比较容易获得的把

所以很快就能得到3个图片对应要生成的大小了,看下面的代码,top和left表示的是在背景图中绘制的左上角的起始位置。


01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

//定义3个图片的大小等一些参数

              Rect[] arrayOfRect =
new Rect[3];

              arrayOfRect[0] =
new Rect();

              arrayOfRect[0].top =
0;

              arrayOfRect[0].left =
0;

              arrayOfRect[0].right =
this.parentLeft +
this.parentWidth /
4;

              arrayOfRect[0].bottom =
this.popupWindowHeight;

               

              arrayOfRect[1] =
new Rect();

              arrayOfRect[1].top =
0;

              arrayOfRect[1].left = arrayOfRect[0].right;

              arrayOfRect[1].right =
this.parentWidth /
2;

              arrayOfRect[1].bottom =
this.popupWindowHeight;

               

              arrayOfRect[2] =
new Rect();

              arrayOfRect[2].top =
0;

              arrayOfRect[2].left =
this.parentLeft +
this.parentWidth *
3 / 4;

              arrayOfRect[2].right = screenwidth - arrayOfRect[2].left;

              arrayOfRect[2].bottom =
this.popupWindowHeight;

其中parentLeft为button的距离屏幕左边距的距离,也就是getLeft方法得到的数值,parentWidth就是按钮本身的宽度了,screenwidth 是屏幕宽度,popupWindowHeight为popupWindow的高度,具体你们看图和源码。

现在只要循环调用把3张图绘制到一张bitmap中在生成drawable就好。


01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

/**

         * 生成背景图

         * @param context 上下文,为生成BitmapDrawable所需的

         * @param ArrayOfRect

         * @param ArrayOfDrawable

         * @return

         */

         
private Drawable getDrawable(Context context,

                          Rect[] ArrayOfRect, Drawable[] ArrayOfDrawable)

         
{

                  Bitmap.Config localConfig = Bitmap.Config.ARGB_8888;

                  //先更具popupWindow的大小生成一个Bitmap

                  Bitmap paramBitmap = Bitmap.createBitmap(screenwidth, popupWindowHeight, localConfig);

                   

                  //这里循环把3个图片绘制到paramBitmap中

                  for
(int
i =
0; i < ArrayOfDrawable.length; i++)

                  {

                          Rect localRect = ArrayOfRect<i>;

                     
Bitmap localBitmap = Bitmap.createBitmap(localRect.right, localRect.bottom, localConfig);            

                     
Drawable localDrawable = ArrayOfDrawable</i><i><i>;

                     
getBitMap(localRect, localDrawable, localBitmap);//得到相应的drawable的BitMap

                     
drawbitMap(paramBitmap, localBitmap, localRect.top, localRect.left);//在paramBitmap中绘制localBitmap

                     
localBitmap.recycle();//释放掉,要不多次运行有可能会内存泄漏

                  }

                  return
new BitmapDrawable(context.getResources(), paramBitmap);

         
}</i></i>

以上代码就生成了相应大小的图片了。

有了这些方法,就可实现菜单背景的生成。


01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

public
void
show(View parent, Context context) {

               
bg = mapDrawable.get(parent);//为节省资源,map中会保存以前生成的背景,根据父控件来获得

               
popupWindowHeight = popupWindow.getHeight();//得到popupWindow的高度,在popupWindow构造完后才能获取

 this.parentLeft = parent.getLeft();//父控件的左边距

               
this.parentWidth = parent.getWidth();//父控件的宽度

               
if(bg == null)//背景为空

               
{

                        createDrawable(context);//生成背景图

                        mapDrawable.put(parent, bg);//保存到map中

               
}

               
 

               
popupWindow.setBackgroundDrawable(bg);//给popupWindow设置背景

               
popupWindow.showAtLocation(parent, Gravity.BOTTOM,
0, parent.getHeight());// 距离底部的位置

               
popupWindow.setAnimationStyle(R.style.popwin_anim_style);

               
popupWindow.setFocusable(true);

               
popupWindow.setOutsideTouchable(true);

               
popupWindow.update();

}

mapDrawable是一个HashMap<View, Drawable>对象,用来保存生成的背景的,多次调用肯定会带来内存和时间上的大量损耗,所以一个按钮生成一个背景后保存下来下次再用是非常好的方法。

最后看我弄的效果哈

效果还行吧!!

发图和部分代码不给源码是非常不人道的,但是希望下源码人不要只copy,那是没有进步的,我们不光要模仿还要会思考,使用别人的方法达到别人没有实现的效果也是有进步的,代码还可优化,大家自己弄哈,由于源码放在上家公司没带走,所以前天我下了个仿UC的菜单源码进行修改来的,所以代码有些乱望见谅,PopMenu类可以直接使用的:TestPullPopWindow.rar(1.01
MB, 下载次数: 641)

ps:转载请标明出处,好歹给我们这些IT民工一些优越感吧,by:baofei

时间: 2024-08-04 04:11:59

仿uc下部弹出菜单的相关文章

android自定义popupwindow仿微信右上角弹出菜单效果_Android

微信右上角的操作菜单看起来很好用,就照着仿了一下,不过是旧版微信的,手里刚好有一些旧版微信的资源图标,给大家分享一下. 不知道微信是用什么实现的,我使用popupwindow来实现,主要分为几块内容: 1.窗口布局文件:popwin_share.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com

android自定义popupwindow仿微信右上角弹出菜单效果

微信右上角的操作菜单看起来很好用,就照着仿了一下,不过是旧版微信的,手里刚好有一些旧版微信的资源图标,给大家分享一下. 不知道微信是用什么实现的,我使用popupwindow来实现,主要分为几块内容: 1.窗口布局文件:popwin_share.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com

仿酷狗音乐播放器开发日志二十六 duilib在标题栏弹出菜单的方法

转载请说明原出处,谢谢~~        上篇日志说明了怎么让自定义控件响应右键消息.之后我给主窗体的标题栏增加右键响应,观察原酷狗后可以发现,在整个标题栏都是可以响应右键并弹出菜单的.应该的效果如下:        本以为像上一片博客那样,处理标题栏的布局的右键消息就可以了.后来发现在duilib的标题栏中无法像在客户区那样自如响应UIEVENT_CONTEXTMENU消息的.所以还得用另外的方法.       在非客户区处理右击消息对应的是WM_NCRBUTTONUP,WM_NCRBUTTO

uc浏览器长按弹出菜单怎么取消?

问题描述 uc浏览器长按弹出菜单怎么取消? 安卓手机uc浏览器长按弹出菜单怎么取消?我自己的网站长按有我自己的操作,但是UC本身也会跳出菜单,这样就影响了我的网站的用户体验,请问各位大神怎么取消? 解决方案 就没有大牛吗? 各位大神大牛,你们在哪?坐等你们现身 解决方案二: 在浏览器中很难实现吧,类似web网站中的右键

jquery 插件之仿“卓越亚马逊”首页弹出菜单效果_jquery

复制代码 代码如下: /*弹出式菜单*/ //没剑 2008-07-03 //http://regedit.cnblogs.com /*参数说明*/ //showobj:要显示的菜单ID //timeout:延时时间,鼠标停留/离开后延时多久开始显示/隐藏菜单 //speed:菜单显示速度,数字越大,显示越慢,默认为100 //调用示例:$("#button").DMenu("#content"); jQuery.fn.DMenu=function(showobj,

Android仿网易严选底部弹出菜单效果

在网易严选的看东西的时候在商品详情页里看到他的底部弹出菜单,本能反应是想用DottomSheetDialog或者PopupWindow来实现,可是发现实现不了他那种效果,于是就自己模仿一个像严选这样的底部弹出菜单. 不管是DottomSheetDialog或者PopupWindow他们的阴影背景都是全部覆盖的,这就造成除了菜单内容的View之外其他都是阴影的,而严选不是这样的.唠叨到此,首先展示效果图如下: 是不是还可以呢,由于代码量不多却注释详细,所以先贴出代码再一一详说: BottomPop

Android 高仿QQ滑动弹出菜单标记已读、未读消息

  在上一篇博客<Android 高仿微信(QQ)滑动弹出编辑.删除菜单效果,增加下拉刷新功能>里,已经带着大家学习如何使用SwipeMenuListView这一开源库实现滑动列表弹出菜单,接下来,将进一步学习,如何为不同的list item呈现不同的菜单,此处我们做一个实例:Android 高仿QQ滑动弹出菜单标记已读.未读消息,看下效果图: 1. 创建项目,并导入SwipeMenuListView类库 2. 创建消息实体bean: public class Msg { public int

Android仿QQ滑动弹出菜单标记已读、未读消息_Android

在上一篇<Android仿微信滑动弹出编辑.删除菜单效果.增加下拉刷新功能>里,已经带着大家学习如何使用SwipeMenuListView这一开源库实现滑动列表弹出菜单,接下来,将进一步学习,如何为不同的list item呈现不同的菜单,此处我们做一个实例:Android 高仿QQ滑动弹出菜单标记已读.未读消息,看下效果图: 1. 创建项目,并导入SwipeMenuListView类库 2. 创建消息实体bean: public class Msg { public int id; publi

Android仿QQ滑动弹出菜单标记已读、未读消息

在上一篇<Android仿微信滑动弹出编辑.删除菜单效果.增加下拉刷新功能>里,已经带着大家学习如何使用SwipeMenuListView这一开源库实现滑动列表弹出菜单,接下来,将进一步学习,如何为不同的list item呈现不同的菜单,此处我们做一个实例:Android 高仿QQ滑动弹出菜单标记已读.未读消息,看下效果图: 1. 创建项目,并导入SwipeMenuListView类库 2. 创建消息实体bean: public class Msg { public int id; publi