ListView/Popwindow 自定义控件

135 阅读2分钟

跟随鸿洋大神的步伐研究代码-写一个ListView上左滑跳出popwindow删除ListItem的自定义控件 并记录下关于几个不熟悉的类的使用和解释

1.ViewConfiguration.get(context)

//  获取touchSlop (系统 滑动距离的最小值,大于该值可以认为滑动)
int touchSlop = viewConfiguration.getScaledTouchSlop();
//  获得允许执行fling (抛)的最小速度值
int minimumVelocity = viewConfiguration.getScaledMinimumFlingVelocity();
//  获得允许执行fling (抛)的最大速度值
int maximumVelocity = viewConfiguration.getScaledMaximumFlingVelocity();
//  Report if the device has a permanent menu key available to the user 
//  (报告设备是否有用户可找到的永久的菜单按键)
//  即判断设备是否有返回、主页、菜单键等实体按键(非虚拟按键)
boolean hasPermanentMenuKey = viewConfiguration.hasPermanentMenuKey();  

2.ListView中pointToPosition()

//根据触摸点的坐标计算出点击的是ListView的哪个Item
int mCurrent = pointToPosition();
//获取界面中显示可见的第一个item的下标
int firstPosition = lisView.getFirstVisiblePosition();
//获取界面中显示可见的最后一个item的下标;
int lastPosition = lisView.getLastVisiblePosition();
//获取界面显示可见的liem的列目总数
int childCount = lisView.getChildCount();

自定义控件的代码


public class QQListView extends ListView {
    private static final String TAG = "QQListView";
    private int xMove;//移动X坐标
    private int yMove;//移动Y坐标
    private int xDown;//按下X坐标
    private int yDown;//按下Y坐标
    private boolean isSlide;//是否移动
    private int touchSlop;//最小距离
    private LayoutInflater layoutInflater;
    private PopupWindow popupWindow;
    private int popWindowHeight;//高
    private int popWindowWidth;//宽
    private Button mBtn;
    private int mCurrentPos;
    private View mCurrentView;
    private DelButtonClickListener delButtonClickListener;

    public void setDelButtonClickListener(DelButtonClickListener delButtonClickListener) {
        this.delButtonClickListener = delButtonClickListener;
    }



    public QQListView(Context context, AttributeSet attrs) {
        super(context, attrs);
        layoutInflater = LayoutInflater.from(context);
        //  获取touchSlop (系统 滑动距离的最小值,大于该值可以认为滑动)
        touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
        View v = layoutInflater.inflate(R.layout.item_btn,null);
        mBtn = v.findViewById(R.id.btn);

        popupWindow = new PopupWindow(v, LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT);

        popupWindow.getContentView().measure(0,0);//获取视图设置成不限制测量大小
        popWindowHeight = popupWindow.getContentView().getMeasuredHeight();
        popWindowWidth = popupWindow.getContentView().getMeasuredWidth();

    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        int action = ev.getAction();
        //获取触摸的坐标
        int x = (int)ev.getX();
        int y = (int)ev.getY();
        switch (action){
            case MotionEvent.ACTION_DOWN:
                xDown = x;
                yDown = y;
                if(popupWindow.isShowing()){
                    dismissPopWindow();
                    return false;
                }
                //根据触摸点的坐标计算出点击的是ListView的哪个Item
                mCurrentPos = pointToPosition(xDown,yDown);
                /**
                 *childCount 12说明屏幕上只能显示12个数据
                 * first = 2;mCurrentPos = 5;last = 13;就会截取显示的数据为数组这样下标就会被重新定义0-11;
                 * getChildAt(3) //这就是重新定数组只有的下标
                 */
                mCurrentView = getChildAt(mCurrentPos - getFirstVisiblePosition());
                break;
            case MotionEvent.ACTION_MOVE:
                xMove = x;
                yMove = y;
                int dx = xMove - xDown;
                int dy = yMove - yDown;
                    //移动最终的点小于按下的点说名是向左滑动 并且 移动最终的点-按下的点 肯定是 负值 所以要 绝对值一下
                    //既然是向左滑动 那上下的移动就不能超过 滑动的移动范围
                if(xMove < xDown && Math.abs(dx) > touchSlop && Math.abs(dy) <touchSlop ){
                    isSlide = true;
                }
                break;
        }
        return super.dispatchTouchEvent(ev);

    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        int action = ev.getAction();
        if(isSlide){
            switch (action){
                case MotionEvent.ACTION_MOVE:
                    int location[] = new int[2];
                    mCurrentView.getLocationOnScreen(location);
                    popupWindow.update();
                    popupWindow.showAtLocation(mCurrentView, Gravity.TOP|Gravity.LEFT
                    ,location[0]+mCurrentView.getWidth(),
                            location[1]+mCurrentView.getHeight()/2-popWindowHeight/2);

                    mBtn.setOnClickListener(new OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            if(delButtonClickListener != null){
                                delButtonClickListener.clickHappend(mCurrentPos);
                                popupWindow.dismiss();
                            }
                        }
                    });
                    break;
                case MotionEvent.ACTION_UP:
                    isSlide = false;
                    break;
            }
            return true;
        }
        return super.onTouchEvent(ev);
    }

    private void dismissPopWindow()
    {
        if (popupWindow != null && popupWindow.isShowing())
        {
            popupWindow.dismiss();
        }
    }

    public interface DelButtonClickListener{
        public void clickHappend(int position);
    }
}

