Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android學習筆記二十九之SwipeRefreshLayout、RecyclerView和CardView

Android學習筆記二十九之SwipeRefreshLayout、RecyclerView和CardView

編輯:關於Android編程

前面我們介紹了AlertDialog和幾個常用的Dialog,ProgressDialog進度條提示框、DatePickerDialog日期選擇對話框和TimePickerDialog時間選擇對話框。這一節我們介紹幾個新的API控件SwipeRefreshLayout、RecyclerView和CardView,這幾個API控件都是google在Android5.0推出的。下面我們來學習一下這幾個新的控件:

SwiperefreshLayout

SwiperefreshLayout是Android提供的一個下拉刷新的布局,繼承自ViewGroup,在support v4兼容包下,想要使用必須把你的support library的版本升級到19.1。相信很多Android開發者都對ActionBarPullToRefresh這個框架比較熟悉。SwiperefreshLayout的推出,對於我們實現下拉刷新就變得非常簡單了。

下面是SwiperefreshLayout的常用方法:

setOnRefreshListener(OnRefreshListener): 為布局添加一個Listener

setRefreshing(boolean): 設置是否處於刷新狀態

isRefreshing(): 檢查是否處於刷新狀態

setColorScheme(): 設置進度條的顏色主題,最多能設置四種

setProgressBackgroundColorSchemeResource(): 設置進度條背景顏色

使用的話就直接在XML文件中使用即可,例如:



這個一個布局容器,我們可以在其上添加其他的控件。附上SwiperefreshLayout的國內鏡像API

RecyclerView

RecyclerView是Android5.0之後推出的一個新的控件,這是一個強大的滑動組件,比ListView擁有更多的功能。官方介紹RecyclerView是ListView的升級版,RecyclerView有如下的優點:

RecylerView封裝了viewholder的回收復用,也就是說是RecyclerView是面向ViewHolder編程而不是View

RecyclerView高度解耦,非常靈活。RecyclerView不僅可以像ListView一樣顯示列表視圖,還可以顯示網格視圖等。只要你傳入不同的LayoutManager就可以控制顯示不同的樣式,RecyclerView提供的LayoutManager有:LinearLayoutManager橫向或者縱向滑動;GridLayoutManager網格布局顯示;StaggeredGridLayoutManager瀑布流顯示效果。

RecyclerView可以通過ItemDecoration控制Item之間的間隔

RecyclerView可以通過ItemAnimator控制Item的增刪動畫

關於具體的RecyclerView的介紹推薦兩篇博客,Android RecyclerView 使用完全解析 體驗藝術般的控件 Android開發之RecyclerView的使用全解 這裡就不在做過多的描述了。後面我們會通過幾個例子體會一下RecyclerView的用法。

附上RecyclerView的國內鏡像API

CardView

CardView也是Android5.0推出的一個全新控件,CardView類似於FrameLayout,但是添加了圓角和陰影效果,常用於ListView和RecyclerView中,是一種容器,可以在CardView之上添加其它控件。下面我們了解一下CardView的常用屬性:

card_view:cardElevation:陰影的大小 card_view:cardMaxElevation:陰影最大高度 card_view:cardBackgroundColor:卡片的背景色 card_view:cardCornerRadius:卡片的圓角大小 card_view:contentPadding:卡片內容的內邊距 card_view:contentPaddingBottom:卡片內容的底部內邊距 card_view:contentPaddingTop:卡片內容的上內邊距 card_view:contentPaddingLeft:卡片內容的左內邊距 card_view:contentPaddingRight:卡片內容的右內邊距 card_view:contentPaddingStart:卡片內容的左內邊距 card_view:contentPaddingEnd:卡片內容的右內邊距 card_view:cardUseCompatPadding:設置內邊距,V21+的版本和之前的版本仍舊具有一樣的計算方式 card_view:cardPreventConrerOverlap:在V20和之前的版本中添加內邊距,這個屬性為了防止內容和邊角的重疊

附上CardView的國內鏡像API

關於SwiperefreshLayout、RecyclerView和CardView就簡單介紹到這裡,下面我們用幾個例子體會一下這三個控件組合的效果:

使用RecyclerView需要在Gradle中添加:

compile 'com.android.support:recyclerview-v7:24.0.0'

使用CardView需要在Gradle中添加:

compile 'com.android.support:cardview-v7:24.0.0'

