惯例,先放效果图,DEMO在最后

想当年博主刚接触Android的时候,看到这个效果心中只有膜拜啊,如果慢慢的自己水平也上来了,就把当年的一个想法给圆满了吧。
好了,废话不多说,先总结总结这个效果:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
//宽度适配,改变ItemView的宽度
SlideItemView.Width = width;
for(int i = 0; i < getChildCount(); i++){
SlideItemView item = (SlideItemView) getChildAt(i);
item.resetWidth();
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
} @Override
public boolean onTouchEvent(MotionEvent ev) {
float dx = 0;
float dy = 0;
switch (ev.getAction()){
case MotionEvent.ACTION_DOWN:
mTouchX = ev.getX();
mTouchY = ev.getY();
mMoveX = ev.getX();
mMoveY = ev.getY();
mTouchPosition = pointToPosition((int)ev.getX(), (int)ev.getY());
break;
case MotionEvent.ACTION_MOVE:
dx = ev.getX() - mMoveX;
dy = ev.getY() - mMoveY;
if(Math.abs(dx) > Math.abs(dy)){
//根据坐标点得到索引值
int position = pointToPosition((int)ev.getX(), (int)ev.getY());
if(mTouchPosition != ListView.INVALID_POSITION && position == mTouchPosition){
//得到内存中真实的Item
SlideItemView itemView = (SlideItemView) getChildAt(position - getFirstVisiblePosition());
itemView.scroll((int) dx);
}
}
mMoveX = ev.getX();
mMoveY = ev.getY();
break;
case MotionEvent.ACTION_UP:
dx = ev.getX() - mTouchX;
dy = ev.getY() - mTouchY;
if(Math.abs(dx) > Math.abs(dy) && Math.abs(dx) >= mTouchSlop){
int position = pointToPosition((int)ev.getX(), (int)ev.getY());
if(mTouchPosition != ListView.INVALID_POSITION && position == mTouchPosition){
//得到真正在内存中的Item
SlideItemView itemView = (SlideItemView) getChildAt(position - getFirstVisiblePosition());
//根据当前scrollX以及dx判断是否显示正文内容
if (itemView.shouldShowContent((int) dx)){
itemView.showContent();
}else{
itemView.showMenu();
}
}else if(position != mTouchPosition){
SlideItemView itemView = (SlideItemView) getChildAt(mTouchPosition - getFirstVisiblePosition());
//根据当前scrollX以及dx判断是否显示正文内容
if (itemView.shouldShowContent((int) dx)){
itemView.showContent();
}else{
itemView.showMenu();
}
}
}else{
SlideItemView itemView = (SlideItemView) getChildAt(mTouchPosition - getFirstVisiblePosition());
//根据当前scrollX以及dx判断是否显示正文内容
if (itemView.shouldShowContent((int) dx)){
itemView.showContent();
}else{
itemView.showMenu();
}
}
break;
case MotionEvent.ACTION_CANCEL:
if(mTouchPosition != ListView.INVALID_POSITION){
SlideItemView itemView = (SlideItemView) getChildAt(mTouchPosition - getFirstVisiblePosition());
itemView.showContent();
}
break;
}
return super.onTouchEvent(ev);
}public void setView(SlideListView listView, int contentId, int menuId, float menuScale){
this.listView = listView;
this.content = View.inflate(getContext(), contentId, null);
this.menu = View.inflate(getContext(), menuId, null);
this.scale = menuScale;
LayoutParams param1 = new LayoutParams(Width, LayoutParams.MATCH_PARENT);
addView(content, param1);
LayoutParams param2 = new LayoutParams((int) (Width * menuScale), LayoutParams.MATCH_PARENT);
addView(menu, param2);
}
public View getContent(){
return content;
}
public View getMenu(){
return menu;
} public void showContent(){
mScroller.startScroll(mScroller.getFinalX(), mScroller.getFinalY(), -mScroller.getFinalX(), 0);
invalidate();
}
public void showMenu(){
mScroller.startScroll(mScroller.getFinalX(), mScroller.getFinalY(), menu.getWidth() - mScroller.getFinalX(), 0);
invalidate();
}
public boolean shouldShowContent(int dx){
//初始化
if(menu.getWidth() == 0){
resetWidth();
}
if(dx > 0){
//右滑,当滑过1/4的时候开始变化
if(mScroller.getFinalX() < menu.getWidth() * 3 / 4){
return true;
}else{
return false;
}
}else{
//左滑,当滑过1/4的时候开始变化
if(mScroller.getFinalX() < menu.getWidth() / 4){
return true;
}else{
return false;
}
}
}public void scroll(int dx){
if(dx > 0){
//右滑
if(mScroller.getFinalX() > 0){
if(dx > mScroller.getFinalX()){
mScroller.startScroll(mScroller.getFinalX(), mScroller.getFinalY(), -mScroller.getFinalX(), 0);
}else{
mScroller.startScroll(mScroller.getFinalX(), mScroller.getFinalY(), -dx, 0);
}
}else{
mScroller.setFinalX(0);
}
invalidate();
}else{
//左滑
if(mScroller.getFinalX() < menu.getWidth()){
if(mScroller.getFinalX() - dx > menu.getWidth()){
mScroller.startScroll(mScroller.getFinalX(), mScroller.getFinalY(), menu.getWidth()- mScroller.getFinalX(), 0);
}else{
mScroller.startScroll(mScroller.getFinalX(), mScroller.getFinalY(), -dx, 0);
}
}else{
mScroller.setFinalX(menu.getWidth());
}
invalidate();
}
} /**
* 重设宽度,在ListView的onMeasure方法中调用。
* 此方法是为了动态适配ListView的宽度,因为ListView的layout_width不一定等于MATCH_PARENT
* 也可能是定值比如300dp
*/
public void resetWidth(){
ViewGroup.LayoutParams param1 = content.getLayoutParams();
if(param1 == null){
param1 = new LayoutParams(Width, LayoutParams.MATCH_PARENT);
}else{
param1.width = Width;
}
content.setLayoutParams(param1);
ViewGroup.LayoutParams param2 = menu.getLayoutParams();
if(param2 == null){
param2 = new LayoutParams((int) (Width * scale), LayoutParams.MATCH_PARENT);
}else{
param2.width = (int) (Width * scale);
}
menu.setLayoutParams(param2);
}<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">
<cc.wxf.slide.SlideListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:cacheColorHint="@android:color/transparent"
android:listSelector="@android:color/transparent"
android:dividerHeight="1dp"
android:divider="@android:color/darker_gray"
/>
</RelativeLayout>
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SlideListView listView = (SlideListView) findViewById(R.id.listView);
listView.setAdapter(new SlideAdapter(this, listView));
}
}public class SlideAdapter extends BaseAdapter {
private Context context;
private SlideListView listView;
public SlideAdapter(Context context, SlideListView listView){
this.context = context;
this.listView = listView;
}
private String[] data = new String[]{
"1231231","232131231","1231231","232131231","1231231","232131231","1231231","232131231","1231231","232131231","1231231","232131231","1231231","232131231"
};
@Override
public int getCount() {
return data.length;
}
@Override
public Object getItem(int position) {
return data[position];
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if(convertView == null){
SlideItemView itemView = new SlideItemView(context);
itemView.setView(listView, R.layout.item_content, R.layout.item_menu, 2.0f / 3);
holder = new ViewHolder(itemView);
itemView.setTag(holder);
convertView = itemView;
}else{
holder = (ViewHolder) convertView.getTag();
}
holder.textView.setText(data[position]);
final SlideItemView itemView = (SlideItemView) convertView;
holder.imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(context, "点击了imageview", Toast.LENGTH_SHORT).show();
itemView.showContent();
}
});
holder.textView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(context, "点击了textview", Toast.LENGTH_SHORT).show();
itemView.showContent();
}
});
holder.btn1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(context, "点击了btn1", Toast.LENGTH_SHORT).show();
itemView.showContent();
}
});
holder.btn2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(context, "点击了btn2", Toast.LENGTH_SHORT).show();
itemView.showContent();
}
});
return convertView;
}
public class ViewHolder {
public ImageView imageView;
public TextView textView;
public TextView btn1;
public TextView btn2;
public ViewHolder(SlideItemView view){
View content = view.getContent();
imageView = (ImageView) content.findViewById(R.id.imageView);
textView = (TextView) content.findViewById(R.id.textView);
View menu = view.getMenu();
btn1 = (TextView) menu.findViewById(R.id.btn1);
btn2 = (TextView) menu.findViewById(R.id.btn2);
}
}
}<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="wrap_content"
>
<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_launcher"
android:layout_centerVertical="true"
android:layout_marginLeft="10dp"
/>
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/app_name"
android:textSize="15sp"
android:textColor="@android:color/black"
android:layout_centerVertical="true"
android:layout_alignParentRight="true"
android:layout_marginRight="10dp"
/>
</RelativeLayout>
<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="horizontal"
android:gravity="center"
android:padding="20dp"
android:background="@android:color/holo_red_light"
>
<TextView
android:id="@+id/btn1"
android:layout_width="match_parent"
android:layout_weight="1"
android:layout_height="match_parent"
android:gravity="center"
android:text="@string/btn1"
android:textSize="15sp"
android:textColor="@android:color/black"
/>
<TextView
android:id="@+id/btn2"
android:layout_width="match_parent"
android:layout_weight="1"
android:layout_height="match_parent"
android:gravity="center"
android:text="@string/btn2"
android:textSize="15sp"
android:textColor="@android:color/black"
/>
</LinearLayout>
热门源码