Android自定义组件之ListPopWindow

简介: 版权声明:本文为博主原创文章,转载请标明出处。 https://blog.csdn.net/lyhhj/article/details/50582900 最近小编在学习IOS开发,感触颇深,看到了iOS里面封装了好多组件,很多组件都是iOS自带的,相信一般的小公司的产品经理都是按照iOS的交互来设计UI,而且还要求Android要和iOS统一风格,这让Android开发人员很头痛,iOS自带组件很容易实现,而Android可能需要重写控件去配合iOS的效果。
版权声明:本文为博主原创文章,转载请标明出处。 https://blog.csdn.net/lyhhj/article/details/50582900

最近小编在学习IOS开发,感触颇深,看到了iOS里面封装了好多组件,很多组件都是iOS自带的,相信一般的小公司的产品经理都是按照iOS的交互来设计UI,而且还要求Android要和iOS统一风格,这让Android开发人员很头痛,iOS自带组件很容易实现,而Android可能需要重写控件去配合iOS的效果。其实这样必然会导致性能的小将,或有些许的卡顿。小编个人认为,按照各自系统的风格和规范进行设计才能把自己的优点发挥到最大化。
下面就引出了今天的主题,自定义组件ListPopWindow,iOS中,这个效果是自带的。PopWindow可以说在项目里用的比较多的了,可能有n处要用到PopWindow,那么自定义一个PopWindow,到处来用更方便一些。
先看一下效果:
这里写图片描述
效果就是这样,看一下实现,其实也没多难,就是想开源出来供小伙伴们使用,如有不合理地方,希望大家多多指正。

1.自定义PopWindow

首先我们分析一下,这样的效果肯定是一个PopWindow嵌套着listview,而上面的title、和下面的cancel是两个文本框,实现起来也比较简单。
然后我们在PopWindow中声明两个接口,用来回调cancel和item的点击事件

public interface  OnPopItemClickListener{
        void onPopItemClick(View view,int position);
    }

    public interface OnBottomTextviewClickListener{
        void onBottomClick();
    }

然后再设置一些PopWindow的一些属性

parentView = LayoutInflater.from(context).inflate(R.layout.list_popwindow,null);
        setContentView(parentView);
        lv = (ListView) parentView.findViewById(R.id.lv_popwindow);
        //设置弹出窗体的高
        this.setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
        this.setHeight(ViewGroup.LayoutParams.MATCH_PARENT);
        //设置弹出窗体可点击
        this.setFocusable(true);
        //实例化一个ColorDrawable颜色为半透明
        ColorDrawable dw = new ColorDrawable(0xb0000000);
        //设置SelectPicPopupWindow弹出窗体的背景
        this.setBackgroundDrawable(dw);

看一下整体的代码吧:

/**
 * Created by Hankkin on 16/1/25.
 */
public class ListPopWindow extends PopupWindow{

    private Context context;        //上下文
    private View parentView;        //父视图
    private List<PopBean> dataList; //item数据源
    private OnPopItemClickListener listener;    //item点击接口
    private ListView lv;    //item列表视图
    private View viewTop;   //title视图   
    private String topText,bottomText;  //title文字,bottom文字
    private TextView tvTop,tvBottom;    //title文本,bottom文本
    private PopWindowAdapter adapter;   //适配器
    private OnBottomTextviewClickListener bottomListener;//底部点击接口


    public interface  OnPopItemClickListener{
        void onPopItemClick(View view,int position);
    }

    public interface OnBottomTextviewClickListener{
        void onBottomClick();
    }

    public ListPopWindow(Context context,OnPopItemClickListener listener,OnBottomTextviewClickListener bottomListener,
                         View parentView,List<PopBean> dataList,String bottomText,String topText){
        this.context = context;
        this.listener = listener;
        this.parentView = parentView;
        this.dataList = dataList;
        this.bottomListener = bottomListener;
        this.topText = topText;
        this.bottomText = bottomText;

        initViews();
    }


