cvmachine.com - 申博开户网

查找: 您的方位主页 > 手机频道 > 阅览资讯:ListView滑动删去完结之四——Scroller类与listview缓慢滑动

ListView滑动删去完结之四——Scroller类与listview缓慢滑动

2019-03-30 18:06:29 来历:www.cvmachine.com 【

前语:这个月真是过得太快了,本来说要看四章的内容,这下才看了两章,擦……严峻没完结预算碍…撞豆腐死了算了

 

相关文章:

1、《 ListView滑动删去完结之一——merge标签与LayoutInflater.inflate()》

2、《ListView滑动删去完结之二——scrollTo、scrollBy详解》

3、《 ListView滑动删去完结之三——创立可滑动删去的ListView》

4、《ListView滑动删去完结之四——Scroller类与listview缓慢滑动》

 

上篇咱们现已完结了运用scrollTo完结listview的滑动删去,但咱们终究也提到了一个问题:当手指抬起时,scrollTo直接将ITEM滑动到了指定方位,中心没有缓冲进程,用户体会欠好。咱们想完结一个能缓慢滑动的listview:如下图所示:

ListView滑动删去完结之四——Scroller类与listview缓慢滑动

从示图中显着能够看到,这儿并不像上一章相同,一会儿复原到初始化状况或许一会儿到彻底打开的状况了。而是有一个进程,它会慢慢点,一点点地复原或打开。这便是Scroller类所起的作用。下面咱们先看看Scroller类的运用办法,然后再在前一篇的基础上加上Scroller。

一、Scroller类

首要,上篇咱们也提到了,scrollTo()是没有办法增加运动的时刻长度的,所以为了补偿这个问题,google就新增了一个类Scroller!必定要留意的是,Scroller类,并不能像scrollTo相同移动View的视角,而只能用来核算当时滑动的方位。看不懂不要紧,持续往下看。

1、相关函数

(1)结构函数:
public Scroller (Context context)
public Scroller (Context context, Interpolator interpolator)
假如咱们用第一个结构函数,那么Scroller就会给咱们传入一个默许的插值器;一般咱们会挑选第二个结构函数,传入一个咱们想要的插值器。插值器的概念是从Animation来的,曾经我曾把一切插值器的动画特效都罗列了一遍,咱们有爱好能够参阅:《Animation动画详解(二)——Interpolator插值器》
Scroller结构完了今后,就能够调用startScroll()了,关于这个函数的作用先不表,但肯定不是像scrollTo相同移动视角的。
(2)startScroll
public void startScroll(int startX, int startY, int dx, int dy, int duration)
public void startScroll(int startX, int startY, int dx, int dy)
咱们先看第一个结构函数:
  • startX:开端移动的X坐标
  • startY开端移动的Y坐标
  • dx:沿X轴移动间隔,可正可负,为正时,子控件向左移动;为负时,子控件向右移动
  • dy:沿Y轴移动间隔,相同,为正时,子控件向上移动;为负时,子控件向下移动
  • duration:整个移动进程,所耗费时长
第二个结构函数中,没有duration这个参数,体系会运用默许的时长:250毫秒

2、运用办法:

过程一:初始化
private Scroller mScroller;
mScroller = new Scroller(context,new LinearInterpolator(context,null));
过程二:startScroll
在需求翻滚的当地调用startScroll
 mScroller.startScroll(0,0,200,0,500);
 invalidate();
