ListView模仿——支付宝手机客户端长按ListView的Item弹出操作按钮效果

微信小程序点击商品按钮从底部出现商品详情弹框 /*wsml*/ <!-- 弹出购买详情 --> <view bindtap='showModal'> click me </view> <code class="language-html"><!--屏幕背景变暗的背景 --> <view class="commodity_screen" bindtap="hide... 阅读详情

效果

首先上两张图:


左面一张是支付宝手机客户端的截图,右面是最终实现的效果图。长按listView的item,会弹出一个View覆盖在长按的那个item上。点击相应按钮,即可执行对应的操作。点击手机返回键隐藏操作按钮组。当滚动ListView时,显示的按钮组离开当前界面后会消失。


分析

之前很多时候,自己的想法就是长按item,弹出一个dialog,在dialog中做一些操作然后反映到listview上。相信很多人也跟我一样。看到这个效果之后感觉在用户体验上比dialog有不少进步,遂想记录之。当然还有一些更酷更炫的效果,比如QQ的在item上滑动显示一个删除按钮,其他的左滑和右滑实现功能,拖动改变item顺序,这些在之后的文章中继续模仿吐舌头

分析下,这个功能模仿到形似很简单:监听用户长按,记录当前item的ID,然后通知adapter数据改变,重新计算item的时候显示操作按钮组;用户点击返回时,若当前有操作按钮组显示则首先隐藏,这个只需要将item的ID置位即可;当用户将当前item滑出屏幕再重新计算item时将按钮组隐藏,这个在listview的OnScrollListener中处理。复杂一点的没有item不同的时候显示不通的操作按钮组,这个暂时没有实现。


实现

这里直接贴核心代码了,代码中都有注释:
/**
 * 自定义的ListView,模仿支付宝手机客户端的第一个界面的ListView效果:长按某个Item时在Item上显示操作按钮<br>
 * 个人认为, 这个体验应该比长按弹出对话框要好<br>
 * 实现思路:<br>
 * 监听用户长按,记录当前item的ID,然后显示操作按钮<br>
 * 调用方法:<br>
 * 自定义的ListViewAapter继承这个CustomAdapter实现必要的方法即可
 * 
 * @author ttdevs
 * 
 */
public abstract class CustomAdapter extends BaseAdapter implements OnItemLongClickListener, OnScrollListener {

	private Context mContext;
	private ListView mListView;
	private List<OperateList> mOpList;
	private LinearLayout mOperateLayout;
	private OnCustomItemLongClickListener mListener;

	private int showPosition = -1;

	public CustomAdapter(Context context, ListView listView) {
		mContext = context;
		mListView = listView;
		mListView.setOnItemLongClickListener(this);
		mListView.setOnScrollListener(this);
	}

	@Override
	public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
		if (mOpList != null) {
			showPosition = position;
			notifyDataSetChanged();
		}
		return true;
	}

	public void setOnCustomItemLongClick(List<OperateList> opList, OnCustomItemLongClickListener listener) {
		if (opList != null && opList.size() > 0 && listener != null) {
			mOpList = opList;
			mListener = listener;
		}
	}

	@Override
	public void onScrollStateChanged(AbsListView view, int scrollState) {
		// TODO Auto-generated method stub

	}

	@Override
	public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
		// 这个地方主要处理选中item被滑出界面时隐藏按钮组的逻辑
		if (showPosition > (firstVisibleItem + visibleItemCount) || showPosition < firstVisibleItem) {
			showPosition = -1;
		}
	}

	/**
	 * 隐藏操作按钮组:置位showPostion,通知adapter数据有变
	 * 
	 * @return
	 */
	public boolean hideOperateView() {
		if (showPosition == -1) {
			return false;
		} else {
			showPosition = -1;
			notifyDataSetChanged();
			return true;
		}
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		System.err.println(position + "convertView == null>>>>>" + (convertView == null));
		convertView = getCustomView(position, convertView, parent);
		if (position == showPosition) {
			addOperateButtonView(position, convertView, parent);
		}
		return convertView;
	}

	/**
	 * 自定义的一个方法,用来替代getView(),这样可以保证执行完创建Item之后做自己想要的事情:添加操作按钮组到item上
	 * 
	 * @param position
	 * @param convertView
	 * @param parent
	 * @return
	 */
	public abstract View getCustomView(int position, View convertView, ViewGroup parent);

	/**
	 * 添加操作按钮所在的布局,这个地方要求ListView的Item必须为FrameLayout,否则会报错
	 * 
	 * @param position
	 * @param convertView
	 * @param parent
	 */
	private void addOperateButtonView(int position, View convertView, ViewGroup parent) {
		if (mOpList == null) {
			return;
		}
		try {
			FrameLayout flOperate = (FrameLayout) convertView;
			// if (mOperateLayout == null) { // TODO 这个地方加上会没有效果,很奇怪
			mOperateLayout = new LinearLayout(mContext);
			mOperateLayout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
			mOperateLayout.setOrientation(LinearLayout.HORIZONTAL);
			mOperateLayout.setBackgroundColor(Color.parseColor("#88FE9D3D"));
			mOperateLayout.setGravity(Gravity.CENTER);
			// }
			for (int i = 0; i < mOpList.size(); i++) {
				addOperateButton(mOperateLayout, mOpList.get(i), position, convertView);
				if (i != mOpList.size() - 1) {
					addOperateButtonDivider(mOperateLayout);
				}
			}
			flOperate.addView(mOperateLayout);
		} catch (Exception e) {
			String toast = "CustomAdapter:ListView's item layout must be FrameLayout!";
			Toast.makeText(mContext, toast, Toast.LENGTH_LONG).show();
		}
	}

	/**
	 * 添加一个按钮,先创建一个线性布局,然后在里面添加ImageView和TextView
	 * 
	 * @param mOperateLayout
	 * @param opList
	 * @param position
	 * @param convertView
	 */
	@SuppressWarnings("deprecation")
	public void addOperateButton(LinearLayout mOperateLayout, OperateList opList, final int position,
			final View convertView) {
		final int flag = opList.getFlag();

		LinearLayout llButtom = new LinearLayout(mContext);
		llButtom.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
		llButtom.setOrientation(LinearLayout.HORIZONTAL);
		llButtom.setGravity(Gravity.CENTER);
		// llButtom.setBackground(getSelectorDrawable());
		llButtom.setBackgroundDrawable(getSelectorDrawable());
		llButtom.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				mListener.onCustomItemLongClick(flag, position, convertView);
			}
		});

		ImageView ivIcon = new ImageView(mContext);
		ivIcon.setImageResource(opList.getDrawableId());
		ivIcon.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
		llButtom.addView(ivIcon);

		TextView tvOperate = new TextView(mContext);
		tvOperate.setText(opList.getContent());
		tvOperate.setGravity(Gravity.CENTER_VERTICAL);
		tvOperate.setTextSize(16);
		tvOperate.setTextColor(Color.parseColor("#FF3399FF"));

		llButtom.addView(tvOperate);

		LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,
				LayoutParams.MATCH_PARENT);
		lp.weight = 1;
		mOperateLayout.addView(llButtom, lp);
	}

	/** 添加一条分隔线 */
	public void addOperateButtonDivider(LinearLayout mOperateLayout) {
		ImageView ivBg = new ImageView(mContext);
		ivBg.setBackgroundColor(Color.parseColor("#FFFFFFFF"));

		LinearLayout.LayoutParams lpDivider = new LinearLayout.LayoutParams(2, LayoutParams.MATCH_PARENT);
		lpDivider.setMargins(0, 6, 0, 6);

		mOperateLayout.addView(ivBg, lpDivider);
	}

	/** 获取一个selector */
	public Drawable getSelectorDrawable() {
		ColorDrawable cdNormal = new ColorDrawable(Color.parseColor("#88FE9D3D"));
		ColorDrawable cdPressed = new ColorDrawable(Color.parseColor("#EEFE9D3D"));
		StateListDrawable sld = new StateListDrawable();
		sld.addState(new int[] { -android.R.attr.state_pressed }, cdNormal);
		sld.addState(new int[] { android.R.attr.state_pressed }, cdPressed);
		return sld;
	}

	/** 自定义的接口,处理用户单击返回 */
	public interface OnCustomItemLongClickListener {
		public void onCustomItemLongClick(int flag, int position, View itemView);
	}
}

自己的adapter需要继承这个CustomAdapter,一个简单的实现如下:
public class ListViewAdapter extends CustomAdapter {
	private String[] mValues;
	private LayoutInflater mInflater;
	private Context mContext;

	public ListViewAdapter(Context context, ListView listView, String[] values) {
		super(context, listView);
		mContext = context;
		mInflater = LayoutInflater.from(context);
		mValues = values;
	}

	@Override
	public int getCount() {
		return mValues.length;
	}

