Android 之自定义布局(继承控件)
2017-05-17 18:13
260 查看
就是继承已有的控件,创建新控件,保留继承的父控件的特性,并且还可以引入新特性。下面就以支持横向滑动删除列表项的自定义ListView的实现来介绍。
1、创建删除按钮布局delete_btn.xml,这个布局是在横向滑动列表项后显示的:
2、创建CustomListView类,继承自ListView,并实现了OnTouchListener和OnGestureListener接口:
以上代码实现le,自定义View。重点:在重写ListView 时,在类中进行复杂操作。比如点击事件,触摸事件,显示布局,更新布局。在此进行相关的操作~(布局的变化)然后可以写一些接口,可供使用的类调用!
1、创建删除按钮布局delete_btn.xml,这个布局是在横向滑动列表项后显示的:
<?xml version="1.0" encoding="utf-8"?> <Button xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#FF0000" android:padding="5dp" android:text="\u5220\u9664" android:textColor="#FFFFFF" android:textSize="16sp" > </Button>
2、创建CustomListView类,继承自ListView,并实现了OnTouchListener和OnGestureListener接口:
package cn.com.tcl.customlistview; import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.view.GestureDetector; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.widget.ListView; import android.widget.RelativeLayout; public class CustomListViewActivity extends ListView implements View.OnTouchListener, GestureDetector.OnGestureListener { private final GestureDetector mGestureDetector; private View mDeletBtn; private ViewGroup mItemLAyout; private int mSelecteditem,mlastSelecteditem; private boolean isDelectShown; private OnDeleteListener mOnDeleteListener; public interface OnDeleteListener { void onDelete(int index); } public CustomListViewActivity(Context context, AttributeSet attrs) { super(context, attrs); mGestureDetector = new GestureDetector(getContext(), this); setOnTouchListener(this); } public void setOnDeleteListener(OnDeleteListener listener) { mOnDeleteListener = listener; } @Override public boolean onTouch(View v, MotionEvent event) { if (isDelectShown) { Log.d("haha", "onTouch:---isDelectShown "); hideDelete(); return false; } else { return mGestureDetector.onTouchEvent(event); } } @Override public boolean onDown(MotionEvent e) { if(!isDelectShown){ mSelecteditem = pointToPosition((int) e.getX(),(int) e.getY()); mlastSelecteditem = mSelecteditem; Log.d("haha", "onDown: --->mSelecteditem:"+mSelecteditem); } return false; } @Override public void onShowPress(MotionEvent e) { Log.d("haha", "onShowPress: "); } @Override public boolean onSingleTapUp(MotionEvent e) { Log.d("haha", "onSingleTapUp: "); return false; } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { // Log.d("haha", "onScroll: "); return false; } @Override public void onLongPress(MotionEvent e) { Log.d("haha", "onLongPress: "); } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { mSelecteditem = pointToPosition((int) e2.getX(),(int) e2.getY()); Log.d("haha", "onFling: --->mSelecteditem:"+mSelecteditem); if(mlastSelecteditem != mSelecteditem && isDelectShown){ hideDelete(); } if (!isDelectShown && Math.abs(velocityX) > Math.abs(velocityY)) { mDeletBtn = LayoutInflater.from(getContext()).inflate(R.layout.delect_btn, null); mDeletBtn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mItemLAyout.removeView(mDeletBtn); mDeletBtn = null; isDelectShown = false; Log.d("haha", "onClick:--> delete"+mSelecteditem); mOnDeleteListener.onDelete(mSelecteditem); } }); mItemLAyout = (ViewGroup) getChildAt(mSelecteditem - getFirstVisiblePosition()); RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams( LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); params.addRule(RelativeLayout.CENTER_VERTICAL); mItemLAyout.addView(mDeletBtn, params); isDelectShown = true; } return false; } void hideDelete(){ mItemLAyout.removeView(mDeletBtn); mDeletBtn = null; isDelectShown = false; } public boolean isDelectShown() { return isDelectShown; } }3、定义列表项布局custom_listview_item.xml,它的结构很简单,只包含了一个TextView:
<?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" android:descendantFocusability="blocksDescendants" > <TextView android:id="@+id/content_tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_margin="30dp" android:gravity="center_vertical|left" /> </RelativeLayout> </LinearLayout>4、定义适配器类CustomListViewAdapter,继承自ArrayAdapter<String>:
public class CustomListViewAdapter extends ArrayAdapter<String> { public CustomListViewAdapter(Context context, int textViewResourceId, List<String> objects) { super(context, textViewResourceId, objects); } @Override public View getView(int position, View convertView, ViewGroup parent) { View view; if (convertView == null) { view = LayoutInflater.from(getContext()).inflate( R.layout.custom_listview_item, null); } else { view = convertView; } TextView contentTv = (TextView) view.findViewById(R.id.content_tv); contentTv.setText(getItem(position)); return view; } }5、在activity_main.xml中引入自定义的ListView:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/main_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <com.example.test.CustomListView android:id="@+id/custom_lv" android:layout_width="match_parent" android:layout_height="wrap_content" />6、在MainActivity中对列表做初始化、设置列表项删除按钮点击事件等处理
public class MainActivity extends Activity { // 自定义Lv private CustomListView mCustomLv; // 自定义适配器 private CustomListViewAdapter mAdapter; // 内容列表 private List<String> contentList = new ArrayList<String>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main); initContentList(); mCustomLv = (CustomListView) findViewById(R.id.custom_lv); mCustomLv.setOnDeleteListener(new OnDeleteListener() { @Override public void onDelete(int index) { contentList.remove(index); mAdapter.notifyDataSetChanged(); } }); mAdapter = new CustomListViewAdapter(this, 0, contentList); mCustomLv.setAdapter(mAdapter); } // 初始化内容列表 private void initContentList() { for (int i = 0; i < 20; i++) { contentList.add("内容项" + i); } } @Override public void onBackPressed() { if (mCustomLv.isDeleteShown()) { mCustomLv.hideDelete(); return; } super.onBackPressed(); } }
以上代码实现le,自定义View。重点:在重写ListView 时,在类中进行复杂操作。比如点击事件,触摸事件,显示布局,更新布局。在此进行相关的操作~(布局的变化)然后可以写一些接口,可供使用的类调用!
相关文章推荐
- 【Android】使用自定义Adapter优化ListView、修改数据及控件内部布局
- Android自定义控件之继承ViewGroup创建新容器
- Android利用添加自定义布局来搞定触摸事件的分发,解决组合界面中特定控件响应特定方向的事件
- Android获取dialog自定义布局中的控件
- Android 自定义ViewGroup布局控件,垂直滚动引导
- android自定义RadioGroup实现继承多种布局
- Android 手机卫士--自定义组合控件构件布局结构
- android控件使用---recycleview自定义上拉加载,和加载多个布局及加入动画
- android问题:布局文件控件自定义的ID错误
- 在Android中,可以自定义类,继承ViewGroup等容器类,以实现自己需要的布局显示。
- Android Jamendo开源在线音乐播放器源码分析九 ViewFlipper及自定义布局控件的分析
- Windows Phone 自定义布局控件,继承Panel
- Android自定义控件之继承ViewGroup创建新容器(四)
- Android自定义控件系列 十:利用添加自定义布局来搞定触摸事件的分发,解决组合界面中特定控件响应特定方向的事件
- Android自定义控件系列 十:利用添加自定义布局来搞定触摸事件的分发,解决组合界面中特定控件响应特定方向的事件
- Windows Phone 自定义布局控件,继承Panel
- Android开发之自定义布局和控件
- Android自定义控件系列 十:利用添加自定义布局来搞定触摸事件的分发,解决组合界面中特定控件响应特定方向的事件
- android 自定义布局继承一个系统的布局会报错
- Android Fragment 中自定义键盘如何调整布局,不挡住界面控件