过程三: public void computeScroll()中处理
@Override
public void computeScroll() {

  if (mScroller.computeScrollOffset()){
    itemRoot.scrollTo(mScroller.getCurrX(),mScroller.getCurrY());
  }
  invalidate();
}
在这儿留意一个当地,咱们在computeScroll()中终究调用了itemRoot的scrollTo(),这儿又触及两个函数:
mScroller.getCurrX()
mScroller.getCurrY()
这两个是什么意思?看外表意思是获取当时scroller地点的X轴坐标和Y轴坐标。莫非它的X轴坐标和Y轴坐标还都不相同吗?
原因是这样的:
咱们前面说过,Scoller类是scrollTo的弥补,他没有scrollTo的功用,它的功用便是依据传进去的参数核算方位的。咱们再看一下的咱们比如中的结构函数:
mScroller.startScroll(0,0,200,0,500);
这个代码便是说用500毫秒的时刻从(0,0)的方位,沿X轴反方向移动200,Y轴不动;
但这个函数并不会移动,而是模拟核算,调用了这个函数之后,它就会在scroller内部用一个线程来核算从(0,0)的方位,沿X轴反方向移动200,Y轴不动;每一毫秒的方位,用户能够经过scroller.getCurrX()、scroller.getCurrY()来获取,当时应该在的方位。留意,我用的“应该”。因为scroller仅仅依据插值器,指定的时刻,间隔;算出当时地点的X轴坐标,Y轴坐标。但对图画并没有做任何操作!!!!!!要想移动图画,就有必要运用scrollTo()!!!所以咱们要每核算出一个新的方位就让View重绘一次。这便是为什么过程二和过程三都会调用invalidate()的原因。
//过程二:
 mScroller.startScroll(0,0,200,0,500);
 invalidate();
```
``` java
@Override
public void computeScroll() {
//过程三:
  if (mScroller.computeScrollOffset()){
    itemRoot.scrollTo(mScroller.getCurrX(),mScroller.getCurrY());
    invalidate();
  }
}
这儿还要再说一个点:咱们怎么判别什么时分中止重绘呢。scroller给咱们供给了一个函数:
Scroller.computeScrollOffset()
当scroller还在移动时,就回来TRUE,假如scroller现已移动完毕就回来FALSE;所以,咱们能够在直接itemRoot.scrollTo(mScroller.getCurrX(),mScroller.getCurrY());前运用mScroller.computeScrollOffset()来判别当时scroller是不是现已完毕了。
这儿要插一句,computeScroll()函数,不是Scroller的函数,而是VIEW的函数,当调用invaidate或许postInvalidate重绘时就会调用computeScroll() 来重绘与scroller有关的View部分,而在View中的完结办法如下:
  /**
   * Called by a parent to request that a child update its values for mScrollX
   * and mScrollY if necessary. This will typically be done if the child is
   * animating a scroll using a {@link android.widget.Scroller Scroller}
   * object.
   */
  public void computeScroll() {
  }
显着这儿是一个空函数,所以,这就交由咱们自己来完结,Scroller中的移动部分了,这也便是为什么咱们会在computeScroll() 中调用 scrollTo来完结视图的移动了。

终究咱们总结一下:Scroller在调用startScroll()之后,会自己依据移动间隔和时刻来核算每毫秒的移动意图坐标,用户能够经过scroller.getCurrX()和scroller.getCurrY()来获龋当VIEW在重绘时,会调用View的computeScroll()函数来处理与scroller有关的重绘操作。而因为View类并没有对computeScroll()做任何的完结(仅仅一个空函数),所以有关scroller的移动操作,就只能靠咱们自己完结了。(重写computeScroll函数,调用)

二、完结缓慢滑动的ListView

这儿咱们就运用scroller类来完结文章最初时的作用,这篇文章依附上一篇的源码:《 ListView滑动删去完结之三——创立可滑动删去的ListView》
因为咱们要完结的缓慢滑动作用是在用户手指抬起后,缓慢移动到方针方位的,所以咱们下面一切的代码都是在MyListView中来做的。

1、声明Scroller变量及初始化

代码如下:
public class MyListView extends ListView {
  
  private Context mContext;
  private Scroller mScroller;

  public MyListView(Context context, AttributeSet attrs) {
    super(context, attrs);
    mContext = context;
    mScroller = new Scroller(context, new LinearInterpolator(context, null));
  }
  ……
}
咱们这儿初始化mScroller时,运用线性插值器;咱们也能够用其它插值器,每一个插值器的运动作用都是不相同的。

2、用户抬起时,调用startScroll()

