android:background="@null","安xiaobai"让你的ListView插上翅膀,实现拨号,打电话,侧滑删除等功能...

大家好,我是"安xiaobai",我又来和大家分享我自己写的代码了。![图片描述][1]上一次的“处女秀”我介绍的是一个安卓的图片轮播,获得大量的浏览量,所以这次我又来了。如果你没看过,或者又想了解快点这里,点这里,点这里:

http://www.imooc.com/article/9647

这次的demo是通过一个自定义ListView,来实现侧滑删除,拨号,发短信等功能。

好了上正文。一共有七个文件,四个java文件,三个布局文件。

先上效果图:![图片描述][2]![图片描述][3]

第一个文件:

public class Telphone extends Activity implements MyInterface {

private ImageView tel_back;

private SlidingItemListView mListView;

private TellDAO tellDAO;

private List mDatas;

private SlidingItemListViewAdapter adapter;

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

requestWindowFeature(Window.FEATURE_NO_TITLE);

setContentView(R.layout.telphone);

initView();

}

/**

* 初始化的方法

*/

private void initView() {

tel_back = (ImageView) findViewById(R.id.tel_back);

tel_back.setOnClickListener(new OnClickListener() {

public void onClick(View v) {

startActivity(new Intent(Telphone.this,MainActivity.class));

finish();

}

});

//找到ListView控件

mListView = (SlidingItemListView) findViewById(R.id.listview);

//实例化一个 查询对象

tellDAO = new TellDAO(Telphone.this);

//查询所有数据

mDatas = tellDAO.getAllTel();

//将数据传递给 adapter

adapter = new SlidingItemListViewAdapter(Telphone.this, mDatas,

mListView.getRightViewWidth());

//将adapater 配置给 ListView

mListView.setAdapter(adapter);

//实现接口 对两个按钮进行监听

adapter.SetMyInterface(this);

//实现每一项的监听事件

mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {

public void onItemClick(AdapterView> parent, View view,

int position, long id) {

}

});

}

/**

* 实现接口 发送消息

*/

public void Onclick_ll_sendMesg_ll_right(View view, int position) {

Map map = (Map)mDatas.get(position);

Uri smsToUri = Uri.parse("smsto:"+map.get("number"));

Intent mIntent = new Intent( android.content.Intent.ACTION_SENDTO, smsToUri );

// mIntent.putExtra("sms_body", "sss"); 这个是预定短信内容

startActivity( mIntent );

}

/**

* 实现接口 拨打电话

*/

public void Onclick_ll_tellCall_ll_right(View view, int position) {

Map map = (Map)mDatas.get(position);

Intent intent = new Intent(Intent.ACTION_DIAL);

intent.setData(Uri.parse("tel:"+map.get("number")));

startActivity(intent);

}

}

这里面有两个方法是实现自定义接口的,通过这两个方法来调用系统的拨号界面,和短信界面。其他的在代码里面有详细的解释。

第二个文件:

public class TellDAO extends Activity{

private Context context;

public TellDAO(Context context){

this.context = context;

}

public List getAllTel(){

List tell = new ArrayList();

try {

Cursor cursor = context.getContentResolver().query(

ContactsContract.CommonDataKinds.Phone.CONTENT_URI,

null, null, null, null);

if (cursor ==null) {

System.out.println("这里为空");

return null;

}

while (cursor.moveToNext()) {

Map map = new HashMap();

map.put("num", cursor.getString(cursor.getColumnIndex(

ContactsContract.CommonDataKinds.Phone.CONTACT_ID)));

map.put("name",cursor.getString(cursor.getColumnIndex(

ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)));

map.put("number", cursor.getString(cursor.getColumnIndex(

ContactsContract.CommonDataKinds.Phone.NUMBER)));

tell.add(map);

}

} catch (Exception e) {e.printStackTrace();}

return tell;

}

}

这是查询系统中通讯录的电话号码。将查询出来的数据保存到map里面在讲map返回给调用者。

第三个文件:

public class SlidingItemListView extends ListView {

private View mPreItemView;

private View mCurrentItemView;

//用户第一点击下去的 X Y的值

private float mFirstX;

private float mFirstY;

private int mRightViewWidth;

private boolean mIsShown;

private Boolean mIsHorizontal;

/**

* 在构造方法里获取自定义的宽度(右边局部隐藏的宽度)

* @param context 上下文

* @param attrs

*/

public SlidingItemListView(Context context, AttributeSet attrs) {

super(context, attrs);

TypedArray typedArray = context.obtainStyledAttributes(attrs,

R.styleable.slidingitemlistview);

mRightViewWidth = (int) typedArray.getDimension(

R.styleable.slidingitemlistview_right_width, 200);

typedArray.recycle();

}

/**

* 重写onInterceptTouchEvent()

* ACTION_DOWN里获取 mCurrentItemView,mPreItemView,mFirstX,mFirstY

*/

public boolean onInterceptTouchEvent(MotionEvent ev) {

float lastX = ev.getX();

float lastY = ev.getY();

switch (ev.getAction()) {

case MotionEvent.ACTION_DOWN:

mIsHorizontal = null;

mFirstX = lastX;

mFirstY = lastY;

int position = pointToPosition((int) mFirstX, (int) mFirstY);

if (position >= 0) {

View view = getChildAt(position - getFirstVisiblePosition());

mPreItemView = mCurrentItemView;

mCurrentItemView = view;

}

break;

case MotionEvent.ACTION_MOVE:

break;

case MotionEvent.ACTION_UP:

//点击隐藏布局会执行MotionEvent.ACTION_UP

if (mIsShown) {

hideRightView(mCurrentItemView);

}

break;

}

return super.onInterceptTouchEvent(ev);

}

/**

*重写onTouchEvent()方法

*/

public boolean onTouchEvent(MotionEvent ev) {

float lastX = ev.getX();

float lastY = ev.getY();

switch (ev.getAction()) {

case MotionEvent.ACTION_DOWN:

break;

case MotionEvent.ACTION_MOVE:

float dx = lastX - mFirstX;

float dy = lastY - mFirstY;

if (mIsHorizontal == null) {

if (!judgeScrollDirection(dx, dy)) {

// 没判断出方向 ,没有滑动的话就直接退出

break;

}

}

//如果滑动了

if (mIsHorizontal) {

if (mIsShown && mPreItemView != mCurrentItemView) {

//正在展示,前视图不等于后视图

//则隐藏前视图

hideRightView(mPreItemView);

}

// 在mPreItemView!= mCurrentItemView执行 显示隐藏的宽度

if (dx < 0 && dx > - mRightViewWidth) {

mCurrentItemView.scrollTo((int) (-dx), 0);

}

} else {

if (mIsShown) {

//竖直方向滚动 则隐藏前视图

hideRightView(mPreItemView);

}

}

break;

case MotionEvent.ACTION_UP:

if (mIsShown) {

//点击时如果有在显示的View则隐藏前视图

hideRightView(mPreItemView);

}

if (mIsHorizontal != null && mIsHorizontal) {

if (mFirstX - lastX > mRightViewWidth / 2) {

showRight(mCurrentItemView);

} else {

// 不到一半则隐藏

hideRightView(mCurrentItemView);

}

return true;

}

break;

}

return super.onTouchEvent(ev);

}

/**

* 展示隐藏的布局

* @param mCurrentItemView2

*/

private void showRight(View mCurrentItemView2) {

mCurrentItemView2.scrollTo(mRightViewWidth, 0);

mIsShown = true;

}

/**

* 隐藏布局

*/

private void hideRightView(View mCurrentItemView2) {

mCurrentItemView2.scrollTo(0, 0);

mIsShown = false;

}

/**

* @param 水平距离差

* @param 竖直距离差

* @return 水平滑动或者竖直滑动都返回true 没有判断出滑动方向则返回false

*/

private boolean judgeScrollDirection(float dx, float dy) {

if (Math.abs(dx) > 30 && Math.abs(dx) > Math.abs(dy) * 2) {

mIsHorizontal = true;

return true;

}

if (Math.abs(dy) > 30 && Math.abs(dy) > Math.abs(dx) * 2) {

mIsHorizontal = false;

return true;

}

return false;

}

/**

* 后面实例化adapter的时候要用

* 获得右边 的宽度

* @return

*/

public int getRightViewWidth() {

return mRightViewWidth;

}

/**

* 设置 右边的宽度

* @param mRightViewWidth

*/

public void setRightViewWidth(int mRightViewWidth) {

this.mRightViewWidth = mRightViewWidth;

}

}

这个文件是自定义ListView文件,是实现滑动效果的关键。

第四文件:

public class SlidingItemListViewAdapter extends BaseAdapter {

//上下文

private Context mContext;

//布局文件

private LayoutInflater mInflater;

//ListView列表

private List list;

//右边的宽度

private int mRightViewWidth;

/**

* 构造方法 初始化一些数据

* @param mContext 上下文

* @param list 列表

* @param mRightViewWidth 右边的宽度

*/

public SlidingItemListViewAdapter(Context mContext,

List list, int mRightViewWidth) {

super();

this.mContext = mContext;

this.list = list;

this.mRightViewWidth = mRightViewWidth;

mInflater = LayoutInflater.from(mContext);

}

//获得数据条目

public int getCount() {

return list.size();

}

//获得List中的每一个Item

public Object getItem(int position) {

return list.get(position);

}

//获得itemId

public long getItemId(int position) {

return position;

}

/**

* 获得view控件

*/

public View getView(int position, View convertView, ViewGroup parent) {

ViewHolder viewHolder;

onClick listener;

if (convertView == null) {

//将ListView中每一个Item的布局文件加载进来

convertView = mInflater.inflate(R.layout.item_sliding_listview,null);

//实例化

viewHolder = new ViewHolder();

listener = new onClick();

viewHolder.Re_left = (RelativeLayout) convertView.findViewById(R.id.Re_left);

viewHolder.ll_right = (LinearLayout) convertView.findViewById(R.id.ll_right);

//找到 ListView中每一个Iten布局文件中的每一个控件

viewHolder.num = (TextView) convertView.findViewById(R.id.tv_num_Re_left);

viewHolder.name = (TextView) convertView.findViewById(R.id.tv_name_Re_left);

viewHolder.number = (TextView) convertView.findViewById(R.id.tv_path_Re_left);

viewHolder.tell = (ImageView) convertView.findViewById(R.id.img_tell_Re_left);

//找到 删除按钮 和 发送短信按钮

viewHolder.ll_delete = (LinearLayout) convertView.findViewById(R.id.ll_delete_ll_right);

viewHolder.ll_sendMessgae = (LinearLayout) convertView.findViewById(R.id.ll_sendMessge_ll_right);

//给三个个按钮设置监听事件

viewHolder.ll_delete.setOnClickListener(listener);

viewHolder.ll_sendMessgae.setOnClickListener(listener);

viewHolder.tell.setOnClickListener(listener);

//设置tag标记

convertView.setTag(viewHolder.tell.getId(),listener);

convertView.setTag(viewHolder);

} else {

viewHolder = (ViewHolder) convertView.getTag();

// 获取实例

listener = (onClick) convertView.getTag(viewHolder.tell.getId());

}

// 传递position

listener.setPosition(position);

// 设置布局参数

LayoutParams lp_left = new LayoutParams(

android.widget.LinearLayout.LayoutParams.MATCH_PARENT,

android.widget.LinearLayout.LayoutParams.MATCH_PARENT);

//将布局参数 设置给控件

viewHolder.Re_left.setLayoutParams(lp_left);

// 设置布局参数

LayoutParams lp_right = new LayoutParams(mRightViewWidth,

android.widget.LinearLayout.LayoutParams.MATCH_PARENT);

//将布局参数 设置给控件

viewHolder.ll_right.setLayoutParams(lp_right);

Map map = (Map)list.get(position);

viewHolder.num.setText(map.get("num").toString());

viewHolder.name.setText(map.get("name").toString());

viewHolder.number.setText(map.get("number").toString());

return convertView;

}

/**

* 内部类 复用监听事件

* @author First.One

*/

class onClick implements OnClickListener {

int position;

public void setPosition(int position) {

this.position = position;

}

//重写的方法

public void onClick(View v) {

switch (v.getId()) {

case R.id.img_tell_Re_left:

if (myInterface != null) {

myInterface.Onclick_ll_tellCall_ll_right(v,position);

}else {

Toast.makeText(mContext, "程序异常,请稍后再试。",2000).show();

}

break;

//删除

case R.id.ll_delete_ll_right:

list.remove(position);

SlidingItemListViewAdapter.this.notifyDataSetChanged();

break;

case R.id.ll_sendMessge_ll_right:

if (myInterface != null) {

myInterface.Onclick_ll_sendMesg_ll_right(v,position);

}else {

Toast.makeText(mContext, "这里是发送短信",

Toast.LENGTH_SHORT).show();

}

break;

}

}

}

MyInterface myInterface;

/**

* 自己定义置顶的MySetTopInterface接口

* @author First.One

* 传递两个参数,一个是被点击的View,另一个是position。

*/

public interface MyInterface {

void Onclick_ll_sendMesg_ll_right(View view,int position);

void Onclick_ll_tellCall_ll_right(View view,int position);

}

public void SetMyInterface(MyInterface myInterface) {

this.myInterface = myInterface;

}

/**

* 内部类 复用item控件里面的view控件

* @author First.One

*/

static class ViewHolder {

//左边的布局文件控件

RelativeLayout Re_left;

//右边滑动的控件

LinearLayout ll_right;

//删除按钮 发送短信 按钮

LinearLayout ll_delete;

LinearLayout ll_sendMessgae;

//编号、姓名、电话

TextView num;

TextView name;

TextView number;

//拨打电话 的图标

ImageView tell;

}

}

