編輯:關於Android編程
前面我們介紹了AlertDialog和幾個常用的Dialog,ProgressDialog進度條提示框、DatePickerDialog日期選擇對話框和TimePickerDialog時間選擇對話框。這一節我們介紹幾個新的API控件SwipeRefreshLayout、RecyclerView和CardView,這幾個API控件都是google在Android5.0推出的。下面我們來學習一下這幾個新的控件:
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是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也是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條數據");
}
}
}
實現效果圖如下:
這樣就可以實現瀑布流效果了,關於這三個控件的組合就簡單介紹到這裡,下一節,我們繼續用這三個控件實現拖拽和滑動效果。
最近在學習android底層的一些東西,看了一些大神的博客,整體上有了一點把握,也產生了很多疑惑,於是再次把鄧大神的深入系列翻出來仔細看看,下面主要是一些閱讀筆記。JNI
本文實例為大家分享了Android帶有記住密碼功能的登陸界面實現代碼,供大家參考,具體內容如下1、設計思路主要采用SharedPreferences來保存用戶數據,本De
從系統相冊中選擇照片或則調用系統相機。大部分的項目都會用到,我進行了一下封裝,仿ios的效果。效果如下:1、Camera的基類package com.zhang.test
本文實例實現一下 RecyclerView,代碼比較簡單,適合初學者,如有錯誤,歡迎指出。復習 ListView可以查看這篇文章深入淺出學習Android ListVie