Android高级控件(六)——自定义ListView高仿一个QQ可拖拽列表的实现


我们做一些好友列表或者商品列表的时候,居多的需求可能就是需要列表拖拽了,而我们选择了ListView,也是因为使用ListView太久远了,导致对他已经有浓厚的感情了,我们之前也是写过几篇关于ListView的博文

而今天我们就来实现以下课拖拽的方案,大家可以借鉴以下

我们大致的思路,其实是这样子的,也是我的设想,我们可以先去实现一个简单的ListView的数据,但是他的Adapter,我们可以用系统封装好的,然后传递进去一个实体类,最后自定义一个listview去操作,所以我们先把准备的工作做好,比如?

list_item.xml

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

    <ImageView
        android:id="@+id/iv_logo"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_alignParentLeft="true"
        android:layout_centerInParent="true"
        android:layout_marginLeft="10dp"/>

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:layout_marginLeft="10dp"
        android:layout_toRightOf="@id/iv_logo"/>

</RelativeLayout>

这就只有一个头像和一句话了,然后我们把实体类也给写完了

DragBean

package com.liuguilin.draglistviewsample.entity;

/*
 *  项目名:  DragListViewSample
 *  包名:    com.liuguilin.draglistviewsample.entity
 *  文件名:   DragBean
 *  创建者:   LGL
 *  创建时间:  2016/8/29 22:49
 *  描述:    实体类
 */

public class DragBean {

    private int ivId;
    private String text;

    public DragBean() {

    }

    public DragBean(int ivId, String text) {
        this.ivId = ivId;
        this.text = text;
    }

    public int getIvId() {
        return ivId;
    }

    public String getText() {
        return text;
    }

}

ok,其实很简单,id是图片,然后是文本,这样我们就可以来实现一个Adapter了,这里我用的是ArrayAdapter这样能让我们插入和删除很轻松

DragAdapter

package com.liuguilin.draglistviewsample.adapter;

/*
 *  项目名:  DragListViewSample
 *  包名:    com.liuguilin.draglistviewsample.adapter
 *  文件名:   DragAdapter
 *  创建者:   LGL
 *  创建时间:  2016/8/29 22:41
 *  描述:    拖拽列表的数据源
 */

import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import com.liuguilin.draglistviewsample.R;
import com.liuguilin.draglistviewsample.entity.DragBean;

import java.util.List;

public class DragAdapter extends ArrayAdapter<DragBean> {

    /**
     * 构造方法
     *
     * @param context
     * @param mList
     */
    public DragAdapter(Context context, List<DragBean> mList) {
        super(context, 0, mList);
    }

    /**
     * 实现View
     *
     * @param position
     * @param convertView
     * @param parent
     * @return
     */
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View view;
        ViewHolder viewHolder;
        if (convertView == null) {
            view = View.inflate(getContext(), R.layout.list_item, null);
            viewHolder = new ViewHolder();
            viewHolder.imageView = (ImageView) view
                    .findViewById(R.id.iv_logo);
            viewHolder.textView = (TextView) view.findViewById(R.id.textView);
            view.setTag(viewHolder);
        } else {
            view = convertView;
            viewHolder = (ViewHolder) view.getTag();
        }

        viewHolder.imageView.setImageResource(getItem(position).getIvId());
        viewHolder.textView.setText(getItem(position).getText());
        return view;
    }

    /**
     * 缓存
     */
    static class ViewHolder {
        ImageView imageView;
        TextView textView;
    }

}

好的,其实到这里,他就是一个最普通的ListView了,我们给他填充点数据

MainActivity