在初始化完scroller今后,下面便是在用户抬起手指时,调用startScroll()来开端核算每毫秒地点的意图坐标。
public boolean onTouchEvent(MotionEvent event) {
  int maxLength = dipToPx(mContext, MAX_WIDTH);
  int x = (int) event.getX();
  int y = (int) event.getY();
  switch (event.getAction()) {
    …………
    case MotionEvent.ACTION_UP: {
      int scrollX = itemRoot.getScrollX();
      int newScrollX = scrollX + mlastX - x;
      if (scrollX > maxLength / 2) {
        newScrollX = maxLength;
      } else {
        newScrollX = 0;
      }
      mScroller.startScroll(scrollX,0,newScrollX - scrollX,0);
      invalidate();
    }
    break;
  }

  mlastX = x;
  return super.onTouchEvent(event);
}
咱们把中心代码摘出来:
  int scrollX = itemRoot.getScrollX();
  int newScrollX = scrollX + mlastX - x;
  if (scrollX > maxLength / 2) {
    newScrollX = maxLength;
  } else {
    newScrollX = 0;
  }
  mScroller.startScroll(scrollX,0,newScrollX - scrollX,0);
  invalidate();
首要跟上篇相同,依据当时手指的方位(假如超越黄色块1/2就将newScrollX设置到最大值;假如小于黄色块1/2,那就复原到初始化状况),然后是调用
mScroller.startScroll(scrollX,0,newScrollX - scrollX,0);
首要是移动间隔,咱们必定要留意的是移动间隔不必定是正数,它仅仅表明在当时方向上的移动数,X轴为正:视角向右移动,即其间的子控件向左移动。为负:视角向左移动,即其间的子控件所右移动;Y轴同理。所以这儿的第三个参数dx:就等于意图坐标减去原坐标。这便是第三个参数为什么是newScrollX - scrollX的原因。
终究调用invalidate()来重绘,因为咱们这儿有Scroller,所以在重绘时就会走到VIEW的computeScroll()函数中,上面咱们也说了VIEW中的computeScroll()仅仅一个空函数,VIEW并没有对它进行任何完结。所以咱们下面这样来完结它:

3、完结computeScroll()函数

先上代码:
public void computeScroll() {

  if (mScroller.computeScrollOffset()){
    itemRoot.scrollTo(mScroller.getCurrX(),mScroller.getCurrY());
    invalidate();
  }
}
能够看到,首要是运用mScroller.computeScrollOffset()来判别当时Scroller的状况——是否现已核算移动方位完毕,假如完毕回来FALSE,假如还在核算就回来TRUE。
然后,假如还在核算,就阐明还在移动进程中,那么就调用Scroller.getCurrX()和mScroller.getCurrY()来提取当时核算出来的应该移动的X轴坐标和Y轴坐标。然后调用itemRoot.scrollTo();来移动其间的子控件。这一次完毕了,下一毫秒该怎么办呢?所以咱们还要调用invalidate();函数,让它再次重绘,从头走进computeScroll() 函数,找到最新的Scroller方位并移动。终究当移动完毕,mScroller.computeScrollOffset()就会回来FALSE,终究完毕重绘。

三、优化

1、开始优化

用过这个控件的同学应该都知道,一般情况下的完结办法是,假如有一个ITEM被划出来,其它的ITEM都应该缩短回去。就如下面的这个作用:
ListView滑动删去完结之四——Scroller类与listview缓慢滑动

1、首要,当另一个ITEM滑出来的时分,上一个ITEM缩回去。
2、但终究咱们会发现问题:当我接连点击一个ITEM之后,上一个ITEM就会中止滑动。这个作用不是咱们想要的,咱们先完结第一个作用,后边再处理这个问题。

因为咱们要让上一个ITEM滑动,所以咱们要在MyListView中别的界说一个变量来保存前次滑动的VIEW

private LinearLayout mPreScrollView;
然后额定增加一个SCROLLER,用来核算mPreScrollView的翻滚坐标:
private Scroller mPreScroller;