    private void initViews(){
        parentView = LayoutInflater.from(context).inflate(R.layout.list_popwindow,null);
        setContentView(parentView);
        lv = (ListView) parentView.findViewById(R.id.lv_popwindow);
        //设置弹出窗体的高
        this.setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
        this.setHeight(ViewGroup.LayoutParams.MATCH_PARENT);
        //设置弹出窗体可点击
        this.setFocusable(true);
        //实例化一个ColorDrawable颜色为半透明
        ColorDrawable dw = new ColorDrawable(0xb0000000);
        //设置SelectPicPopupWindow弹出窗体的背景
        this.setBackgroundDrawable(dw);

        //view添加OnTouchListener监听判断获取触屏位置如果在布局外面则销毁弹出框
        parentView.setOnTouchListener(new View.OnTouchListener() {
            public boolean onTouch(View v, MotionEvent event) {
                int height = parentView.findViewById(R.id.ll_bottom).getTop();
                int y = (int) event.getY();
                if (event.getAction() == MotionEvent.ACTION_UP) {
                    if (y > height) {
                        dismiss();
                    }
                }
                return true;
            }
        });

        update();
        viewTop = parentView.findViewById(R.id.view_line1);
        tvBottom = (TextView) parentView.findViewById(R.id.tv_popwindow_bottom);
        tvTop = (TextView) parentView.findViewById(R.id.tv_popwindow_first);
        adapter = new PopWindowAdapter(context,dataList,false);
        lv.setAdapter(adapter);

        if (!TextUtils.isEmpty(topText)){
            tvTop.setVisibility(View.VISIBLE);
            tvTop.setText(topText);
            viewTop.setVisibility(View.VISIBLE);
        }
        else {
            tvTop.setVisibility(View.GONE);
            viewTop.setVisibility(View.GONE);
        }

        if (!TextUtils.isEmpty(bottomText)){
            tvBottom.setVisibility(View.VISIBLE);
            tvBottom.setText(bottomText);
        }
        else {
            tvBottom.setVisibility(View.GONE);
        }

        lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                listener.onPopItemClick(view, i);
            }
        });

        tvBottom.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                bottomListener.onBottomClick();
            }
        });

    }

}

2.看一些item的bean

这里我就声明了title和图片的id

package com.hankkin.library;

/**
 * Created by Hankkin on 16/1/25.
 */
public class PopBean {
    private String title;
    private int icon_res;

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public int getIcon_res() {
        return icon_res;
    }

    public void setIcon_res(int icon_res) {
        this.icon_res = icon_res;
    }

    public PopBean(String title, int icon_res) {
        this.title = title;
        this.icon_res = icon_res;
    }
}

3.自定义adapter适配器

这里面可能要注意的就是item的背景设置,有的是上半部分圆角、有的是下半部分圆角,特殊处理一下

@Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        ViewHolder holder;
        if (view == null) {
            view = inflater.inflate(R.layout.listview_popwindow_item, null);
            holder = new ViewHolder();
            holder.tv_name = (TextView) view.findViewById(R.id.tv_title);
            holder.v_line = (View) view.findViewById(R.id.v_line);
            view.setTag(holder);
        } else {
            holder = (ViewHolder) view.getTag();
        }

        holder.tv_name.setText(dataList.get(i).getTitle());


        if (dataList.size() - 1 == i) {
            holder.v_line.setVisibility(View.INVISIBLE);
            holder.tv_name.setBackground(context.getResources().getDrawable(R.drawable.selector_bottom_half));
        } else {
            holder.v_line.setVisibility(View.VISIBLE);
            holder.tv_name.setBackground(context.getResources().getDrawable(R.drawable.list_gray_item));
        }
        return view;
    }

最后看一下调用

Activity需要实现item接口(OnPopItemClickListener)和底部按钮接口(OnBottomTextviewClickListener)

public void show(View view){
        List<PopBean> pops = new ArrayList<>();
        for (int i=0;i<5;i++){
            PopBean pop = new PopBean("item"+i,0);
            pops.add(pop);
        }
        popWindow = new ListPopWindow(MainActivity.this,this,this,rl,pops,"cancel","title");
        popWindow.showAtLocation(rl, Gravity.CENTER| Gravity.BOTTOM,0,0);
    }

最后小编附上github源码地址,小伙伴们可以直接用哦。
https://github.com/Hankkin/ListPopwidowDemo

相关文章
|
1月前
|
Android开发
Android面试题之自定义View注意事项
在Android开发中,自定义View主要分为四类:直接继承View重写onDraw,继承ViewGroup创建布局,扩展特定View如TextView,以及继承特定ViewGroup。实现时需注意:支持wrap_content通过onMeasure处理,支持padding需在onDraw或onMeasure/onLayout中处理。避免在View中使用Handler,使用post系列方法代替。记得在onDetachedFromWindow时停止线程和动画以防止内存泄漏。处理滑动嵌套时解决滑动冲突,并避免在onDraw中大量创建临时对象。
23 4
|
19天前
|
机器学习/深度学习 人工智能 算法
探索AI在医疗影像分析中的应用探索安卓开发中的自定义View组件
【7月更文挑战第31天】随着人工智能技术的飞速发展,其在医疗健康领域的应用日益广泛。本文将聚焦于AI技术在医疗影像分析中的运用,探讨其如何通过深度学习模型提高诊断的准确性和效率。我们将介绍一些关键的深度学习算法,并通过实际代码示例展示这些算法是如何应用于医学影像的处理和分析中。文章旨在为读者提供对AI在医疗领域应用的深刻理解和实用知识。
22 0
|
1月前
|
前端开发 API Android开发
Android自定义View之Canvas一文搞定
这篇文章介绍了Android自定义View中如何使用Canvas和Paint来绘制图形。Canvas可理解为画布,用于绘制各种形状如文字、点、线、矩形、圆角矩形、圆和弧。常见API包括`drawText()`、`drawPoint()`、`drawLine()`、`drawRect()`等。文章还提到了Canvas的保存、恢复、平移和旋转方法,通过绘制钟表盘的例子展示了如何实际应用。总结关键点:Canvas与Paint结合用于图像绘制,掌握Canvas的基本绘图函数及坐标变换操作是自定义View的关键。
23 0
Android自定义View之Canvas一文搞定
|
2月前
|
API Android开发 开发者
`RecyclerView`是Android API 21引入的UI组件,用于替代ListView和GridView
【6月更文挑战第26天】`RecyclerView`是Android API 21引入的UI组件,用于替代ListView和GridView。它提供高效的数据视图复用,优化的布局管理,支持多种布局(如线性、网格),并解耦数据、适配器和视图。RecyclerView的灵活性、性能(如局部刷新和动画支持)和扩展性使其成为现代Android开发的首选,特别是在处理大规模数据集时。
36 2
|
2月前
|
搜索推荐 数据库 Android开发
自定义头像 Android
【6月更文挑战第16天】
|
1月前
|
消息中间件 前端开发 Android开发
Android面试题自定义View之Window、ViewRootImpl和View的三大流程
Android开发中,View的三大核心流程包括measure(测量)、layout(布局)和draw(绘制)。MeasureSpec类在测量过程中起到关键作用,它结合尺寸大小和模式(EXACTLY、AT_MOST、UNSPECIFIED)来指定View应如何测量。onMeasure方法用于自定义View的测量,布局阶段,ViewGroup调用onLayout确定子元素位置,而draw阶段按照特定顺序绘制背景、内容、子元素和装饰。整个流程始于ViewRootImpl的performTraversals,该方法触发测量、布局和绘制。
24 0
|
1月前
|
XML 数据格式
Android-自定义三角形评分控件
Android-自定义三角形评分控件
22 0
|
1月前
Android-自定义流布局标签
Android-自定义流布局标签
24 0
|
1月前
|
Android开发
Android自定义之高仿淘宝下拉刷新
Android自定义之高仿淘宝下拉刷新
26 0
|
1月前
|
Android开发
Android自定义之QQ身边的人
Android自定义之QQ身边的人
23 0