quickAction

article/2025/10/11 15:21:48

有一段时间没有上来折腾这个专题了,一来项目的确紧张,二来自己一惯是很懒的。
今天想与大家分享的是一个QuickAction的东西,模样其实就是通讯录中点击头像后弹出的那个提供可操作按钮的窗口。

这个效果其实我们也用过,就是QuickContactBadge。显然,它很有意思,但是为什么只能由系统决定上面的按钮呢?
所以今天我们要做的事情就是做一个自己的QuickAction类。


第一步:收集资源 

去Android的源代码网站 http://android.git.kernel.org/ 下载 Contacts 应用的源代码。在它的drawable目录里可以找到那些以quickcontacts_XXXXX的图片,就是我们需要用

来构造这个弹出窗口的图片资源。在layout目录里有quickcontact.xml则是我们需要的布局文件模板。当然,你也可以参考看看src/.../QuickContactsWindows.java文件。因为里

面就有今天我们要实现的内容,只是它太复杂了,已超出我们想要的功能。


第二步:设计布局

我们的布局文件quickaction.xml如下:

view plain copy to clipboard print ?
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="fill_parent"   
  4.     android:layout_height="wrap_content"  
  5. >  
  6.     <FrameLayout  
  7.         android:id="@id/qa_header"  
  8.         android:background="@drawable/quickcontact_top_frame"   
  9.         android:layout_width="fill_parent"   
  10.         android:layout_height="wrap_content"   
  11.         android:layout_marginTop="10.0dip" />  
  12.     <ImageView  
  13.         android:id="@id/qa_arrow_up"  
  14.         android:layout_width="wrap_content"   
  15.         android:layout_height="wrap_content"   
  16.         android:src="@drawable/quickcontact_arrow_up" />  
  17.           
  18.     <HorizontalScrollView   
  19.         android:id="@id/qa_scroll"   
  20.         android:background="@drawable/quickcontact_slider_background"   
  21.         android:scrollbars="none"   
  22.         android:fadingEdgeLength="0.0dip"   
  23.         android:layout_width="fill_parent"   
  24.         android:layout_height="wrap_content"   
  25.         android:layout_below="@id/qa_header">  
  26.         <LinearLayout   
  27.             android:orientation="horizontal"   
  28.             android:id="@id/qa_tracks"   
  29.             android:paddingTop="4.0dip"   
  30.             android:paddingBottom="4.0dip"   
  31.             android:layout_width="wrap_content"   
  32.             android:layout_height="wrap_content">  
  33.             <ImageView   
  34.                 android:layout_width="wrap_content"   
  35.                 android:layout_height="wrap_content"   
  36.                 android:src="@drawable/quickcontact_slider_grip_left" />  
  37.             <ImageView   
  38.                 android:layout_width="wrap_content"   
  39.                 android:layout_height="wrap_content"   
  40.                 android:src="@drawable/quickcontact_slider_grip_right" />  
  41.         </LinearLayout>  
  42.     </HorizontalScrollView>  
  43.       
  44.     <FrameLayout   
  45.         android:id="@id/qa_footer"   
  46.         android:background="@drawable/quickcontact_bottom_frame"   
  47.         android:layout_width="fill_parent"   
  48.         android:layout_height="wrap_content"   
  49.         android:layout_below="@id/qa_scroll" />  
  50.     <ImageView   
  51.         android:id="@id/qa_arrow_down"   
  52.         android:layout_width="wrap_content"   
  53.         android:layout_height="wrap_content"   
  54.         android:layout_marginTop="-1.0dip"   
  55.         android:src="@drawable/quickcontact_arrow_down"   
  56.         android:layout_below="@id/qa_footer" />  
  57. </RelativeLayout>  

 

里面很多东西都好理解,无非就是把图片堆砌一下罢了。重点说说放在中间的那个HorizontalScrollView里面的那个叫qa_tracks的LinearLayout。我们将来的所有按钮都是放在它

上面的,现在已经放了两个按钮(就是两边带点点的装饰按钮)。



第三步:现在开始写代码了,封装按钮的动作

view plain copy to clipboard print ?
  1. public class ActionItem {  
  2.   private Drawable icon;  
  3.   private View.OnClickListener listener;  
  4.   //以下代码省略  
  5. }  


代码超简单,只需要两样东西:图标和事件监听器。


第四步:现在可以做QuickAction了 

其实原理就是利用PopupWindow来显示quickaction布局文件,构造多个ActionItem实例放在qa_tracks里面就OK了。

