关闭

仿uc下部弹出菜单

1434人阅读 评论(1) 收藏 举报
先说说我怎么会无聊到这种地步去弄这个代码呢,在今年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
0
0
查看评论

Android:高仿UC浏览器popupWindow菜单栏

Android:高仿UC浏览器popupWindow菜单栏
  • u012251822
  • u012251822
  • 2013-11-04 18:54
  • 2926

android 打造炫酷导航栏(仿UC头条)

年后开始上班甚是清闲,所以想捣鼓一些东西。在翻阅大神杰作Android 教你打造炫酷的ViewPagerIndicator 不仅仅是高仿MIUI 的时候看到下面有一条评论说,如果导航栏能滑动就更好了。我就想我可以去改一下就可以。然后又想感觉有点像UC的头条的界面。于是就往里面加东西,调试写...
  • qq_16064871
  • qq_16064871
  • 2016-02-17 20:33
  • 4937

自定义Behavior的艺术探索-仿UC浏览器主页

自定义Behavior实现UC浏览器主页
  • CsL664867596
  • CsL664867596
  • 2016-08-05 11:55
  • 2618

仿UC浏览器项目源码

本项目是一个功能非常完善的仿UC的安卓浏览器应用项目源码,支持断点续传,文件一次性下不完可以加接着下。有着比普通浏览器更快的下载速度。内置万能播放器,支持国内外大部分的视频网站的直播和点播。支持自定义主页,支持无图模式和网页内查找,查找内容会高亮显示,支持页面分享和书签/历史功能,支持夜间模式和多标...
  • zz2043191420
  • zz2043191420
  • 2015-08-21 09:54
  • 2060

高仿UC浏览器指导欢迎页面(NineOldAndroid实现)

前几天研究了下小米的卸载动画(上一篇博客),但是太丑了。今天升级了UC到10.4.2觉得指导页面还是很文艺的,用上次自己的接口大概实现了下(真心比小米的好模仿啊) 先上几张效果图 为了能更好的理解,我把每个动画都拆分了出来单个写,没有集成到一起批处理,个人觉得还是很...
  • qtstsq55
  • qtstsq55
  • 2015-05-27 23:55
  • 1129

android 高仿UC浏览器首页上拉面板效果

android 高仿UC浏览器首页上拉面板效果,最近在项目中,产品经理看见uc浏览器首页的上拉面板的效果做的非常不错,于是希望我们的项目的首页也做成这样的效果。于是经过思考后,实现了一个仿uc浏览器的上拉面板效果。
  • only1994
  • only1994
  • 2016-04-16 13:58
  • 5030

android仿新版UC首页,上滑隐藏顶部轮播图,支持单个栏目下拉刷新,左右滑动切换

本博客由gengqiquan原创,转载请注明出处http://blog.csdn.net/gengqiquan/article/details/50542334尊重他人的技术劳动成果,谢谢 UI妹子是个喜欢看各种软件的妹子,这不,最近看上了UC的首页,于是把我们的应用也改成了这样的风格,本着不...
  • gengqiquan
  • gengqiquan
  • 2016-01-19 14:31
  • 12453

【Android】仿UC网络判断效果

利用BroadcastReceive广播接收器来监听网络状态的变化,然后呼出自定义窗口Activity来进行网络的打开关闭操作.
  • zz2043191420
  • zz2043191420
  • 2015-07-17 09:29
  • 880

仿UC视频播放(iOS源代码)

转载自:   http://www.okbase.net/file/item/33894 源码目录结构图 LSPlayer LSPlayer-master._LSPlayer-master 介绍 来源: github/LS...
  • chenyong05314
  • chenyong05314
  • 2017-06-01 17:07
  • 390

Android 仿UC浏览器三点加载效果

1.import android.app.Activity; import android.content.Context; import android.content.res.Resources; import android.content.res.TypedArray; import and...
  • jky_yihuangxing
  • jky_yihuangxing
  • 2016-08-17 13:32
  • 1355
    本人新书
    个人资料
    • 访问:2226639次
    • 积分:29390
    • 等级:
    • 排名:第207名
    • 原创:763篇
    • 转载:267篇
    • 译文:25篇
    • 评论:395条
    技术公众号
      欢迎关注我的公众号,每天为你推荐最新的博文,与大家一起学习共同进步!
    博客专栏
    站长统计
    微博
    最新评论
    本人新作

    新书