RecyclerView巢狀ViewPager實現淘寶搜狐主頁廣告輪播圖
阿新 • • 發佈:2019-01-01
RecyclerView巢狀ViewPager實現原理:
RecyclerView巢狀ViewPager實際上就是RecyclerView複雜佈局的實現,給其中一個item設定為ViewPager來實現廣告輪播圖。既然知道原理 那麼我們實現起來也就非常的方便。使用SwipeRefreshLayout對其RecyclerView實現下拉重新整理。
首先我們來看一下執行效果:
接下來我們看具體程式碼的實現:
RecyclerView巢狀ViewPager肯定會出現滑動衝突的問題,對於滑動衝突的解決我們通常採用以下兩種
內部攔截
外不攔截我們採用內部攔截,重寫ViewPager來進行事件的攔截。具體程式碼如下:
import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.ViewGroup;
/**
* Created by wenpengli on 2017/3/13.
*/
public class MyViewPager extends ViewPager {
private ViewGroup parent;
public MyViewPager(Context context) {
super(context);
}
public MyViewPager(Context context, AttributeSet attributeSet) {
super(context,attributeSet);
}
public void setNestedpParent(ViewGroup parent) {
this.parent = parent;
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (parent != null) {
parent.requestDisallowInterceptTouchEvent(true);
}
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent arg0) {
if (parent != null) {
parent.requestDisallowInterceptTouchEvent(true);
}
return super.onInterceptTouchEvent(arg0);
}
@Override
public boolean onTouchEvent(MotionEvent arg0) {
if (parent != null) {
parent.requestDisallowInterceptTouchEvent(true);
}
return super.onTouchEvent(arg0);
}
}
RecyclerView和ListView一樣比不可少的就是介面卡,在介面卡中我們定義了多種Item並且根據item的型別來判定該位置放置那種item,把我們剛重寫好的ViewPager寫在一種item中,在介面卡中 我們加入了ViewPager的初始化和一些資料的載入,也就是對每個item進行初始化。具體介面卡的程式碼如下:
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.os.Parcelable;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.widget.RecyclerView;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.xyliwp.news.R;
import com.xyliwp.news.bean.TuiJianMessage;
import com.xyliwp.news.view.myview.MyViewPager;
import com.xyliwp.news.view.viewpageranim.LRZheDie;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* Created by wenpengli on 2017/3/12.
*/
public class TuiJianRecyclerViewAdapter extends RecyclerView.Adapter{
private ArrayList<TuiJianMessage> addPinDaos;
private Context context;
private ViewHolderOne viewHolderOne;
private int currentItem = 0; // 當前圖片的索引號
private List<View> views; // 滑動原點的view
// 切換當前圖片
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
// 顯示當前圖片
viewHolderOne.myViewPager.setCurrentItem(currentItem);
}
};
public TuiJianRecyclerViewAdapter(Context context,ArrayList<TuiJianMessage> addPinDaos){
super();
this.addPinDaos = addPinDaos;
this.context = context;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = null;
RecyclerView.ViewHolder viewHolder = null;
switch (viewType){
case 0:
view = LayoutInflater.from(context).inflate(R.layout.item_recyclerview_tuijian_tou
,parent,false);
viewHolder = new ViewHolderOne(view);
break;
case 1:
view = LayoutInflater.from(context).inflate(R.layout.item_recyclerview_tuijian
,parent,false);
viewHolder = new ViewHolderMy(view);
break;
}
return viewHolder;
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
TuiJianMessage addPinDao = addPinDaos.get(position);
switch (getItemViewType(position)){
case 0:
viewHolderOne = (ViewHolderOne)holder;
viewHolderOne.textview_Viewpager.setText(addPinDaos.get(0).getTitle());
viewpagerecommendAdapter adapter = new viewpagerecommendAdapter(context);
viewHolderOne.myViewPager.setPageTransformer(true,new LRZheDie());
viewHolderOne.myViewPager.setAdapter(adapter);
viewHolderOne.myViewPager.setOnPageChangeListener(new viewpagerRecommendPageChangeListener());
ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
scheduledExecutorService.scheduleAtFixedRate(new YuanDianRun(), 3, 6,
TimeUnit.SECONDS);
break;
case 1:
final ViewHolderMy viewHolderMy = (ViewHolderMy)holder;
Glide.with(context).load(addPinDao.getPicUrl()).
override(100, 60).centerCrop().into(viewHolderMy.imageView_my);
viewHolderMy.textView_my.setText(addPinDao.getTitle());
break;
}
}
@Override
public int getItemCount() {
return addPinDaos.size();
}
@Override
public int getItemViewType(int position) {
if(position == 0){
return 0;
}else{
return 1;
}
}
class ViewHolderMy extends RecyclerView.ViewHolder{
private TextView textView_my;
private ImageView imageView_my;
public ViewHolderMy(View itemView) {
super(itemView);
imageView_my = (ImageView)itemView.findViewById(R.id.android_image);
textView_my = (TextView)itemView.findViewById(R.id.android_version);
}
}
class ViewHolderOne extends RecyclerView.ViewHolder{
private MyViewPager myViewPager;
private TextView textview_Viewpager;
private View textview_tuijian_tou1;
private View textview_tuijian_tou2;
private View textview_tuijian_tou3;
private View textview_tuijian_tou4;
private View textview_tuijian_tou5;
public ViewHolderOne(View itemView) {
super(itemView);
myViewPager = (MyViewPager) itemView.findViewById(R.id.myViewPage_tuijian_tou);
textview_Viewpager = (TextView)itemView.findViewById(R.id.textview_Viewpager);
textview_tuijian_tou1 = (View)itemView.findViewById(R.id.textview_tuijian_tou1);
textview_tuijian_tou2 = (View)itemView.findViewById(R.id.textview_tuijian_tou2);
textview_tuijian_tou3 = (View)itemView.findViewById(R.id.textview_tuijian_tou3);
textview_tuijian_tou4 = (View)itemView.findViewById(R.id.textview_tuijian_tou4);
textview_tuijian_tou5 = (View)itemView.findViewById(R.id.textview_tuijian_tou5);
//初始化原點
views = new ArrayList<View>();
views.add(textview_tuijian_tou1);
views.add(textview_tuijian_tou2);
views.add(textview_tuijian_tou3);
views.add(textview_tuijian_tou4);
views.add(textview_tuijian_tou5);
}
}
public int getWidth(){
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics dm = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(dm);
int width = dm.widthPixels;// 螢幕寬度(畫素)
float density = dm.density;//螢幕密度(0.75 / 1.0 / 1.5)
//螢幕寬度演算法:螢幕寬度(畫素)/螢幕密度
return (int) (width/density);//螢幕寬度(dp)
}
//viewpagger的PageChangeListener
private class viewpagerRecommendPageChangeListener implements ViewPager.OnPageChangeListener {
private int oldposition = 0;
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
currentItem = position;
viewHolderOne.textview_Viewpager.setText(addPinDaos.get(position).getTitle());
views.get(oldposition).setBackgroundResource(R.drawable.dot_normal);
views.get(position).setBackgroundResource(R.drawable.dot_focused);
oldposition = position;
}
@Override
public void onPageScrollStateChanged(int state) {
}
}
//viewpager的aderpter
private class viewpagerecommendAdapter extends PagerAdapter {
private Context mContext;
public viewpagerecommendAdapter(Context mContext) {
this.mContext = mContext;
}
@Override
public int getCount() {
return 5;
}
@Override
public Object instantiateItem(View container, int position) {
ImageView imageview = new ImageView(context);
Glide.with(mContext).load(addPinDaos.get(position).getPicUrl()).
override(getWidth(), 150).centerCrop().into(imageview);
((ViewPager) container).addView(imageview);
return imageview;
}
@Override
public void destroyItem(View container, int position, Object object) {
((ViewPager) container).removeView((View) object);
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public void restoreState(Parcelable arg0, ClassLoader arg1) {
}
@Override
public Parcelable saveState() {
return null;
}
@Override
public void startUpdate(View arg0) {
}
@Override
public void finishUpdate(View arg0) {
}
}
private class YuanDianRun implements Runnable {
@Override
public void run() {
synchronized (viewHolderOne.myViewPager) {
currentItem = (currentItem + 1) % 5;
// handler切換圖片
handler.obtainMessage().sendToTarget();
}
}
}
在介面卡中我們對ViewPager的進行了動畫的設定。//此動畫可以註釋不用
mport android.support.v4.view.ViewPager;
import android.view.View;
import com.nineoldandroids.view.ViewHelper;
/**
* viewpager的左右摺疊動畫
* Created by lwp940118 on 2016/11/26.
*/
public class LRZheDie implements ViewPager.PageTransformer{
@Override
public void transformPage(View page, float position) {
if (position < -1){
ViewHelper.setPivotX(page,page.getMeasuredWidth() * 0.5f);
ViewHelper.setPivotY(page,page.getMeasuredHeight() * 0.5f);
ViewHelper.setScaleX(page,1);
}else if (position <= 0){
ViewHelper.setPivotX(page,page.getMeasuredWidth());
ViewHelper.setPivotY(page,0);
ViewHelper.setScaleX(page,1+position);
}else if(position <= 1){
ViewHelper.setPivotX(page,0);
ViewHelper.setPivotY(page,0);
ViewHelper.setScaleX(page,1 - position);
}else {
ViewHelper.setPivotX(page,page.getMeasuredWidth() * 0.5f);
ViewHelper.setPivotY(page,page.getMeasuredHeight() * 0.5f);
ViewHelper.setScaleX(page,1);
}
}
}
我們自定義item的佈局介紹如下:
- item_recyclerview_tuijian_tou.xml的佈局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="wrap_content">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="150dp"
android:background="@color/baise">
<com.xyliwp.news.view.myview.MyViewPager
android:id="@+id/myViewPage_tuijian_tou"
android:layout_width="match_parent"
android:layout_height="match_parent">
</com.xyliwp.news.view.myview.MyViewPager>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="35dip"
android:layout_gravity="bottom"
android:background="#33000000"
android:gravity="center"
android:orientation="vertical">
<TextView
android:id="@+id/textview_Viewpager"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ipet"
android:textColor="#ffffff" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="3dip"
android:gravity="center">
<View
android:id="@+id/textview_tuijian_tou1"
style="@style/dot_style"
android:background="@drawable/dot_focused" />
<View
android:id="@+id/textview_tuijian_tou2"
style="@style/dot_style" />
<View
android:id="@+id/textview_tuijian_tou3"
style="@style/dot_style" />
<View
android:id="@+id/textview_tuijian_tou4"
style="@style/dot_style" />
<View
android:id="@+id/textview_tuijian_tou5"
style="@style/dot_style" />
</LinearLayout>
</LinearLayout>
</FrameLayout>
</LinearLayout>
- item_recyclerview_tuijian.xml的佈局
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="wrap_content">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:layout_marginLeft="5dp"
android:layout_marginBottom="5dp"
android:layout_marginRight="5dp"
>
<ImageView
android:id="@+id/android_image"
android:layout_width="100dp"
android:layout_height="60dp"
android:layout_marginRight="20dp"/>
<TextView
android:id="@+id/android_version"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp"
android:textStyle="bold"
android:layout_centerVertical="true"
android:layout_toRightOf="@id/android_image" />
</RelativeLayout>
</android.support.v7.widget.CardView>
- 在輪播圖的item中dot_style的佈局如下:
<style name="dot_style">
<item name="android:layout_width">5dp</item>
<item name="android:layout_height">5dp</item>
<item name="android:background">@drawable/dot_normal</item>
<item name="android:layout_marginLeft">1.5dp</item>
<item name="android:layout_marginRight">1.5dp</item>
</style>
- drawable中dot_focused.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval" >
<solid android:color="#aaFFFFFF" />
<corners android:radius="5dip" />
</shape>
- drawable中dot_normal.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval" >
<solid android:color="#33000000" />
<corners android:radius="5dip" />
</shape>
資料型別的儲存類定義如下:
/**
* Created by wenpengli on 2017/3/12.
*/
public class TuiJianMessage {
private String ctime;
private String title;
private String description;
private String picUrl;
private String url;
public String getCtime() {
return ctime;
}
public void setCtime(String ctime) {
this.ctime = ctime;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getPicUrl() {
return picUrl;
}
public void setPicUrl(String picUrl) {
this.picUrl = picUrl;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
@Override
public String toString() {
return "TuiJianMessage{" +
"ctime='" + ctime + '\'' +
", title='" + title + '\'' +
", description='" + description + '\'' +
", picUrl='" + picUrl + '\'' +
", url='" + url + '\'' +
'}';
}
}
對於 主介面的實現 ,由於這是專案中的一段,我也沒有寫demo,所以 它實現的是在Fragment中編寫的,因此 如果要編寫demo的話,自行處理即可,具體程式碼如下:
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.xyliwp.news.R;
import com.xyliwp.news.bean.TuiJianMessage;
import com.xyliwp.news.view.fragment.fragmentshouye.adapter.TuiJianRecyclerViewAdapter;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
/**
* Created by lwp940118 on 2016/12/1.
*/
public class FragmentTuiJian extends Fragment{
public static final String TAG = "FragmentTuiJian ------- ";
private View rootView;
private RecyclerView recyclerView_shouye_tuijian;
private SwipeRefreshLayout swipeRefreshLayout_shouye_tuijian;
private ArrayList<TuiJianMessage> tuiJianMessages = new ArrayList<>();
public static final String api = "https://api.tianapi.com/world/?" +
"key=你自己去天行申請的key &num=50";
private TuiJianRecyclerViewAdapter tuiJianRecyclerViewAdapter;
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
if (msg.what == 1){
Log.e(TAG,tuiJianMessages.size()+"===tuiJianMessages");
Log.e(TAG,tuiJianRecyclerViewAdapter.getItemCount()+"===tuiJianMessages");
tuiJianRecyclerViewAdapter.notifyDataSetChanged();
}
}
};
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initData();
}
/**
* 進行資料頁面載入
*/
private void initData(){
new Thread(new Runnable() {
@Override
public void run() {
try {
jiaZai();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
rootView = (View)inflater.inflate(R.layout.fragmentshouye_tuijian,container,false);
initView();
initOnClick();
return rootView;
}
private void initOnClick() {
//新增資料封信
swipeRefreshLayout_shouye_tuijian.setOnRefreshListener(new SwipeRefreshLayout.
OnRefreshListener(){
@Override
public void onRefresh() {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
tuiJianRecyclerViewAdapter.notifyDataSetChanged();
swipeRefreshLayout_shouye_tuijian.setRefreshing(false);
}
}, 2000);
}
});
}
private void initView(){
recyclerView_shouye_tuijian = (RecyclerView)rootView.
findViewById(R.id.recyclerview_shouye_tuijian);
swipeRefreshLayout_shouye_tuijian = (SwipeRefreshLayout)rootView.
findViewById(R.id.swipeRefreshlayout_shouye_tuijian);
recyclerView_shouye_tuijian.setHasFixedSize(true);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getContext());
GridLayoutManager gridLayoutManager = new
GridLayoutManager(getContext(),2);
gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
return 1;
}
});
recyclerView_shouye_tuijian.setLayoutManager(layoutManager);
tuiJianRecyclerViewAdapter = new TuiJianRecyclerViewAdapter(getContext(),tuiJianMessages);
recyclerView_shouye_tuijian.setAdapter(tuiJianRecyclerViewAdapter);
}
private void jiaZai() throws IOException {
OkHttpClient okHttpClient = new OkHttpClient();
FormBody.Builder builder = new FormBody.Builder();
builder.add("json", "true");
RequestBody body = builder.build();
Request request = new Request.Builder()
.url(api)
.post(body)
.build();
try {
Response response = okHttpClient.newCall(request).execute();
if (response.isSuccessful()) {
getNewsData(response.body().string());
} else {
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void getNewsData(String s){
tuiJianMessages.clear();
JSONObject jsonObject = null;
try {
jsonObject = new JSONObject(s);
JSONArray jsonArray = jsonObject.getJSONArray("newslist");
for (int i = 0; i < jsonArray.length();i++){
JSONObject jsonObject1 = jsonArray.getJSONObject(i);
TuiJianMessage tuiJianMessage = new TuiJianMessage();
tuiJianMessage.setCtime(jsonObject1.getString("ctime"));
tuiJianMessage.setTitle(jsonObject1.getString("title"));
String sq = jsonObject1.getString("picUrl".replace("\\",""));
tuiJianMessage.setPicUrl(sq.replaceAll("ss","").replace('_',(char)32).replace(" ",""));
tuiJianMessage.setUrl(jsonObject1.getString("url".replace("\\","")));
Log.e(TAG,tuiJianMessage.toString());
tuiJianMessages.add(tuiJianMessage);
}
} catch (JSONException e) {
e.printStackTrace();
}
handler.sendEmptyMessage(1);
}
}
對於主介面的XML如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.widget.SwipeRefreshLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
android:id="@+id/swipeRefreshlayout_shouye_tuijian">
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerview_shouye_tuijian"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="@color/dibu">
</android.support.v7.widget.RecyclerView>
</android.support.v4.widget.SwipeRefreshLayout>
</LinearLayout>
整個過程就此結束,然後我們就成功完成了RecyclerView巢狀ViewPager。實現了RecyclerView的複雜佈局。