	@Override
	public Object getItem(int position) {
		return mValues[position];
	}

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

	@Override
	public View getCustomView(int position, View convertView, ViewGroup parent) {
		// 此处不是重点,简单写之
		convertView = mInflater.inflate(R.layout.item_main, null);
		TextView tvTitle = (TextView)convertView.findViewById(R.id.tvTitle);
		tvTitle.setText(mValues[position]);

		return convertView;
	}
}

调用的地方也需要实现一些简单的逻辑,如初始化数据,处理返回按键:
public class MainActivity extends Activity implements OnCustomItemLongClickListener {

	private String[] mStrings = Cheeses.sCheeseStrings;
	private ListView lvMain;
	private List<OperateList> opList;
	private ListViewAdapter adapter;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		initData();
		
		lvMain = (ListView) findViewById(R.id.lvMain);
		adapter = new ListViewAdapter(this, lvMain, mStrings);
		adapter.setOnCustomItemLongClick(opList, this);
		lvMain.setAdapter(adapter);
	}

	@Override
	public void onBackPressed() {
		if (!adapter.hideOperateView()) {
			super.onBackPressed();
		}
	}

	private void initData() {
		opList = new ArrayList<OperateList>();

		OperateList ob = new OperateList();
		ob.setDrawableId(R.drawable.ic_undo);
		ob.setContent("撤销");
		ob.setFlag(1);
		opList.add(ob);
	}

	@Override
	public void onCustomItemLongClick(int flag, int position, View itemView) {
		System.out.println("onCustomItemLongClick:" + flag + "||" + position + "||" + itemView);
	}
}

这样就实现最后的效果。

总结

设计的时候本想把他设计的更通用些,这样以后用着也方便,尝试了下去自定义listview,同时自定义listview和adapter,但是都不满意,最终决定还是只自定义一个adapter。仔细的你可能已经发现,还有很多局限性,比如item的布局必须是FrameLayout,能力有限,不知道怎么把这个限制去掉,如果你有好的思路,欢迎指教~~

源码下载





点击listview的item在所点击的item的上边弹出popwindow 点击listview的某个item,在所点击的item的上部弹出popwindow, 手指弹起则消失,类似于qq消息的长按弹出的删除功能 立即下载

相关推荐

Android ListView长按弹出菜单二种实现方式示例