package com.liuguilin.draglistviewsample;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import com.liuguilin.draglistviewsample.adapter.DragAdapter;
import com.liuguilin.draglistviewsample.entity.DragBean;
import com.liuguilin.draglistviewsample.view.DragListView;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    //列表
    private DragListView mListView;
    //数据
    private List<DragBean> mList = new ArrayList<>();
    //数据源
    private DragAdapter adapter;

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

        initView();
    }

    /**
     * 初始化View
     */
    private void initView() {
        mListView = (DragListView) findViewById(R.id.mListView);

        //新增數據
        for (int i = 0; i < 30; i++) {
            DragBean bean = new DragBean(R.mipmap.ic_launcher, "刘某人程序员" + i);
            mList.add(bean);
        }
        //初始化数据源
        adapter = new DragAdapter(this,mList);
        mListView.setAdapter(adapter);
    }
}

现在可以看看实际的效果了

现在我们可以重写我们的ListView了

我们首先拦截他的事件

 /**
     * 获取触点所在条目的位置
     * 获取选中条目的图片
     * 事件的拦截机制
     *
     * @param ev
     * @return
     */
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        //识别动作
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                //获取触点的坐标
                int x = (int) ev.getX();
                int y = (int) ev.getY();
                //这样就可以计算我按到哪个条目上了
                mStartPosition = mEndPosition = pointToPosition(x, y);
                //判断触点是否在logo的区域
                ViewGroup itemView = (ViewGroup) getChildAt(mStartPosition - getFirstVisiblePosition());
                //记录手指在条目中的相对Y坐标
                dragPoint = y - itemView.getTop();
                //ListView在屏幕中的Y坐标
                dragOffset = (int) (ev.getRawY() - y);
                //拖动的图标
                View dragger = itemView.findViewById(R.id.iv_logo);
                //判断触点是否在logo区域
                if (dragger != null && x < dragger.getRight() + 10) {
                    //定义ListView的滚动条目
                    //上
                    upScroll = getHeight() / 3;
                    //下
                    downScroll = getHeight() * 2 / 3;
                    //获取选中的图片/截图
                    itemView.setDrawingCacheEnabled(true);
                    //获取截图
                    Bitmap bitMap = itemView.getDrawingCache();
                    //图片滚动
                    startDrag(bitMap, y);
                }
                break;
        }
        //还会传递事件到子View
        return false;
    }

获取到他的position之后我们直接截图,并且显示我们的window,这里做的事情就比较多了我们还要判断是否点击的是头像才去显示window

 /**
     * 图片在Y轴,也就是上下可滚动
     *
     * @param bitMap
     * @param y
     */
    private void startDrag(Bitmap bitMap, int y) {
        //窗体仿照
        wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
        //设置窗体参数
        lParams = new WindowManager.LayoutParams();
        //设置宽高
        lParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
        lParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
        //属性
        lParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
                | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
        //设置半透明
        lParams.alpha = 0.8f;
        //设置居中
        lParams.gravity = Gravity.TOP;
        //设置xy
        lParams.x = 0;
        lParams.y = y-dragPoint + dragOffset;
        //属性
        lParams.format = PixelFormat.TRANSLUCENT;
        //设置动画
        lParams.windowAnimations = 0;
        //图片
        dragImageView = new ImageView(getContext());
        //设置截图
        dragImageView.setImageBitmap(bitMap);
        //添加显示窗体
        wm.addView(dragImageView, lParams);
    }

好的,我们初始化一下window,光显示还不行呢,我们还要可以滑动,怎么监听?onTouchEvent的ACTION_MOVE事件是可以做到的


    /**
     * 触摸事件
     *
     * @param ev
     * @return
     */
    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        //错误的位置
        if (dragImageView != null && mEndPosition != INVALID_POSITION) {
            //在滑动事件中控制上下滑动
            switch (ev.getAction()) {
                case MotionEvent.ACTION_MOVE:
                    //直接获取到Y坐标进行移动
                    int moveY = (int) ev.getY();
                    doDrag(moveY);
                    break;
                //停止拖动成像
                case MotionEvent.ACTION_UP:
                    int upY = (int) ev.getY();
                    stopDrag();
                    onDrag(upY);
                    break;
            }
        }
        //拦截到事件
        return true;
    }