SwiperefreshLayout、RecyclerView和CardView組合實現普通的列表視圖,有下拉刷新功能:

首先是布局文件的代碼:







Item布局文件代碼:






    

    




接著是適配器的代碼:

package com.example.newapidemo.adapter;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import com.example.newapidemo.OnItemClickListener;
import com.example.newapidemo.R;
import com.example.newapidemo.domain.RVTest;

import java.util.List;

/**
 * Created by Devin on 2016/7/14.
 * 自定義RecyclerView的適配器
 */
public class RVListAdapter extends RecyclerView.Adapter {

private Context mContext;
private List datas;
private OnItemClickListener mListener;

/**
 * 暴露出去的設置item點擊事件
 *
 * @param mListener
 */
public void setOnItemClickListener(OnItemClickListener mListener) {
    this.mListener = mListener;
}

public RVListAdapter(Context mContext, List datas) {
    this.mContext = mContext;
    this.datas = datas;
}

/**
 * 為每一個Item inflate一個View,返回一個ViewHolder,將View封裝在ViewHolder中,省略掉setTag和getTag的步驟
 *
 * @param parent
 * @param viewType
 * @return
 */

@Override
public RVListViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(mContext).inflate(R.layout.item_rvlist, parent, false);
    //給每一個item設置點擊監聽
    view.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            if (mListener != null) {
                //調用getTag取出數據
                mListener.onItemClick(view, (String) view.getTag());
            }
        }
    });
    return new RVListViewHolder(view);
}

/**
 * 將數據渲染到View中
 *
 * @param holder
 * @param position
 */
@Override
public void onBindViewHolder(RVListViewHolder holder, int position) {
    //將數據通過調用setTag方法保存在ItemView裡面,然後可以調用getTag取出數據
    holder.itemView.setTag(datas.get(position).getContent());
    holder.iv_rvlist_icon.setImageResource(R.mipmap.ic_launcher);
    holder.tv_rvlist_text.setText(datas.get(position).getContent());
}

/**
 * 獲取到Item的數量
 *
 * @return
 */
@Override
public int getItemCount() {
    return datas.size();
}

/**
 * 批量添加數據
 *
 * @param testList
 */
public void addItems(List testList) {
    if (testList != null) {
        datas.addAll(0, testList);
        notifyItemRangeChanged(0, testList.size());
    }
}

/**
 * ViewHolder,需要繼承RecyclerView.ViewHolder
 */
public static class RVListViewHolder extends RecyclerView.ViewHolder {
    private ImageView iv_rvlist_icon;
    private TextView tv_rvlist_text;

    public RVListViewHolder(View itemView) {
        super(itemView);
        iv_rvlist_icon = (ImageView) itemView.findViewById(R.id.iv_rvlist_icon);
        tv_rvlist_text = (TextView) itemView.findViewById(R.id.tv_rvlist_text);
    }
}
}

由於RecyclerView不像ListView一樣提供Item點擊事件,所以我們需要自己去實現,Item點擊和長按事件,按自己需求去實現,這裡的話就實現Item點擊事件。

最後是Activity代碼:

package com.example.newapidemo;

import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.OrientationHelper;
import android.support.v7.widget.RecyclerView;
import android.view.View;

import com.example.newapidemo.adapter.RVListAdapter;
import com.example.newapidemo.domain.RVTest;

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

/**
 * Created by Devin on 2016/7/14.
 */
public class RVListActivity extends AppCompatActivity {
private SwipeRefreshLayout swipeRefreshLayout;
private RecyclerView recyclerView;
private LinearLayoutManager linearLayoutManager;
private RVListAdapter adapter;
private List datas;
public static String TAG = "RVListActivity";

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_rvlist);
    swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.sl);
    recyclerView = (RecyclerView) findViewById(R.id.recycler);
    linearLayoutManager = new LinearLayoutManager(this);
    //設置為垂直布局,這也是默認的
    linearLayoutManager.setOrientation(OrientationHelper.VERTICAL);
    //設置布局管理器
    recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
    //設置增加或刪除條目的動畫
    recyclerView.setItemAnimator(new DefaultItemAnimator());
    datas = new ArrayList<>();
    initData();
    adapter = new RVListAdapter(this, datas);
    //設置適配器
    recyclerView.setAdapter(adapter);
    //設置Item點擊監聽
    adapter.setOnItemClickListener(new OnItemClickListener() {
        @Override
        public void onItemClick(View view, String data) {
            ToastUtils.showToast(RVListActivity.this, data);
        }
    });
    //設置刷新時動畫的背景顏色
    swipeRefreshLayout.setProgressBackgroundColorSchemeResource(android.R.color.white);
    //設置下拉刷新時候動畫的顏色,可以一次設置四個
    swipeRefreshLayout.setColorSchemeResources(android.R.color.holo_blue_light,
            +android.R.color.holo_red_light, android.R.color.holo_orange_light,
            +android.R.color.holo_green_light);
    //設置刷新監聽
    swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
        @Override
        public void onRefresh() {
            new UpdateTask().execute();
        }
    });

}