public MyListView(Context context, AttributeSet attrs) {
  super(context, attrs);
  mContext = context;
  mScroller = new Scroller(context, new LinearInterpolator(context, null));
  mPreScroller = new Scroller(context, new LinearInterpolator(context, null));
}
然后是对mPreScrollView赋值和翻滚了。咱们鄙人按一个ITEM的时分,就要把前一个ITEM复原。当咱们手指上抬的时分,那这个ITEM就现已翻滚完毕了,那么它便是下一次的mPreScrollView。
public boolean onTouchEvent(MotionEvent event) {
  switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN: {

      if (mPreScrollView != null){
        int preScrollX = mPreScrollView.getScrollX();
        mPreScroller.startScroll(preScrollX,0,0-preScrollX,0);
      }
    }
    break;
    case MotionEvent.ACTION_UP: {
      …………
      mPreScrollView = itemRoot;
      …………
      invalidate();
    }
    break;
  }
  mlastX = x;
  return super.onTouchEvent(event);
}
终究是在computeScroll()中移动mPreScrollView
public void computeScroll() {
  …………
  if (mPreScroller.computeScrollOffset()){
    mPreScrollView.scrollTo(mPreScroller.getCurrX(),mPreScroller.getCurrY());
  }
  invalidate();

}
到这儿就完毕了,mPreScrollView鄙人一次滑动ITEM时就会自己缩短了,但这儿有个问题,也便是作用图中的第二点问题。当咱们对一个ITEM点击两下的时分,它的上一个ITEM就会中止滑动。导致不能彻底缩短回去。这是为什么呢?首要是因为咱们在MotionEvent.ACTION_UP中对mPreScrollView = itemRoot;进行的赋值。假如咱们抬起的太快,而上一个ITEM还没有滑动完毕,那么mPreScrollView还没完毕就现已被赋值给最新的ITEM了,这时分的computeScroll(),调用的mPreScrollView.scrollTo(mPreScroller.getCurrX(),mPreScroller.getCurrY());就现已是最新的ITEM了,所以上一个ITEM就会中止滑动。
源码在文章底部给出

2、终究优化

关于上面的问题,咱们仅有的处理办法便是让每个ITEM担任自己的滑动,只需求上层给它一个告诉,它自己担任自己的滑动,这样就不会抵触了。
所以咱们要对ITEM的根布局lin_root进行重写。新界说一个LinearLayout派生类MyLInearLayout。然后在其间做操作。

(1)改造:派生MyLInearLayout类

咱们独自把ITEM的根布局拿出来,在其间做一切有关的对ITEM的移动操作,代码如下:
public class MyLinearLayout extends LinearLayout {
  private int mlastX = 0;
  private final int MAX_WIDTH = 200;
  private Context mContext;
  private Scroller mScroller;
  public MyLinearLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
    mContext = context;
    mScroller = new Scroller(context, new LinearInterpolator(context, null));
  }
  public void disPatchTouchEvent(MotionEvent event){
    int maxLength = dipToPx(mContext, MAX_WIDTH);

    int x = (int) event.getX();
    int y = (int) event.getY();

    switch (event.getAction()) {
      case MotionEvent.ACTION_DOWN: {
      }
      break;
      case MotionEvent.ACTION_MOVE: {
        int scrollX = this.getScrollX();
        int newScrollX = scrollX + mlastX - x;
        if (newScrollX < 0) {
          newScrollX = 0;
        } else if (newScrollX > maxLength) {
          newScrollX = maxLength;
        }
        this.scrollTo(newScrollX, 0);
      }
      break;
      case MotionEvent.ACTION_UP: {
        int scrollX = this.getScrollX();
        int newScrollX = scrollX + mlastX - x;
        if (scrollX > maxLength / 2) {
          newScrollX = maxLength;
        } else {
          newScrollX = 0;
        }
        mScroller.startScroll(scrollX, 0, newScrollX - scrollX, 0);
        invalidate();
      }
      break;
    }
    mlastX = x;
  }

  @Override
  public void computeScroll() {
    if (mScroller.computeScrollOffset()) {
      this.scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
    }
    invalidate();

  }

  private int dipToPx(Context context, int dip) {
    return (int) (dip * context.getResources().getDisplayMetrics().density + 0.5f);
  }
}
这儿便是集成了一切对ITEM跟从手指移动的操作。

(2)、改变ITEM布局——运用MyLinearLayout

然后便是更改本来ITEM的布局,把根结点的LinearLayout改成MyLinearLayout:
<com.harvic.com.blog3_4_mylinearlayout.MyLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/lin_root"
  android:orientation="horizontal"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:minHeight="120dp">

  <TextView
    android:id="@+id/title"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="#0000ff"
    android:gravity="center"
    android:textSize="25dp" />

  <TextView
    android:id="@+id/del"
    android:layout_width="200dp"
    android:layout_height="fill_parent"
    android:background="#ffff00"
    android:text="删去"
    android:textSize="25dp"
    android:textColor="#ffffff"
    android:gravity="center" />

</com.harvic.com.blog3_4_mylinearlayout.MyLinearLayout>

(3)、终究是在MyListView中分发MotionEvent事情:

public class MyListView extends ListView {

  private MyLinearLayout mCurView;
  public MyListView(Context context, AttributeSet attrs) {
    super(context, attrs);
  }

  @Override
  public boolean onTouchEvent(MotionEvent event) {
    int x = (int) event.getX();
    int y = (int) event.getY();

    switch (event.getAction()) {
      case MotionEvent.ACTION_DOWN: {
        //咱们想知道当时点击了哪一行
        int position = pointToPosition(x, y);
        if (position != INVALID_POSITION) {
          DataHolder data = (DataHolder) getItemAtPosition(position);
          mCurView = data.rootView;
        }
      }
      break;
      default:
        break;
    }
    if (mCurView != null){
      mCurView.disPatchTouchEvent(event);
    }
    return super.onTouchEvent(event);
  }
}
首要依据方位找到一切ITEM的VIEW,然后把事情传给对应的MyLinearLayout自己处理。
到这儿改造就完结了,然后便是完结自己滑动缩回去的过程了。

 

下面的内容或许比较绕,咱们或许加上我的解说,咱们能够还要自己了解一下了
首要,咱们有几个点先罗列一下:
1、咱们需求在一个ITEM滑出来的时分,告诉到上一个ITEM,让它缩短
2、每一个ITEM都应该具有监听功用,当上一个ITEM滑出来时,它就能对应的缩短回去

(4)、主动缩短之——监听

首要,咱们要了解的一点是,咱们要监听!!!监听当时ITEM是否悉数拉了出来,所以咱们在MyLinearLayout中需求加一个回调函数来做监听:

public class MyLinearLayout extends LinearLayout {
  private OnScrollListener mScrollListener;

  public static interface OnScrollListener {
    public void OnScroll(MyLinearLayout view);
  }

  public void disPatchTouchEvent(MotionEvent event) {

    switch (event.getAction()) {
      …………
      case MotionEvent.ACTION_UP: {
        int scrollX = this.getScrollX();
        int newScrollX = scrollX + mlastX - x;
        if (scrollX > maxLength / 2) {
          newScrollX = maxLength;
          //当彻底打开时,告诉出去
          mScrollListener.OnScroll(this);
        } else {
          newScrollX = 0;
        }
        mScroller.startScroll(scrollX, 0, newScrollX - scrollX, 0);
        invalidate();
      }
      break;
    }
    mlastX = x;
  }

  …………
}
上面的代码,一共做了两件事:
1、创立回调函数
private OnScrollListener mScrollListener;
public static interface OnScrollListener{
  public void OnScroll(MyLinearLayout view);
}
因为咱们后边要保存当时的VIEW来做主动缩短,所以咱们要把当时扩展出来的ITEM的VIEW传出去,供对方保存。当下一个ITEM出来的时分,让这个VIEW缩回去
2、运用回调函数

当用户手指抬起来,并且ITEM彻底打开的时分,调用onScroll()告诉出去

case MotionEvent.ACTION_UP: {
  int scrollX = this.getScrollX();
  int newScrollX = scrollX + mlastX - x;
  if (scrollX > maxLength / 2) {
  //当彻底打开时,告诉出去
    newScrollX = maxLength;
    mScrollListener.OnScroll(this);
  } else {
    newScrollX = 0;
  }
  mScroller.startScroll(scrollX, 0, newScrollX - scrollX, 0);
  invalidate();

}
break;
然后,还有两个额定的函数:
//设置监听器
public void setOnScrollListener(OnScrollListener scrollListener) {
  mScrollListener = scrollListener;
}
//缓慢将ITEM翻滚到指定方位
public void smoothScrollTo(int destX, int destY) {
  int scrollX = getScrollX();
  int delta = destX - scrollX;
  mScroller.startScroll(scrollX, 0, delta, 0);
  invalidate();
}

(5)、主动缩短之——为每一个ITEM设置监听

因为咱们每一个ITEM都需求监听,所以把监听函数设在Adapter中最适宜。所以在MergeListAdapter中为每一个Item的根结点MyLinearLayout增加监听函数:
public View getView(final int position, View convertView, ViewGroup parent) {
  …………
  DataHolder item = mDataList.get(position);
  holder.title.setText(item.title);

  item.rootView = (MyLinearLayout) convertView.findViewById(R.id.lin_root);
  item.rootView.scrollTo(0, 0);
  item.rootView.setOnScrollListener(mScrollListener);
  …………
  return convertView;
}
而Adapter中是没有办法做监听的,所以它的监听函数也只要从MainActivity传过来:
public class MergeListAdapter extends BaseAdapter {
  private View.OnClickListener mDelClickListener;
  private MyLinearLayout.OnScrollListener mScrollListener;

  public MergeListAdapter(Context context, List<DataHolder> dataList, View.OnClickListener delClickListener, MyLinearLayout.OnScrollListener listener) {
    …………
    mDelClickListener = delClickListener;
    mScrollListener = listener;
  }
  …………
}

(6)主动缩短之——MainActivity中处理监听

代码如下:
public class MainActivity extends Activity implements View.OnClickListener,MyLinearLayout.OnScrollListener{
  private MyLinearLayout mLastScrollView;
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    …………
    adapter = new MergeListAdapter(this,items,this,this);
    listView.setAdapter(adapter);
  }
  @Override
  public void OnScroll(MyLinearLayout view) {
    if (mLastScrollView != null){
      mLastScrollView.smoothScrollTo(0,0);
    }
    mLastScrollView = view;
  }
}
首要初始化adapter,当一个ITEM彻底打开时,咱们的OnScroll()函数就会得到调用。用一个变量:MyLinearLayout mLastScrollView来保存上一次彻底打开的ITEM;当一个ITEM彻底打开时,就先调用mLastScrollView.smoothScrollTo(0,0);将上一个ITEM缩短回去,然后再将这个VIEW赋值给mLastScrollView;
终究的作用图如下:
ListView滑动删去完结之四——Scroller类与listview缓慢滑动

源码在文章底部给出

四、存在问题:不能将listview的布局参数设为wrap_content

自界说listview的参数有必要是layout_width:match_parent/fill_parent,layout_height:match_parent/fill_parent

即下面的代码:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  tools:context=".MainActivity">

  <com.harvic.com.blog3_4_mylinearlayout.MyListView
    android:id="@+id/listview"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

</RelativeLayout>

假如给Mylistview运用wrap_content,将导致scrollTo无效,详细什么原因我也不知道,所以假如listView底部还有什么界面的话,主张咱们运用listview::addFooterView()来增加底部布局的办法来做。必定要防止运用wrap_content,否则就真的会滑动无效,咱们能够测验一下,横竖我是找不到原因了……

 

好了,到这儿有关滑动删去的一切东东都讲完了,这篇文章容量有点大,咱们或许要依据源码细心了解一下了。逻辑的确有点太绕,咱们多看看源码应该问题不大。

 

终究,终究优化部分的代码是咱们这个系列主张运用的代码结构,即ITEM的根布局运用自界说的MyLinearLayout,由它自己来担任自己的翻滚。对应的源码名称为:《ScrollViewUltimate》

 

源码内容:

1、《ScrollView_Scroller》:第二部分:《完结缓慢滑动的ListView》对应源码

2、《ScrollViewUltimate》:第三部分:《优化》的终究代码,也是本体系的终究可用代码

 

假如本文有帮到你,记住加重视哦

源码下载地址:http://download.csdn.net/detail/harvic880925/8642751

请咱们尊重原创者版权,转载请标明出处:http://blog.csdn.net/harvic880925/article/details/45317951 谢谢

 

 
 

本文地址:http://www.cvmachine.com/a/luyou/100039.html
Tags: 完结 滑动 listView
修改:申博开户网
关于咱们 | 联络咱们 | 友情链接 | 网站地图 | Sitemap | App | 回来顶部