mainActivity

public class MainActivity extends AppCompatActivity {
    private QQListView listView;
    private ArrayAdapter<String> mAdapter;
    private List<String> mDatas;

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

    public void init() {
        listView = findViewById(R.id.listView);
        mDatas = new ArrayList<String>(Arrays.asList("HelloWorld", "Welcome", "Java", "Android", "Servlet", "Struts",
                "Hibernate", "Spring", "HTML5", "Javascript", "Lucene"));
        mAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mDatas);
        listView.setAdapter(mAdapter);

    }

    public void dealDelInterface() {
        listView.setDelButtonClickListener(new QQListView.DelButtonClickListener() {
            @Override
            public void clickHappend(int position) {
                Toast.makeText(MainActivity.this, position + " : " + mAdapter.getItem(position), Toast.LENGTH_SHORT).show();
                mAdapter.remove(mAdapter.getItem(position));

            }
        });
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Toast.makeText(MainActivity.this, position + " : " + mAdapter.getItem(position), Toast.LENGTH_SHORT).show();
            }
        });

    }
}

anim-pupop_enter/pupop_exit


<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <scale android:fromXScale="0.6" android:toXScale="1.0"
        android:fromYScale="0.6" android:toYScale="1.0" android:pivotX="50%"
        android:pivotY="50%" android:duration="1000" />
    <alpha android:interpolator="@android:anim/decelerate_interpolator"
        android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="1000" />

</set>

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <scale
        android:fromXScale="1.0"
        android:toXScale="0.5"
        android:fromYScale="1.0"
        android:toYScale="0.5"
        android:pivotX="50%"
        android:pivotY="50%"
        android:duration="500" />
    <alpha
        android:interpolator="@android:anim/accelerate_interpolator"
        android:fromAlpha="1.0"
        android:toAlpha="0.0"
        android:duration="500" />

</set>

values-styles

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="PopupAnimation" parent="android:Animation" mce_bogus="1">
        <item name="android:windowEnterAnimation">@anim/popup_enter</item>
        <item name="android:windowExitAnimation">@anim/popup_exit</item>
    </style>


</resources>

item_btn.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical" >
    <Button
        android:id="@+id/btn"
        android:layout_width="70dp"
        android:singleLine="true"
        android:layout_height="wrap_content"
        android:text="删除"
        android:textColor="#ffffff"
        android:paddingLeft="15dp"
        android:paddingRight="15dp"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:layout_marginRight="15dp"
        />
</LinearLayout>

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

<com.example.threeapp.QQListView
    android:id="@+id/listView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    />
</RelativeLayout>

listView_popwindow.gif