/**
 * 初始化數據
 */
private void initData() {
    for (int i = 0; i < 20; i++) {
        datas.add(new RVTest(i, "這是第 " + (i + 1) + " 條測試數據"));
    }
}

/**
 * 模擬加載數據
 */
private class UpdateTask extends AsyncTask> {
    @Override
    protected List doInBackground(Void... voids) {
        try {
            //休眠3秒鐘
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        List data = new ArrayList<>();
        data.add(new RVTest(0, "下拉刷新出來的數據1"));
        data.add(new RVTest(1, "下拉刷新出來的數據2"));
        data.add(new RVTest(2, "下拉刷新出來的數據3"));
        return data;
    }

    @Override
    protected void onPostExecute(List testList) {
        adapter.addItems(testList);
        //停止刷新
        swipeRefreshLayout.setRefreshing(false);
        //RecyclerView滑動到第一個
        recyclerView.scrollToPosition(0);
        ToastUtils.showToast(RVListActivity.this, "刷新了3條數據");
    }
}
}

在這裡通過用SwiperefreshLayout實現下拉刷新功能,非常簡單,下拉刷新加載數據在這裡只是模擬網絡請求數據,然後實現的效果圖如下:

\

這裡是實現類似於ListView的效果,不過用這種組合比較符合google的MD設計效果,在實際的開發中我們可以按需求擴展。下面是SwiperefreshLayout、RecyclerView和CardView實現網格效果

SwiperefreshLayout、RecyclerView和CardView實現網格效果:<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwPsrXz8jSwMi7yseyvL7WzsS8/rT6wuujujwvcD4NCjxwcmUgY2xhc3M9"brush:java;">

Item布局代碼:






    

    




接著是適配器代碼,跟上面一個例子的適配器代碼基本一樣,就沒有寫那麼多注釋了:

package com.example.newapidemo.adapter;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.example.newapidemo.OnItemClickListener;
import com.example.newapidemo.R;
import com.example.newapidemo.domain.RVTest;

import java.util.List;

/**
 * Created by Devin on 2016/7/14.
 */
public class RVGridAdapter extends RecyclerView.Adapter {

private Context mContext;
private List datas;
private OnItemClickListener onItemClickListener;

public void setOnItemClickListener(OnItemClickListener listener) {
    this.onItemClickListener = listener;
}

public RVGridAdapter(Context mContext, List datas) {
    this.mContext = mContext;
    this.datas = datas;
}

@Override
public RVGridViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(mContext).inflate(R.layout.item_rvgrid, parent, false);
    view.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            if (onItemClickListener != null) {
                onItemClickListener.onItemClick(view, (String) view.getTag());
            }
        }
    });
    return new RVGridViewHolder(view);
}

@Override
public void onBindViewHolder(RVGridViewHolder holder, int position) {
    holder.itemView.setTag(datas.get(position).getContent());
    holder.tv_rvgrid.setText(datas.get(position).getContent());
}

@Override
public int getItemCount() {
    return datas.size();
}
/**
 * 批量添加數據
 *
 * @param testList
 */
public void addItems(List testList) {
    if (testList != null) {
        datas.addAll(0, testList);
        notifyItemRangeChanged(0, testList.size());
    }
}
public static class RVGridViewHolder extends RecyclerView.ViewHolder {
    TextView tv_rvgrid;

    public RVGridViewHolder(View itemView) {
        super(itemView);
        tv_rvgrid = (TextView) itemView.findViewById(R.id.tv_rvgrid);
    }
}
}

最後是Activity代碼:

package com.example.newapidemo;

import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;

import com.example.newapidemo.adapter.RVGridAdapter;
import com.example.newapidemo.domain.RVTest;

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