我们在移动的时候不断的去更新他的位置

    /**
     * 控制窗体移动
     *
     * @param moveY
     */
    private void doDrag(int moveY) {
        if (dragImageView != null) {
            lParams.y = moveY - dragPoint + dragOffset;
            wm.updateViewLayout(dragImageView, lParams);
        }
        //判断移动到分割线 返回-1
        int tempLine = pointToPosition(0, moveY);
        //我们处理他
        if (tempLine != INVALID_POSITION) {
            //只要你不移动到分割线 我才处理
            mEndPosition = tempLine;
        }

        //拖拽时滚动、滚动速度
        int scrollSpeed = 0;
        //上滚
        if (moveY < upScroll) {
            scrollSpeed = 10;
            //下滚
        } else if (moveY > downScroll) {
            scrollSpeed = -10;
        }
        //开始滚动
        if (scrollSpeed != 0) {
            //计算条目的Y坐标
            int dragItemY = getChildAt(mEndPosition - getFirstVisiblePosition()).getTop();
            //当前速度
            int dy = dragItemY + scrollSpeed;
            //设置
            setSelectionFromTop(mEndPosition, dy);
        }
    }

当你移动完成之后,我就可以停止你的window体了

     /**
     * 停止的位置
     */
    private void stopDrag() {
        //直接移除窗体
        if (dragImageView != null) {
            wm.removeView(dragImageView);
            dragImageView = null;
        }

    }

这样,我就直接拼接你的position达到一个拖拽的效果


    /**
     * 最终开始成像
     *
     * @param upY
     */
    private void onDrag(int upY) {
        //分割线的处理
        //判断移动到分割线 返回-1
        int tempLine = pointToPosition(0, upY);
        //我们处理他
        if (tempLine != INVALID_POSITION) {
            //只要你不移动到分割线 我才处理
            mEndPosition = tempLine;
        }

        /**
         * 你在最上方就直接落在第一个最下方就直接最下面一个
         */

        //上边界处理
        if (upY < getChildAt(1).getTop()) {
            mEndPosition = 1;
            //下边界处理
        } else if (upY > getChildAt(getChildCount() - 1).getTop()) {
            mEndPosition = getAdapter().getCount() - 1;
        }

        //开始更新item顺序
        if (mEndPosition > 0 && mEndPosition < getAdapter().getCount()) {
            DragAdapter adapter = (DragAdapter) getAdapter();
            //删除原来的条目
            adapter.remove(adapter.getItem(mStartPosition));
            //更新
            adapter.insert(adapter.getItem(mStartPosition), mEndPosition);
        }
    }

全部代码贴上

DragListView

package com.liuguilin.draglistviewsample.view;

/*
 *  项目名:  DragListViewSample
 *  包名:    com.liuguilin.draglistviewsample.view
 *  文件名:   DragListView
 *  创建者:   LGL
 *  创建时间:  2016/8/29 20:50
 *  描述:    自定义高仿QQ列表可拖拽的ListView
 */

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.PixelFormat;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.ListView;

import com.liuguilin.draglistviewsample.R;
import com.liuguilin.draglistviewsample.adapter.DragAdapter;

public class DragListView extends ListView {

    //按下选中的position
    private int mStartPosition;
    //需要达到的position
    private int mEndPosition;
    //手指在条目中的相对Y坐标
    private int dragPoint;
    //ListView在屏幕中的Y坐标
    private int dragOffset;
    //上
    private int upScroll;
    //下
    private int downScroll;
    //窗体
    private WindowManager wm;
    //显示的截图
    private ImageView dragImageView;
    //窗体参数
    private WindowManager.LayoutParams lParams;

    //构造方法
    public DragListView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    /**
     * 获取触点所在条目的位置
     * 获取选中条目的图片
     * 事件的拦截机制
     *
     * @param ev
     * @return
     */
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        //识别动作
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                //获取触点的坐标
                int x = (int) ev.getX();
                int y = (int) ev.getY();
                //这样就可以计算我按到哪个条目上了
                mStartPosition = mEndPosition = pointToPosition(x, y);
                //判断触点是否在logo的区域
                ViewGroup itemView = (ViewGroup) getChildAt(mStartPosition - getFirstVisiblePosition());
                //记录手指在条目中的相对Y坐标
                dragPoint = y - itemView.getTop();
                //ListView在屏幕中的Y坐标
                dragOffset = (int) (ev.getRawY() - y);
                //拖动的图标
                View dragger = itemView.findViewById(R.id.iv_logo);
                //判断触点是否在logo区域
                if (dragger != null && x < dragger.getRight() + 10) {
                    //定义ListView的滚动条目
                    //上
                    upScroll = getHeight() / 3;
                    //下
                    downScroll = getHeight() * 2 / 3;
                    //获取选中的图片/截图
                    itemView.setDrawingCacheEnabled(true);
                    //获取截图
                    Bitmap bitMap = itemView.getDrawingCache();
                    //图片滚动
                    startDrag(bitMap, y);
                }
                break;
        }
        //还会传递事件到子View
        return false;
    }

    /**
     * 图片在Y轴,也就是上下可滚动
     *
     * @param bitMap
     * @param y
     */
    private void startDrag(Bitmap bitMap, int y) {
        //窗体仿照
        wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
        //设置窗体参数
        lParams = new WindowManager.LayoutParams();
        //设置宽高
        lParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
        lParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
        //属性
        lParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
                | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
        //设置半透明
        lParams.alpha = 0.8f;
        //设置居中
        lParams.gravity = Gravity.TOP;
        //设置xy
        lParams.x = 0;
        lParams.y = y-dragPoint + dragOffset;
        //属性
        lParams.format = PixelFormat.TRANSLUCENT;
        //设置动画
        lParams.windowAnimations = 0;
        //图片
        dragImageView = new ImageView(getContext());
        //设置截图
        dragImageView.setImageBitmap(bitMap);
        //添加显示窗体
        wm.addView(dragImageView, lParams);
    }

    /**
     * 触摸事件
     *
     * @param ev
     * @return
     */
    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        //错误的位置
        if (dragImageView != null && mEndPosition != INVALID_POSITION) {
            //在滑动事件中控制上下滑动
            switch (ev.getAction()) {
                case MotionEvent.ACTION_MOVE:
                    //直接获取到Y坐标进行移动
                    int moveY = (int) ev.getY();
                    doDrag(moveY);
                    break;
                //停止拖动成像
                case MotionEvent.ACTION_UP:
                    int upY = (int) ev.getY();
                    stopDrag();
                    onDrag(upY);
                    break;
            }
        }
        //拦截到事件
        return true;
    }

    /**
     * 最终开始成像
     *
     * @param upY
     */
    private void onDrag(int upY) {
        //分割线的处理
        //判断移动到分割线 返回-1
        int tempLine = pointToPosition(0, upY);
        //我们处理他
        if (tempLine != INVALID_POSITION) {
            //只要你不移动到分割线 我才处理
            mEndPosition = tempLine;
        }

        /**
         * 你在最上方就直接落在第一个最下方就直接最下面一个
         */

        //上边界处理
        if (upY < getChildAt(1).getTop()) {
            mEndPosition = 1;
            //下边界处理
        } else if (upY > getChildAt(getChildCount() - 1).getTop()) {
            mEndPosition = getAdapter().getCount() - 1;
        }

        //开始更新item顺序
        if (mEndPosition > 0 && mEndPosition < getAdapter().getCount()) {
            DragAdapter adapter = (DragAdapter) getAdapter();
            //删除原来的条目
            adapter.remove(adapter.getItem(mStartPosition));
            //更新
            adapter.insert(adapter.getItem(mStartPosition), mEndPosition);
        }
    }

    /**
     * 停止的位置
     */
    private void stopDrag() {
        //直接移除窗体
        if (dragImageView != null) {
            wm.removeView(dragImageView);
            dragImageView = null;
        }

    }

    /**
     * 控制窗体移动
     *
     * @param moveY
     */
    private void doDrag(int moveY) {
        if (dragImageView != null) {
            lParams.y = moveY - dragPoint + dragOffset;
            wm.updateViewLayout(dragImageView, lParams);
        }
        //判断移动到分割线 返回-1
        int tempLine = pointToPosition(0, moveY);
        //我们处理他
        if (tempLine != INVALID_POSITION) {
            //只要你不移动到分割线 我才处理
            mEndPosition = tempLine;
        }

        //拖拽时滚动、滚动速度
        int scrollSpeed = 0;
        //上滚
        if (moveY < upScroll) {
            scrollSpeed = 10;
            //下滚
        } else if (moveY > downScroll) {
            scrollSpeed = -10;
        }
        //开始滚动
        if (scrollSpeed != 0) {
            //计算条目的Y坐标
            int dragItemY = getChildAt(mEndPosition - getFirstVisiblePosition()).getTop();
            //当前速度
            int dy = dragItemY + scrollSpeed;
            //设置
            setSelectionFromTop(mEndPosition, dy);
        }
    }
}

然后我们引用

layout_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:orientation="vertical"
    android:layout_height="match_parent">

    <com.liuguilin.draglistviewsample.view.DragListView
        android:id="@+id/mListView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>

对了,别忘记了添加窗体的权限哦

 <!--窗口权限-->
 <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

做完这一系列事情之后,就觉得这个设想其实是对的,然后我们可以尝试性的运行一下

运行时成功的,说明我们的设想是没有问题的,但是随着而来的,也是诸多的bug,所以呢,这也只是思想的参考,不过这些bug我有时间野就修复一下,应该是可以的,好的,本篇博文就先到这里!

有兴趣的加群:555974449

DragListViewSample:http://download.csdn.net/detail/qq_26787115/9616355

Android高级控件(六)——自定义ListView高仿一个QQ可拖拽列表的实现的更多相关文章

  1. Android高级控件(五)——如何打造一个企业级应用对话列表,以QQ,微信为例

    Android高级控件(五)--如何打造一个企业级应用对话列表,以QQ,微信为例 看标题这么高大上,实际上,还是运用我么拿到listview去扩展,我们讲什么呢,就是研究一下QQ,微信的这种对话列表, ...

  2. Android高级控件(一)——ListView绑定CheckBox实现全选,增加和删除等功能

    Android高级控件(一)--ListView绑定CheckBox实现全选,增加和删除等功能 这个控件还是挺复杂的,也是项目中应该算是比较常用的了,所以写了一个小Demo来讲讲,主要是自定义adap ...

  3. Android高级控件(一)——ListView绑定CheckBox实现全选,添加和删除等功能

    Android高级控件(一)--ListView绑定CheckBox实现全选,添加和删除等功能 这个控件还是挺复杂的.也是项目中应该算是比較经常使用的了,所以写了一个小Demo来讲讲,主要是自己定义a ...

  4. Android高级控件--AdapterView与Adapter

    在J2EE中提供过一种非常好的框架--MVC框架,实现原理:数据模型M(Model)存放数据,利用控制器C(Controller)将数据显示在视图V(View)上.在Android中有这样一种高级控件 ...

  5. Android 高级控件(七)——RecyclerView的方方面面

    Android 高级控件(七)--RecyclerView的方方面面 RecyclerView出来很长时间了,相信大家都已经比较了解了,这里我把知识梳理一下,其实你把他看成一个升级版的ListView ...

  6. Android高级控件(二)——SurfaceView实现GIF动画架包,播放GIF动画,自己实现功能的初体现

    Android高级控件(二)--SurfaceView实现GIF动画架包,播放GIF动画,自己实现功能的初体现 写这个的原因呢,也是因为项目中用到了gif动画,虽然网上有很多的架包可以实现,不过我们还 ...

  7. Android高级控件(四)——VideoView 实现引导页播放视频欢迎效果,超级简单却十分的炫酷

    Android高级控件(四)--VideoView 实现引导页播放视频欢迎效果,超级简单却十分的炫酷 是不是感觉QQ空间什么的每次新版本更新那炫炫的引导页就特别的激动,哈哈,其实他实现起来真的很简单很 ...

  8. Android高级控件(三)—— 使用Google ZXing实现二维码的扫描和生成相关功能体系

    Android高级控件(三)-- 使用Google ZXing实现二维码的扫描和生成相关功能体系 摘要 现在的二维码可谓是烂大街了,到处都是二维码,什么都是二维码,扫一扫似乎已经流行到习以为常了,今天 ...

  9. Android高级控件(三)——&#160;使用Google ZXing实现二维码的扫描和生成相关功能体系

    Android高级控件(三)-- 使用Google ZXing实现二维码的扫描和生成相关功能体系 摘要 如今的二维码可谓是烂大街了.到处都是二维码.什么都是二维码,扫一扫似乎已经流行到习以为常了,今天 ...

随机推荐

  1. gift 分数规划的最大权闭合子图

    题目大意: N个物品,物品间有M组关系,每个物品有一个ai的代价,满足关系后会得到bi的值 求 max(sigma(bi)/sigma(ai)) 题解: 很明显的最大权闭合子图,只不过需要处理分数. ...

  2. hdu 5137(2014广州—最短路)

    题意:给你一个图,求删除一个点后使1->n的距离最大 思路: 枚举删除点,然后求最短路,取这些最短路的最大值 #include <iostream> #include <cst ...

  3. 【完整项目】使用Scrapy模拟HTTP POST,获取完美名字

    1. 背景 最近有人委托我给小孩起个名字,说名字最好符合周易五行生克理论,然后给了我个网址,说像是这个网站中的八字测名,输入名字和生辰八字等信息,会给出来这个名字的分数和对未来人生的预测.当父母的自然 ...

  4. 作为开发也要了解的 mysql 优化思路

    作为开发人员,数据库知识掌握的可能不是很深入,但是一些基本的技能还是要有时间学习一下的.作为一个数据库菜鸟,厚着脸皮来总结一下 mysql 的基本的不能再基本的优化方法. 为了更好的说明,我假想出来了 ...

  5. Windows系统提供什么样的接口,Unix、Linux系统的用户接口是什么?

    Windows:图形化用户界面 Unix.Linux:独立的环境.

  6. glusterfs 4.0.1 event模块 分析笔记1

    1. 前言 在C语言i中,存储变量的结构体加上一组函数指针,大概就可以算是一个对象模型了:如果将一组函数指针捆绑为结构体, 后期根据配置或者环境需要绑定到不同实现模块中的一组函数,可以认为是C语言面对 ...

  7. swift之属性

    知识点总结: 1.存储属性 struct Town{ let region = "South" //只读属性 var population = //读写属性 } 2.惰性存储属性 ...

  8. hasattr(),getattr(),setattr()的使用

    # 首先你有一个command.py文件,内容如下,这里我们假若它后面还有100个方法 class MyObject(object): def __init__(self): self.x = def ...

  9. 深入理解Oracle中的随机函数

    --Oracle中取随机值的函数 .dbms_random包 dbms_random包提供了一系列的随机值获取函数以及相关存储过程.下面详细讲解常用的函数和过程. ()dbms_random.rand ...

  10. js模拟form表单提交数据, js模拟a标签点击跳转,避开使用window.open引起来的浏览器阻止问题

    js模拟form表单提交数据, js模拟a标签点击跳转,避开使用window.open引起来的浏览器阻止问题 js模拟form表单提交数据源码: /** * js模拟form表单提交 * @param ...