这个文件是自定义Adapter里面重点的是那两个内部类,实现了监听事件和View控件的重复使用。

第五个文件:

xmlns:dyk="http://schemas.android.com/apk/res/com.example.ashixi"

android:id="@+id/listview"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:background="@drawable/bg"

android:cacheColorHint="#00000000"

android:divider="#dddbdb"

android:dividerHeight="1dp"

android:layout_below="@id/include_id"

dyk:right_width="120dp" />

这就是一个简单的布局文件,相信你能看懂。

第六个文件:

```。

这个文件是控制右便滑动的宽度。在自定义ListView中的构造方法会调用它。

最后一个文件 :

android:id="@+id/Re_left"

android:layout_width="match_parent"

android:layout_height="match_parent">

android:id="@+id/tv_num_Re_left"

android:layout_width="20dp"

android:layout_height="20dp"

android:layout_centerVertical="true"

android:layout_marginLeft="10dp"

android:layout_marginRight="10dp"

android:gravity="center"

android:textColor="#fff"

android:textSize="13sp" />

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_centerVertical="true"

android:layout_toRightOf="@id/tv_num_Re_left" >

android:id="@+id/tv_name_Re_left"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_marginBottom="5dp"

android:textSize="19sp"

android:textColor="#fff"/>

android:id="@+id/tv_path_Re_left"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_below="@id/tv_name_Re_left"

android:textColor="#fff"

android:textSize="15sp" />

android:id="@+id/img_tell_Re_left"

android:layout_width="30dp"

android:layout_height="30dp"

android:layout_alignParentRight="true"

android:layout_centerVertical="true"

android:layout_marginRight="10dp"

android:scaleType="fitXY"

android:class="lazyload" src="https://img-blog.csdnimg.cn/2022010620524225770.png" data-original="@drawable/tel" />

android:id="@+id/ll_right"

android:layout_width="wrap_content"

android:layout_height="match_parent"

android:orientation="horizontal" >

android:id="@+id/ll_delete_ll_right"

android:layout_width="0dp"

android:layout_height="match_parent"

android:layout_weight="1"

android:background="#F77D48"

android:gravity="center"

android:orientation="vertical"

android:padding="5dp" >

android:layout_width="30dp"

android:layout_height="30dp"

android:scaleType="fitXY"

android:class="lazyload" src="https://img-blog.csdnimg.cn/2022010620524225770.png" data-original="@drawable/del_icon_normal" />

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="删除"

android:textColor="#fff"

android:textSize="16sp" />

android:id="@+id/ll_sendMessge_ll_right"

android:layout_width="0dp"

android:layout_height="match_parent"

android:layout_weight="1"

android:background="#FED33F"

android:gravity="center"

android:orientation="vertical"

android:padding="5dp" >

android:layout_width="30dp"

android:layout_height="30dp"

android:scaleType="fitXY"

android:class="lazyload" src="https://img-blog.csdnimg.cn/2022010620524225770.png" data-original="@drawable/msg" />

android:id="@+id/tv_sendMes"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="短信"

android:textColor="#fff"

android:textSize="12sp" />

这个是LiseView控件中每一个Item的布局文件,也不难。

![图片描述][4]

终于写完了.................心好累。如果你真心想学习这个demo的同学,”俺“保证我这个栗子绝对是最详细的了,没有之一...........好吧!!!!我还是要谦虚点。

![图片描述][5]

注意:

上面的文件我全部没有引入包,,所以要复制的同学小心哦!!!

上面的文件我全部没有引入包,,所以要复制的同学小心哦!!!

上面的文件我全部没有引入包,,所以要复制的同学小心哦!!!

![图片描述][6]

各位同学,"安xiaobai"我写一个文章也不容易,代码敲了半天,然后又敲了半天的字,如果你觉得文章还可以的话,就点一个推荐呗,,谢谢了。

严重申明:本文的图片全部来源于网络,如有侵权,请及时联系本人删除。

[1]: http://img1.sycdn.imooc.com/57751692000109b603160194.jpg

[2]: http://img1.sycdn.imooc.com/5775246b00017bb910801920.jpg

[3]: http://img1.sycdn.imooc.com/5775247c0001fde310801920.jpg

[4]: http://img1.sycdn.imooc.com/57751d720001108e02880240.gif

[5]: http://img1.sycdn.imooc.com/57751dfc00011cc402110240.jpg

[6]: http://img1.sycdn.imooc.com/57751ee70001e66003830240.gif

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值