/**
 * Created by Devin on 2016/7/14.
 */
public class RVGridActivity extends AppCompatActivity {
private SwipeRefreshLayout sl_grid;
private RecyclerView rv_grid;
private GridLayoutManager gridLayoutManager;
private RVGridAdapter adapter;
private List datas;
private String[] names = {"浏覽器", "工具", "圖庫", "設置", "微信", "安全", "電話", "短信", "QQ",
        "聯系人", "起點", "雲音樂", "游戲", "愛消除", "系統",
        "筆記", "隨手記", "計算器", "文件", "天氣"};

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_rvgrid);
    rv_grid = (RecyclerView) findViewById(R.id.rv_grid);
    sl_grid = (SwipeRefreshLayout) findViewById(R.id.sl_grid);
    gridLayoutManager = new GridLayoutManager(this, 4);
    rv_grid.setLayoutManager(gridLayoutManager);
    rv_grid.setItemAnimator(new DefaultItemAnimator());
    //設置刷新時動畫的背景顏色
    sl_grid.setProgressBackgroundColorSchemeResource(android.R.color.white);
    //設置下拉刷新時候動畫的顏色,可以一次設置四個
    sl_grid.setColorSchemeResources(android.R.color.holo_blue_light,
            +android.R.color.holo_red_light, android.R.color.holo_orange_light,
            +android.R.color.holo_green_light);
    initData();
    adapter = new RVGridAdapter(this, datas);
    rv_grid.setAdapter(adapter);
    adapter.setOnItemClickListener(new OnItemClickListener() {
        @Override
        public void onItemClick(View view, String data) {
            ToastUtils.showToast(RVGridActivity.this, "點擊的是:" + data);
        }
    });
    sl_grid.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
        @Override
        public void onRefresh() {
            new UpdateTask().execute();
        }
    });
}

private void initData() {
    datas = new ArrayList<>();
    for (int i = 0; i < 20; i++) {
        datas.add(new RVTest(i, names[i]));
    }
}

/**
 * 模擬加載數據
 */
private class UpdateTask extends AsyncTask> {
    @Override
    protected List doInBackground(Void... voids) {
        try {
            //休眠3秒鐘
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        List data = new ArrayList<>();
        data.add(new RVTest(0, "數據1"));
        data.add(new RVTest(1, "數據2"));
        data.add(new RVTest(2, "數據3"));
        data.add(new RVTest(2, "數據4"));
        return data;
    }

    @Override
    protected void onPostExecute(List testList) {
        adapter.addItems(testList);
        //停止刷新
        sl_grid.setRefreshing(false);
        //RecyclerView滑動到第一個
        rv_grid.scrollToPosition(0);
        ToastUtils.showToast(RVGridActivity.this, "刷新了4條數據");
    }
}
}

其實這個例子跟上一個比較類似,只是在RecyclerView中傳入不同的布局管理器而已,這樣我們在實現網格效果就比較簡單了,然後是效果圖:

\

這裡簡單實現類似網格視圖的效果,跟上一個例子比較相似,就不再做很多介紹了,下面是實現瀑布流的效果:

首先是布局文件代碼:






Item布局代碼:









適配器代碼:

package com.example.newapidemo.adapter;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.example.newapidemo.OnItemClickListener;
import com.example.newapidemo.R;
import com.example.newapidemo.domain.RVTest;

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

/**
 * Created by Devin on 2016/7/14.
 */
public class RVStaggerAdapter extends RecyclerView.Adapter {
private Context mContext;
private List datas;
private OnItemClickListener onItemClickListener;
private List heights;

public RVStaggerAdapter(Context mContext, List datas) {
    this.mContext = mContext;
    this.datas = datas;
    getRandomHeight(this.datas);
}

public void setOnItemClickListener(OnItemClickListener listener) {
    this.onItemClickListener = listener;
}

@Override
public RVStaggerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(mContext).inflate(R.layout.item_rvstagger, parent, false);
    view.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            if (onItemClickListener != null) {
                onItemClickListener.onItemClick(view, (String) view.getTag());
            }
        }
    });
    return new RVStaggerViewHolder(view);
}

@Override
public void onBindViewHolder(RVStaggerViewHolder holder, int position) {
    //得到item的LayoutParams布局參數
    ViewGroup.LayoutParams params = holder.itemView.getLayoutParams();
    //把隨機的高度賦予item布局
    params.height = heights.get(position);
    //把params設置給item布局
    holder.itemView.setLayoutParams(params);
    holder.itemView.setTag(datas.get(position).getContent());
    holder.tv_rvstagger.setText(datas.get(position).getContent());
}