代码如下:/** * 知识点1:ListView item:两种长按弹出菜单方式* 知识点2:ListView SimpleAdapter的使用* 知识点 3:在java代码中创建一个ListView*/ public class ListOnLongClickActivity extends Activity {         private LinearLayout myListViewlayout;         private ListView mListView;         SimpleAdapter adapter;         public int MID;  

android自定义长按菜单,Android ListView长按弹出菜单二种实现方式示例

/*** 知识点1:ListView item:两种长按弹出菜单方式* 知识点2:ListView SimpleAdapter的使用*知识点 3:在java代码中创建一个ListView*/public class ListOnLongClickActivity extends Activity {private LinearLayout myListViewlayout;private Lis...

weixin_39754915的博客 496

Ribo-seq数据解析:从翻译效率计算到动态可视化分析

本文系统介绍了Ribo-seq(核糖体印迹测序)数据分析全流程,从核心的P-site定位、翻译效率计算,到差异翻译分析和动态可视化。重点阐述了如何利用Ribo-seq高分辨率数据揭示基因表达在翻译层面的精细调控,并提供了从数据处理到生物学解读的实用工具与避坑指南。

weixin_28559803的博客 422

Android之 弹框总结

弹框总结

qq_29848853的博客 4669

基于Multisim的模电调幅发射机仿真设计

振荡器产生的高频信号的功率很小,所以有必要对高频信号进行功率放大,有利于信号的调制发射。缓冲电路将主振荡器和高频功放电路相隔离,以减小功放电路对主振荡器的影响。缓冲电路可以用射极跟随器电路来实现,其作用就是前后级的阻抗相互匹配,减小前后级的影响。总电路的仿真结果见下图:示波器1~4分别是主振荡器、缓冲电路、高频放大电路和调幅电路的输出波形。由于载波频率稳定度≤10-3,所以可以采用并联型改进电容反馈式三端振荡器(Seiler电路)谐振回路,滤除其他频率的成分,得到与载波(假设。(1)缓冲电路的设计与实现。

Eve223322的博客 4594

PSIM仿真实战:反激电源从设计到调试的完整流程(附短路保护配置)

本文详细介绍了使用PSIM仿真工具进行反激电源从设计到调试的完整流程,包括变压器参数设计、功率器件选型、动态特性调试以及短路保护配置。通过实战案例和仿真技巧,帮助工程师提前暴露并解决设计中的常见问题,如负载突变、输入电压波动和短路保护失效等,显著降低硬件试错成本。

weixin_29216353的博客 244

recyclerView的写法--实现长按item弹出菜单功能,每个item实现偏移

recyclerView的写法导入到工程中 导入到工程中 在你的工程上点击右键,弹出如下图片,大家看图吧 点击ok后,这个recyclerview-v7的包就引用到自己的工程里了,也不用管那个build.jradle文件了,打开会发现已经自动填好了. ...

Barryjacket的博客 1962

如何优雅地进行频谱分析—— 一行代码实现绘制MATLAB频谱、功率谱图

之前的文章里讲了关于信号频谱、能量谱的相关理论和MATLAB编程实现方法: Mr.看海:信号频域分析方法的理解(频谱、能量谱、功率谱、倒频谱、小波分析) Mr.看海:频域特征值提取的MATLAB代码实现(频谱、功率谱、倒频谱) 不过对于刚刚开始进行这方面研究,或者对MATLAB不甚熟悉,抑或者不想花太多时间用在编程这件事上的同学,目前缺少一种足够便捷、高效、可靠的代码。 所以笔者想做这样一件事:编写一个函数,同学们只需要导入自己要分析的数据,并按照自己的需求设置部分选项,调用一行代码就可以实现绘制频

fengzhuqiaoqiu的博客 2万+

Android onItemLongClick+onCreateContextMenu setOnCreateContextMenuListener实现长按ListItem弹出不同菜单

转:http://hi.baidu.com/dean_wang/blog/item/00b0e247d223b528cefca374.htmlAndroid onItemLongClick+onCreateContextMenu实现长按ListItem弹出不同菜单2010-09-07 18:29    前一段时间做项目需要做一个效果:一个ListActivity,长按不同的item弹出的菜单不一样;如下图所示我们长按不同的item需要弹出不同标题的menu:<br />     <br />    长按事件

gaoyizyy2008的专栏 3255

【iOS开发】dyld: Symbol not found: ___chkstk_darwin 问题解决

【iOS开发】dyld: Symbol not found: ___chkstk_darwin 问题解决 Xcode 13.2.1 运行到iOS12.x版本上崩溃报错如下:dyld: Symbol not found: ___chkstk_darwin dyld: Symbol not found: ___chkstk_darwin Referenced from: /private/var/containers/Bundle/Application/A424CEFD-51DB-450E-9D62-B8

wm9028的专栏 6566

差分信号_差分信号的原理及其在PCB的设计

差分线是 PCB 设计中非常重要的一部分信号线,信号处理要求也是相当严谨,今天为大家介绍下差分信号的原理以及其在 PCB 设计中的处理方法。 什么是差分信号 差分传输是一种信号传输的技术,区别于传统的一根信号线一根地线的做法,差分传输在这两根线上都传输信号,这两个信号的振幅相等,相位相差 180 度,极性相反。在这两根线上传输的信号就是差分...

weixin_31849185的博客 1812

ListView onItemLongClick 弹出ContextMenu

开发了一个简单的功能: 长按ListView中的item后, 弹出选择菜单: public class NetworktoolActivity extends Activity implements View.OnClickListener, AdapterView.OnItemLongClickListener{ boolean isSendItem = false; int

ansondroider的博客 1088

精读204页华为的流程管理(文末附下载链接)

链接:https://pan.baidu.com/s/1eEwdBR5c0PIxkOrNhDZcGg?pwd=wha2 提取码:wha2 复制这段内容后打开百度网盘手机App,操作更方便哦。,以提升企业运营效率和竞争力,同时解决了诸多业务痛点,为华为的全球化发展提供了有力支撑。华为的流程管理对其发展起着关键作用,通过构建完善的流程体系,提升了企业运营效率与竞争力。华为的流程管理在企业发展中至关重要,其围绕。,并通过流程变革不断优化。在流程管理过程中,强调。构建了全面的流程体系。

cdfunlove的博客 283

android onitemlongclick参数,在Android中使用弹出菜单实现OnItemLongClickListener到Android的ListView...

我有一个listview,我已经保存了一个弹出式菜单。所以我可以在长按一个listview项目时弹出菜单。我的弹出式菜单方法如下:在Android中使用弹出菜单实现OnItemLongClickListener到Android的ListViewvoid delete(){listView.setOnItemLongClickListener(new AdapterView.OnItemLongCl...

weixin_35521169的博客 392

ProgLoss+STAL 技术详解:YOLO26 小目标检测增强方案

本文提出了一种基于ProgLoss渐进式损失函数和STAL小目标感知标签分配的YOLO26增强方案。针对小目标检测中特征信息少、正负样本不平衡等难题,STAL通过尺度感知的标签分配策略动态调整候选样本数量和IoU阈值,为小目标分配更多正样本;ProgLoss则根据训练阶段动态调整分类和回归损失的权重,早期侧重定位能力,后期加强分类精度。实验表明,该组合方案显著提升了小目标检测性能,在COCO数据集上小目标AP达到38.2%,比基线提升6.5个百分点。该方法为遥感、监控等场景的小目标检测提供了有效解决方案。

一键难忘的博客 1290

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

Android中listview长按弹出选择菜单的两种实现

使用ContextMenu或PopupMenu均可实现 listview布局 <ListView android:layout_width="match_parent" android:layout_height="655dp" android:id="@+id/listView"></ListView> private ListView listView; listView = (ListView) findViewById(R.i

dsaaf21的博客 2976

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

Android期末复习4-3:使用弹出菜单PopupMenu(长按弹出型菜单,比ContextMenu好用)

1.了解PopupMenu的工作原理:不像ContextMenu那样重写两个光秃秃的方法,而是可以直接创建PopupMenu对象,想要对哪个View实现PopupMenu功能直接通过它的构造方法把这个View传进去即可,然后PopupMenu如何创建PopupMenu对象。2.在MainActivity.java中给View实现PopupMenu的步骤。3.PopupMenu如何填充菜单。4.PopupMenu如何对菜单项点击事件处理

qq_65836449的博客 1224

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

长按listview弹出操作菜单

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_33937778的博客 823

android长按呼出菜单,Android ListView 长按列表弹出菜单

Android ListView 长按列表弹出菜单设置长按菜单listView.setOnCreateContextMenuListener(new View.OnCreateContextMenuListener() {@Overridepublic void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuIn...

weixin_42279320的博客 886

ListView长按弹出菜单项

要使用listview的setOnCreateContextMenuListener监听,并重写onContextItemSelected方法,共同完成弹出菜单项,点击菜单项做相应的操作。1、为ListView添加长按弹出菜单项事件listView.setOnCreateContextMenuListener(new View.OnCreateContextMenuListener() {

hello_1s的博客 2632

Android ListView长按事件弹出菜单并获取选中的item

看了很多listview的长按事件,但几乎都是只给出弹出菜单的代码,没有给出选中的某个项的代码,我贴个全的吧,免得摸索麻烦 思路就是 listview在父窗口先注册一个长按弹出菜单registerReceiver=》设置一个长按的listener,保存好选中item数据=》onCreateContextMenu添加菜单=》onContextItemSelected菜单响应处理; 就这么简单。

鑫路,鑫的未来。。。 1万+

Android学习----------长按列表项弹出菜单,给菜单项添加事件,获取上下文

这里是先显示一个listview,长按listview的一个列表项,弹出一个菜单来,菜单有两个条目, “更新该条”和“删除该条”,并且这两条都有监听事件,整体就像微信好友对话操作一样。 其中菜单项有一个获取上下文的操作:AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo(); 这句也是用于列表项的。

FFA(Frighting for Ambition!) 3504

长按item弹出菜单

长按item弹出菜单,并作出相应 item中包含复选框,点击选项可实现勾选取消,adapter继承BaseAdapter 代码如下 MainActivity` import java.util.ArrayList; import java.util.List; import org.w3c.dom.Text; import android.R.string; import android.nf...

weixin_43858255的博客 379

ListView的长按菜单

Android的listview可以长按弹出来一个菜单。今天就跟了下代码大概看了下弹出菜单的流程。我们实现一个菜单长按步骤通常如下:1、弹出菜单的生成如果控制listview长按应该生成什么样的菜单。a、生成一个OnCreateContextMenuListener的接口对象l该接口定义如下:在view.java中 public interface OnCreateContextMenuListener { /** * Called when the contex

elfylin的专栏 8806

ListView项目长按的菜单功能总结

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_33806300的博客 132
上一篇: ViewHolder vs HolderView
下一篇: 简单记录——android selector对应的java实现:StateListDrawable
ttdevs
博客等级 码龄15年 388粉丝 91原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值