具体实现如下:

  1. public class QuickAction {  
  2.     private static final String TAG="QuickAction";  
  3.     protected final View anchor; //弹出窗口的锚点  
  4.      
  5.     private View root; //弹出窗口的根  
  6.     public final PopupWindow window; //弹出窗口  
  7.     protected final WindowManager windowManager; //只是用来计算屏幕大小的  
  8.      
  9.     private ArrayList<ActionItem> actionList; //这里存放了很多的动作ActionItem  
  10.      
  11.     private final Context mContext;  
  12.     private final LayoutInflater inflater;  
  13.     private final ImageView mArrowDown;  
  14.     private final ImageView mArrowUp;  
  15.     private ViewGroup mTrack;  
  16.     private final Animation mTrackAnim;//显示出来时的动画效果  
  17.     private Interpolator mAnimationInterpolator = new Interpolator(){  
  18.         @Override  
  19.         public float getInterpolation(float i) {  
  20.             // TODO Auto-generated method stub  
  21.             //这个插值很重要,弹簧效果哦  
  22.             final float inner = (i * 1.55f) - 1.1f;  
  23.                     return 1.2f - inner * inner;  
  24.         }};  
  25.     public QuickAction(View v) {  
  26.         this.anchor = v;  
  27.          
  28.         this.mContext = v.getContext();  
  29.         this.inflater = LayoutInflater.from(this.mContext);  
  30.          
  31.         this.window = new PopupWindow(mContext);         
  32.         this.window.setTouchInterceptor(new View.OnTouchListener() {  
  33.              
  34.             @Override  
  35.             public boolean onTouch(View view, MotionEvent event) {  
  36.                 // TODO Auto-generated method stub  
  37.                 if (event.getAction() == MotionEvent.ACTION_OUTSIDE)  
  38.                       dismiss();  
  39.                 return false;  
  40.             }  
  41.         });  
  42.          
  43.         windowManager = (WindowManager)mContext.getSystemService("window");     
  44.          
  45.         this.actionList = new ArrayList<ActionItem>();  
  46.          
  47.         this.root = (ViewGroup)this.inflater.inflate(R.layout.quickaction, null);  
  48.          
  49.         this.mArrowDown =  (ImageView)this.root.findViewById(R.id.qa_arrow_down);  
  50.         this.mArrowUp = (ImageView)this.root.findViewById(R.id.qa_arrow_up);  
  51.          
  52.         this.window.setContentView(this.root);  
  53.          
  54.         //这里的动画anim文件及style,参考Contacts里的相应文件  
  55.         this.mTrackAnim = AnimationUtils.loadAnimation(this.mContext, R.anim.quickcontact);  
  56.         this.mTrackAnim.setInterpolator(mAnimationInterpolator);  
  57.          
  58.         this.mTrack =  (ViewGroup)this.root.findViewById(R.id.qa_tracks);  
  59.          
  60.       }  
  61.     public void dismiss() {  
  62.         this.window.dismiss();         
  63.     }  
  64.      
  65.     private void createActionList() {           
  66.         int i = 1;  
  67.         for(ActionItem ai : this.actionList){  
  68.             Drawable icon = ai.getIcon();  
  69.             View.OnClickListener listener=ai.getListener();  
  70.             View v = getActionItem(icon,listener);  
  71.             v.setFocusable(true);  
  72.             v.setClickable(true);  
  73.             this.mTrack.addView(v,i);  
  74.             i++;  
  75.         }  
  76.          
  77.     }  
  78.     private View getActionItem(Drawable icon, View.OnClickListener listener) {  
  79.         LinearLayout view = (LinearLayout)this.inflater.inflate(R.layout.action_item, null);  
  80.         ImageView ic = (ImageView)view.findViewById(R.id.ai_icon);  
  81.          
  82.         if (icon != null){  
  83.             ic.setImageDrawable(icon);  
  84.             if( listener!=null)  
  85.                 view.setOnClickListener(listener);  
  86.              
  87.             view.setVisibility(View.VISIBLE);  
  88.         }  
  89.         else  
  90.             view.setVisibility(View.GONE);  
  91.          
  92.         return view;         
  93.     }  
  94.      
  95.     public void addActionItem(ActionItem item) {  
  96.         this.actionList.add(item);  
  97.     }  
  98.     public void setOnDismissListener(PopupWindow.OnDismissListener listener) {  
  99.         this.window.setOnDismissListener(listener);  
  100.     }  
  101.      
  102.     protected void preShow() {  
  103.         if (this.root == nullthrow new IllegalStateException("setContentView was not called with a view to display.");  
  104.         this.window.setBackgroundDrawable(new BitmapDrawable());  
  105.          
  106.         this.window.setWidth(LayoutParams.FILL_PARENT);  
  107.         this.window.setHeight(LayoutParams.WRAP_CONTENT);  
  108.         this.window.setTouchable(true);  
  109.         this.window.setFocusable(true);  
  110.         this.window.setOutsideTouchable(true);  
  111.         this.window.setContentView(this.root);  
  112.          
  113.         //这里的动画anim文件及style,参考Contacts里的相应文件  
  114.         this.window.setAnimationStyle(R.style.QuickContactAboveAnimation);  
  115.          
  116.     }  
  117.      
  118.     private void showArrow(int resId, int margin) {  
  119.         ImageView v1=this.mArrowDown;  
  120.         ImageView v2=this.mArrowUp;  
  121.          
  122.         if (resId == R.id.qa_arrow_up){  
  123.             v1 = this.mArrowUp;  
  124.             v2= this.mArrowDown;  
  125.         }  
  126.          
  127.         int w = v1.getMeasuredWidth()/2;  
  128.         v1.setVisibility(View.VISIBLE);  
  129.         ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams)v1.getLayoutParams();  
  130.         params.leftMargin=margin-w;  
  131.         v2.setVisibility(View.INVISIBLE);         
  132.       }  
  133.       public void show() {  
  134.         preShow();  
  135.          
  136.         int[] loc = new int[2];  
  137.         this.anchor.getLocationOnScreen(loc);  
  138.         int i = loc[0];  
  139.         int j = loc[1];  
  140.          
  141.         int w = i + this.anchor.getWidth();  
  142.         int h = j + this.anchor.getHeight();  
  143.          
  144.         Rect localRect = new Rect(i, j, w, h);  
  145.         this.root.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT));  
  146.         this.root.measure(MeasureSpec.UNSPECIFIED,MeasureSpec.UNSPECIFIED);  
  147.          
  148.         int ww = this.root.getMeasuredWidth();  
  149.         int hh = this.root.getMeasuredHeight();  
  150.          
  151.         int dw = this.windowManager.getDefaultDisplay().getWidth();  
  152.          
  153.         int xx = ( dw- ww) / 2;  
  154.         int yy = localRect.top - hh + 10;  
  155.          
  156.         boolean isArrowDown = true;  
  157.         if (hh > (localRect.top - 50)) {  
  158.           yy = localRect.bottom - 10;  
  159.           isArrowDown = false;  
  160.         }  
  161.          
  162.         {  
  163.             int rid=isArrowDown?R.id.qa_arrow_down:R.id.qa_arrow_up;  
  164.             showArrow(rid, localRect.centerX());  
  165.              
  166.             createActionList();  
  167.              
  168.             this.window.showAtLocation(this.anchor, Gravity.NO_GRAVITY, xx, yy);  
  169.             //showDropDown();  
  170.              
  171.             this.mTrack.startAnimation(this.mTrackAnim);  
  172.            
  173.         }  
  174.       }  
  175. }  


不多解释了,注意事项参考代码中的注释即可。

 

那些漂亮的动画是必不可少的,而这又是GOOGLE已经提供了的,拿来用就是了。

最后的步骤:用它

在你要使用的地方(即原来放badge 位置上,修改成这样):

 

view plain copy to clipboard print ?
  1. <!--   
  2.         <QuickContactBadge   
  3.             android:id="@id/badge"   
  4.             style="@style/QCBTheme"  
  5.             android:background="#ffffff"  
  6.             android:layout_width="fill_parent"  
  7.             android:layout_height="fill_parent"  
  8.             android:layout_alignParentLeft="true"   
  9.             android:layout_centerVertical="true"   
  10.              />    
  11.         -->  
  12.         <ImageView  
  13.             android:id="@id/badge"   
  14.             style="@style/QCBTheme"  
  15.             android:background="#ffffff"  
  16.             android:layout_width="fill_parent"  
  17.             android:layout_height="fill_parent"  
  18.             android:layout_alignParentLeft="true"   
  19.             android:layout_centerVertical="true"   
  20.              />  

 

现在,在你的代码中手工构造并填写Action即可:

 

view plain copy to clipboard print ?
  1. //省略代码  
  2. //......  
  3. //构造ActionItem,设置好图标及点击事件监听器  
  4. ActionItem call=new ActionItem();  
  5.         call.setIcon(mContext.getResources().getDrawable(R.drawable.select_call));  
  6. call.setOnClickListener(mToast);  
  7. //,,,,,,  
  8. //,,,,,,  
  9.   
  10. //QuickContactBadge photo = (QuickContactBadge)convertView.findViewById(R.id.badge);  
  11. //找到锚点                
  12. final ImageView photo=  
  13. (ImageView)convertView.findViewById(R.id.badge);  
  14. //省略代码  
  15. //,,,,,,  
  16. //点击头像时弹出QuickAction  
  17. photo.setOnClickListener(new OnClickListener(){  
  18.     @Override  
  19.     public void onClick(View v) {  
  20.       action=new QuickAction(v);  
  21.         
  22.                           
  23.       action.addActionItem(call);  
  24.       action.addActionItem(imsg);  
  25.       action.addActionItem(detail);  
  26.                           
  27.                       
  28.       action.show();  
  29. }});  

 


http://chatgpt.dhexx.cn/article/3FnQWQSX.shtml

相关文章

快速检查(QuickCheck)(译)

source: http://www.jianshu.com/p/bb93972bac53 快速检查&#xff08;QuickCheck&#xff09;&#xff08;译&#xff09; 作者 低智商游戏 2016.02.01 00:26* 字数 4778 阅读 239 评论 0 喜欢 0 本文译自 objc.io出品的书籍《Functional Programming in swift》第六章&#…

quickbi使用

在maxcomputer中建表时应该注意四种建表方式不能使用临时查询的方式建立表结构&#xff0c;这种无法提交到生产环境&#xff0c;虽然在数据地图中可以查询到&#xff0c;但没提交生产环境中 暂时不知道这种情况&#xff1a;通过数据地图可以看到测试表通过临时查询简报方式也在…

阴阳师模型提取

0.声明 本文中的开发工具、第三方资源均用于学习用途&#xff0c;而非商业用途。本文中所有资源截止发稿时已全部删除 1.前言 最近一直在玩阴阳师。玩的时候我们不难观察到&#xff0c;现代游戏的制作中&#xff0c;画面、游戏体验都大大改善&#xff0c;除此之外&#xff0…

QUICKBMS 中文指南

我正打算做一个使用Quickbmsqu去解那些没有解包器的文档的教程。6 ?- s/ g/ B8 }, a$ ` 起步会很简单,然后越来越难,直到你学会并且编写你自己的脚本。 我们需要如下的四个工具: 1、16进制编辑器,比如HxD。(我用WINHEX) 2、Quick BMS http://aluigi.org/papers/quickbm…

quick bms的使用

下载工具quick bms&#xff0c;官网&#xff1a;http://aluigi.altervista.org/quickbms.htm 新建脚本 Script File -> New 选择你要操作的文件 Archive File -> Open Archive 选择输出目录 Folders -> Select Out Folder 编写脚本&#xff0c;点Quick Save保存脚…

乘方及方根运算电路

乘方及方根运算电路 图5.4-36是乘方运算电路。由于相乘器相移的影响&#xff0c;高次方运算会带来很大误差&#xff0c;通常串接的相乘器数量不超过2~3个。 图5.4-37是开方运算电路。要使此开方电路能稳定地工作&#xff0c;输入电压U1必须为负值。如果U1为正&#xff0c;将形…

比例运算电路(multisim实现)

目录 1.同相比例运算电路 ​ 输入与输出关系&#xff1a;​ 2.反相比例运算电路 输入与输出关系&#xff1a;​ 1.同相比例运算电路 仿真波形&#xff1a; 输入与输出关系&#xff1a; 2.反相比例运算电路 R2扫描波形 输入与输出关系&#xff1a;

模电总结二:基本运算电路

一、比例运算放大电路 二、加法运算放大电路 三、减法运算电路 四、积分运算电路 五、微分运算电路

大学模电实验合集丨实验六 比例求和运算电路

目录 一、实验目的 二、实验仪器 三、实验要求 五、根据实验报告回答下列问题 一、实验目的 1.掌握用集成运算放大电路组成比例、求和电路的特点及性能。 2.学会上述电路的测试和分析方法。 二、实验仪器 1.示波器 2.信号发生器 3.数字万用表 三、实验要求 在 MultiS…

【模拟电子技术Analog Electronics Technology 24】—— 信号的运算与处理(1):基本的运算电路分析

写在前面&#xff1a;在本篇博文中&#xff0c;我将分析几种常见的基本运算电路&#xff1a;比例运算电路&#xff0c;加减运算电路&#xff0c;微分和积分运算电路&#xff0c;指数和对数运算电路输入与输出的关系。但是&#xff0c;掌握单一的运算电路并不是我们的最终目的&a…

计算机系统基础(三)——运算电路基础

运算电路基础 数字逻辑电路基础运算电路基础数字逻辑电路基础 从C语言表达式到逻辑电路C语言支持的基本数据类型从C表达式到运算类指令从运算类指令到运算电路 C语言中各类运算算术运算按位运算逻辑运算移位运算截断和扩展运算 整数加减运算补码加减运算器无符号整数加法溢出判…

运算放大电路(比例运算电路)

0.反向比例运算电路 这是典型的并联反馈负反馈电路&#xff0c;输入电压U1通过电阻R作用于反向输入端&#xff0c;故输出电压与输入电压反向&#xff0c;同相输入端通过补偿电阻R接地&#xff0c;其值为U10时反相输入端的等效电阻&#xff0c;即各支路电阻的并联&#xff0c;因…

正弦运算电路

在很久之前&#xff0c;我在寻找一个能够进行正弦信号的电路。这个电路的意思不是说DDS正弦信号发生器。而是说&#xff0c;当输入一个信号x时&#xff0c;输出信号ysin⁡(x)&#xff0c;也就是说&#xff0c;输入信号xπ/2 V时&#xff0c;输出y1V&#xff0c;输入信号xπV时&…

模电笔记 基本运算电路

理想运放 “虚断” 理想运放的输入电阻为无穷大&#xff0c;流入两个输入端的电流近似为0 “虚短” 条件&#xff1a;理想运放工作于线性区&#xff08;存在负反馈&#xff09; 虚短&#xff1a;两个输入端的电位近似相等&#xff0c;净输入电压近似为0 比例运算电路 反…

实验二十一、积分运算电路的输出波形分析

一、题目 利用 Multisim 分析图1所示两个积分运算电路的输出波形&#xff0c;输入电压为 200 Hz、幅值为 1 V 的方波信号。 图 1 图1\,\, 图1 二、仿真电路 在 Multism 中搭建图1所示的两个电路&#xff0c;如图2所示。为了防止电路中的直流增益过大&#xff0c;故在电容上…

【反向和同向比例运算电路】

反向和同向比例运算电路 1.1 反相比例电路 1. 基本电路 电压并联负反馈输入端虚短、虚断   特点&#xff1a;   反相端为虚地&#xff0c;所以共模输入可视为0&#xff0c;对运放共模抑制比要求低   输出电阻小&#xff0c;带负载能力强   要求放大倍数较大时&#x…

减法器运算电路公式推导

前言 本人是菜鸟&#xff0c;有错误欢迎斧正&#xff0c;近期在看仪表放大器&#xff0c;其第二级放大电路就是一个减法器&#xff0c;大学教的我也忘的差不多了&#xff0c;于是开始网上冲浪&#xff0c;可是网上都是根据具体电路分析&#xff0c;或者分析的跳跃度很大&#…

数字电路基础(五)算术运算电路

数字电路基础&#xff08;五&#xff09;算术运算电路 一、二进制加法电路 1.半加器和全加器 &#xff08;1&#xff09;半加器 半加器是一个只考虑两个一位二进制数相加&#xff0c;而不考虑低位进位的运算电路。如下图所示是半加器的逻辑图&#xff1a; A A A和 B B B端…

积分运算电路的设计方法详细介绍

本文为大家介绍积分运算电路的设计。 积分运算电路的特性分析 下图为以集成运算放大器为核心元件的基本反相积分运算电路&#xff0c;输入电压uI经电阻R加至运算放大器的反相输入端&#xff0c;C为反馈电容&#xff0c;引入电压并联负反馈&#xff0c;R‘为平衡电阻&#xff…

积分和微分运算电路

目录 前言一、积分运算电路1.一般的积分运算电路2.稳定的积分运算电路 二、微分运算电路1.一般的微分运算电路2.稳定的微分运算电路 结语 前言 本文将分析积分运算电路和微分运算电路&#xff0c;运算电路基于通用型集成运放。文章从输入电阻、放大倍数、对称性、功能性、稳定…