@Override
public int getItemCount() {
    return datas.size();
}

/**
 * 批量添加數據
 *
 * @param testList
 */
public void addItems(List testList) {
    if (testList != null) {
        datas.addAll(0, testList);
        notifyItemRangeChanged(0, testList.size());
    }
}

/**
 * 隨機得到Item的高度
 *
 * @param lists
 */
private void getRandomHeight(List lists) {
    heights = new ArrayList<>();
    for (int i = 0; i < lists.size(); i++) {
        heights.add((int) (200 + Math.random() * 400));
    }
}

public static class RVStaggerViewHolder extends RecyclerView.ViewHolder {
    TextView tv_rvstagger;

    public RVStaggerViewHolder(View itemView) {
        super(itemView);
        tv_rvstagger = (TextView) itemView.findViewById(R.id.tv_rvstagger);
    }
}

}

最後是Activity代碼:

package com.example.newapidemo;

import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.view.View;

import com.example.newapidemo.adapter.RVStaggerAdapter;
import com.example.newapidemo.domain.RVTest;

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

/**
 * Created by Devin on 2016/7/14.
 */
public class RVStaggeredActivity extends AppCompatActivity {
private SwipeRefreshLayout sl_stagger;
private RecyclerView rv_stagger;
private StaggeredGridLayoutManager layoutManager;
private List datas;
private String[] names = {"浏覽器", "工具", "圖庫", "設置", "微信", "安全", "電話", "短信", "QQ", "汽車"};
private int[] icons = {R.drawable.icon0, R.drawable.icon1,
        R.drawable.icon2, R.drawable.icon3,
        R.drawable.icon4, R.drawable.icon5,
        R.drawable.icon6, R.drawable.icon7,
        R.drawable.icon8, R.drawable.icon9};
private RVStaggerAdapter adapter;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_rvstagger);
    sl_stagger = (SwipeRefreshLayout) findViewById(R.id.sl_stagger);
    rv_stagger = (RecyclerView) findViewById(R.id.rv_stagger);
    layoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
    rv_stagger.setLayoutManager(layoutManager);
    initData();
    adapter = new RVStaggerAdapter(this, datas);
    rv_stagger.setAdapter(adapter);
    //設置刷新時動畫的背景顏色
    sl_stagger.setProgressBackgroundColorSchemeResource(android.R.color.white);
    //設置下拉刷新時候動畫的顏色,可以一次設置四個
    sl_stagger.setColorSchemeResources(android.R.color.holo_blue_light,
            +android.R.color.holo_red_light, android.R.color.holo_orange_light,
            +android.R.color.holo_green_light);
    adapter.setOnItemClickListener(new OnItemClickListener() {
        @Override
        public void onItemClick(View view, String data) {
            ToastUtils.showToast(RVStaggeredActivity.this, "點擊的是:" + data);
        }
    });
    sl_stagger.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
        @Override
        public void onRefresh() {
            new UpdateTask().execute();
        }
    });

}

private void initData() {
    datas = new ArrayList<>();
    for (int i = 0; i < 30; i++) {
        datas.add(new RVTest(i, "原始數據" + i));
    }
}

/**
 * 模擬加載數據
 */
private class UpdateTask extends AsyncTask> {
    @Override
    protected List doInBackground(Void... voids) {
        try {
            //休眠3秒鐘
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        List data = new ArrayList<>();
        data.add(new RVTest(0, "數據1"));
        data.add(new RVTest(0, "數據2"));
        data.add(new RVTest(0, "數據3"));
        data.add(new RVTest(0, "數據4"));
        return data;
    }

    @Override
    protected void onPostExecute(List testList) {
        adapter.addItems(testList);
        //停止刷新
        sl_stagger.setRefreshing(false);
        //RecyclerView滑動到第一個
        rv_stagger.scrollToPosition(0);
        ToastUtils.showToast(RVStaggeredActivity.this, "刷新了4條數據");
    }
}
}

實現效果圖如下:

\

這樣就可以實現瀑布流效果了,關於這三個控件的組合就簡單介紹到這裡,下一節,我們繼續用這三個控件實現拖拽和滑動效果。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved