Android轮播图封装,下拉刷新相结合
Posted 星火燎原2016
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android轮播图封装,下拉刷新相结合相关的知识,希望对你有一定的参考价值。
- 自定义轮播图CarouselView
- 自定义下拉刷新PullRefreshListView
马上就要正式做毕业设计了,一些零碎时间写其中的一个模块,现记录下来,以备以后忘记时使用。欢迎大神不吝纠正。
效果图:
layout_carousel.xml
<?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">
<android.support.v4.view.ViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="250dp">
</android.support.v4.view.ViewPager>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignBottom="@id/viewPager"
android:background="#55000000"
android:orientation="vertical"
android:padding="10dp">
<TextView
android:id="@+id/tv_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:textColor="#fff" />
<LinearLayout
android:id="@+id/dot_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:gravity="center_horizontal"
android:orientation="horizontal">
</LinearLayout>
</LinearLayout>
</RelativeLayout>
carousel_dot_selected.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@android:color/white" />
</shape>
carousel_dot_unselect.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="#77000000" />
</shape>
carousel_dot_selector.xml (轮播图指示点选择器)
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/carousel_dot_selected" android:state_enabled="true" />
<item android:drawable="@drawable/carousel_dot_unselect" android:state_enabled="false" />
</selector>
轮播图数据bean
package com.xing.carousel;
/**
* Created by Administrator on 2016/3/22.
*/
public class CarouselData {
private int id;
private String title;
private int resId;
public CarouselData(int id, String title, int resId) {
this.id = id;
this.title = title;
this.resId = resId;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public int getResId() {
return resId;
}
public void setResId(int resId) {
this.resId = resId;
}
@Override
public String toString() {
return "CarouselData{" +
"id=" + id +
", title=‘" + title + ‘\‘‘ +
", resId=" + resId +
‘}‘;
}
}
自定义轮播图CarsouselView.java
package com.xing.carousel;
import android.content.Context;
import android.graphics.Color;
import android.os.Handler;
import android.os.Message;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Administrator on 2016/3/22.
*/
public class CarouselView extends LinearLayout {
private Context context;
private List<CarouselData> carouselDataList;
private ViewPager viewPager;
private TextView tv_title;
private LinearLayout dotLayout;
private List<View> dotList; //指示点
private static final int MSG_UPDATE = 1;
private Handler handler;
public CarouselView(Context context) {
this(context, null);
}
public CarouselView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
init();
}
private void init() {
LayoutInflater.from(context).inflate(R.layout.layout_carousel, this, true);
initView();
initData();
}
private void initData() {
dotList = new ArrayList<>();
}
private void initView() {
viewPager = (ViewPager) findViewById(R.id.viewPager);
tv_title = (TextView) findViewById(R.id.tv_title);
dotLayout = (LinearLayout) findViewById(R.id.dot_layout);
}
public void start(List<CarouselData> carouselDataList) {
this.carouselDataList = carouselDataList;
if (this.carouselDataList == null || this.carouselDataList.size() < 1) {
return;
}
View view = null;
LayoutParams params = new LayoutParams(5, 5);
//根据轮播图要显示的数量来创建指示点的个数
for (int i = 0; i < this.carouselDataList.size(); i++) {
view = new View(context);
//设置dot的宽和高,相当于在xml中设置layout_height和layout_width
if (i != 0) { //设置左边距
params.leftMargin = 5;
}
view.setLayoutParams(params);
view.setBackgroundResource(R.drawable.carousel_dot_selector);
dotList.add(view); //加入到list集合中
dotLayout.addView(view); //加入父布局
}
viewPager.setAdapter(new MyPagerAdapter());
viewPager.setOnPageChangeListener(new MyPagerChangeListener());
updateTitleDot();
if (handler == null) {
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case MSG_UPDATE:
int currentItem = viewPager.getCurrentItem();
if (currentItem < CarouselView.this.carouselDataList.size() - 1) { //从0开始
currentItem++;
} else {
currentItem = 0;
}
viewPager.setCurrentItem(currentItem);
handler.sendEmptyMessageDelayed(MSG_UPDATE, 2000);
break;
}
}
};
handler.sendEmptyMessageDelayed(MSG_UPDATE, 2000);
}
}
class MyPagerAdapter extends PagerAdapter {
@Override
public int getCount() {
return carouselDataList.size();
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public Object instantiateItem(ViewGroup container, final int position) {
final CarouselData carouselData = carouselDataList.get(position);
ImageView imageView = new ImageView(context);
imageView.setImageResource(carouselData.getResId());
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
container.addView(imageView);
imageView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
clickCallback.onClick(carouselData.getId(), position);
}
});
return imageView;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
}
class MyPagerChangeListener implements ViewPager.OnPageChangeListener {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
updateTitleDot();
}
@Override
public void onPageScrollStateChanged(int state) {
}
}
private void updateTitleDot() {
int currentPosition = viewPager.getCurrentItem() % carouselDataList.size();
CarouselData carouselData = carouselDataList.get(currentPosition);
tv_title.setText(carouselData.getTitle());
for (int i = 0; i < carouselDataList.size(); i++) {
dotLayout.getChildAt(i).setEnabled(i == currentPosition);
}
}
ClickCallback clickCallback;
interface ClickCallback {
void onClick(int id, int position);
}
public void setClickCallback(ClickCallback clickCallback) {
this.clickCallback = clickCallback;
}
}
圆形进度条
progressbar_rotate.xml
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="360">
<shape
android:innerRadius="12dp"
android:shape="ring"
android:thickness="3dp"
android:useLevel="false">
<!--android:useLevel="false"用于禁止progressbar自己转圈,自己在外层套一个rotate,用于转圈-->
<gradient
android:centerColor="@color/progressbar_center_color"
android:endColor="@color/progressbar_end_color"
android:startColor="@color/progressbar_start_color" />
</shape>
</rotate>
下拉刷新控件
1.ListView头布局
layout_pull_listview_header.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="horizontal">
<!--android:padding不能使用,因为该布局将会以addHeaderview方式添加到listview,可用margin代替。-->
<FrameLayout
android:id="@+id/fl_progressbar_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp">
<ProgressBar
android:id="@+id/pb_refresh"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:indeterminateDrawable="@drawable/progressbar_rotate"
android:visibility="invisible" />
<ImageView
android:id="@+id/iv_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@mipmap/ic_pulltorefresh_arrow" />
</FrameLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:gravity="center_horizontal"
android:orientation="vertical">
<TextView
android:id="@+id/tv_listview_top_tip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"
android:text="正在刷新"
android:textColor="@color/colorPrimary" />
<TextView
android:id="@+id/tv_listview_top_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"
android:text="最新刷新时间 2016-3-13"
android:textColor="@color/colorPrimary" />
</LinearLayout>
</LinearLayout>
ListView底部布局
layout_pull_listview_footer.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal">
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:layout_marginTop="5dp"
android:indeterminateDrawable="@drawable/progressbar_rotate" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:layout_marginLeft="10dp"
android:layout_marginTop="5dp"
android:text="@string/loading_more" />
</LinearLayout>
PullRefreshListView.java
package com.xing.carousel;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.RotateAnimation;
import android.widget.AbsListView;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import java.util.Date;
/**
* Created by Administrator on 2016/3/19.
*/
public class PullRefreshListView extends ListView implements AbsListView.OnScrollListener {
private Context context;
private View headerView;
private final int STATE_PULL_REFRESH = 0;
private final int STATE_RELEASE_REFRESH = 1;
private final int STATE_REFRESHING = 2;
private int currentState = STATE_PULL_REFRESH;
private TextView mRefreshStatusTip;
private TextView mRefreshTime;
private ProgressBar mProgressBar;
private ImageView mArrowImg;
private int headerViewHeight;
private int startY = -1; //初始值
private RotateAnimation upAnimation;
private RotateAnimation downAnimation;
private View footerView;
private int footerViewHeight;
public PullRefreshListView(Context context) {
this(context, null);
}
public PullRefreshListView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
context = getContext();
initView();
initData();
}
private void initData() {
//初始化头布局
headerView.measure(0, 0);
//得到头布局高度
headerViewHeight = headerView.getMeasuredHeight();
//设置上边距,隐藏头布局
headerView.setPadding(0, -headerViewHeight, 0, 0);
//将头布局添加至listView中
this.addHeaderView(headerView, null, false); //头布局selectable=false
//初始化底部布局数据
footerView.measure(0, 0);
footerViewHeight = footerView.getMeasuredHeight();
footerView.setPadding(0, 0, 0, -footerViewHeight);
this.addFooterView(footerView, null, false);
//初始化动画
initAnimation();
}
private void initView() {
//初始化listView头布局
headerView = View.inflate(context, R.layout.layout_pull_listview_header, null);
mProgressBar = (ProgressBar) headerView.findViewById(R.id.pb_refresh);
mArrowImg = (ImageView) headerView.findViewById(R.id.iv_arrow);
mRefreshStatusTip = (TextView) headerView.findViewById(R.id.tv_listview_top_tip);
mRefreshTime = (TextView) headerView.findViewById(R.id.tv_listview_top_time);
//初始化底部布局
footerView = View.inflate(context, R.layout.layout_pull_listview_footer, null);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
startY = (int) event.getRawY();
break;
case MotionEvent.ACTION_MOVE:
//如果当前正在刷新,则不处理
if (currentState == STATE_REFRESHING) {
break;
}
if (startY == -1) {
startY = (int) event.getRawY(); //保证startY有值
}
int deltaY = (int) (event.getRawY() - startY); //手指移动的偏移量
if (deltaY > 0 && getFirstVisiblePosition() == 0) { //只有手指向下滑动(deltaY>0)并且第一个item为可见的时候,才下拉刷新
int paddingTop = -headerViewHeight + deltaY;
headerView.setPadding(0, paddingTop, 0, 0); //将更新的padding设置给headerview,实时更新下拉布局的位置
if (paddingTop > 0 && currentState != STATE_RELEASE_REFRESH) {
currentState = STATE_RELEASE_REFRESH;
mArrowImg.startAnimation(upAnimation);
} else if (paddingTop < 0 && currentState != STATE_PULL_REFRESH) {
currentState = STATE_PULL_REFRESH;
mArrowImg.startAnimation(downAnimation);
}
return true; //拦截move事件,不让listview处理
}
break;
case MotionEvent.ACTION_UP:
startY = -1; //重置
if (currentState == STATE_PULL_REFRESH) { //手指抬起时,如果当前状态是下拉刷新,则直接隐藏头布局。
headerView.setPadding(0, -headerViewHeight, 0, 0);
} else if (currentState == STATE_RELEASE_REFRESH) { //手指抬起时,如果当前状态是松开刷新,则进入正在刷新状态
currentState = STATE_REFRESHING;
//显示正在刷新状态
headerView.setPadding(0, 0, 0, 0);
//更新当前状态
refreshHeaderState(currentState);
//监听回调
if (onRefreshListener != null) {
onRefreshListener.onRefresh();
}
}
break;
}
return super.onTouchEvent(event);
}
private void refreshHeaderState(int currentState) {
switch (currentState) {
case STATE_PULL_REFRESH:
mRefreshStatusTip.setText(getResources().getString(R.string.state_pull_refresh));
mArrowImg.setVisibility(View.VISIBLE);
mProgressBar.setVisibility(View.INVISIBLE);
break;
case STATE_RELEASE_REFRESH:
mRefreshStatusTip.setText(getResources().getString(R.string.state_release_refresh));
mArrowImg.setVisibility(View.VISIBLE);
mProgressBar.setVisibility(View.INVISIBLE);
break;
case STATE_REFRESHING:
mRefreshStatusTip.setText(getResources().getString(R.string.state_refreshing));
mArrowImg.clearAnimation(); //清除动画才能设置其可见性
mArrowImg.setVisibility(View.INVISIBLE);
mProgressBar.setVisibility(View.VISIBLE);
mRefreshTime.setText(getResources().getString(R.string.last_refresh_time));
break;
}
}
private void initAnimation() {
//向上旋转动画
upAnimation = new RotateAnimation(0, -180, RotateAnimation.RELATIVE_TO_SELF, 0.5f,
RotateAnimation.RELATIVE_TO_SELF, 0.5f);
upAnimation.setDuration(300);
upAnimation.setFillAfter(true);
//向下旋转动画
downAnimation = new RotateAnimation(-180, -360, RotateAnimation.RELATIVE_TO_SELF, 0.5f,
RotateAnimation.RELATIVE_TO_SELF, 0.5f);
downAnimation.setDuration(300);
downAnimation.setFillAfter(true);
}
/**
* 重置headerview中的刷新状态和progressbar的显示
*/
public void resetHeaderFooterView() {
currentState = STATE_PULL_REFRESH;
mRefreshStatusTip.setText(getResources().getString(R.string.state_pull_refresh));
mArrowImg.setVisibility(View.VISIBLE);
mProgressBar.setVisibility(View.INVISIBLE);
}
interface OnRefreshListener {
void onRefresh();
void loadMore(); //加载更多,通过listview的滚动监听实现
}
OnRefreshListener onRefreshListener;
public void setOnRefreshListener(OnRefreshListener onRefreshListener) {
this.onRefreshListener = onRefreshListener;
}
/**
* ListView的滑动监听
*
* @param view
* @param scrollState
*/
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (scrollState == OnScrollListener.SCROLL_STATE_FLING || scrollState == OnScrollListener.SCROLL_STATE_IDLE) {
if (getLastVisiblePosition() == getCount() - 1) { //滑动到最后一条,显示tooterView
footerView.setPadding(0, 0, 0, 0);
setSelection(getCount() - 1); //将最后一条拉到屏幕中显示,这样,footerview就可以显示出来了,否则,footerview需要再次滑动才能显示在屏幕中
}
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
}
}
新建Android Project 测试demo
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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="com.xing.carousel.MainActivity">
<com.xing.carousel.PullRefreshListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
轮播图作为头布局添加到PullRefreshListView中
layout_header.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.xing.carousel.CarouselView
android:id="@+id/carsouelView"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
MainActivity.java
package com.xing.carousel;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private CarouselView carouselView;
private List<CarouselData> carouselDataList;
private PullRefreshListView listView;
private int[] resIds = {R.mipmap.ic_launcher, R.mipmap.top2, R.mipmap.back2};
private List<String> data;
private View headerView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (PullRefreshListView) findViewById(R.id.listView);
headerView = View.inflate(this, R.layout.layout_header, null);
carouselView = (CarouselView) headerView.findViewById(R.id.carsouelView);
carouselDataList = new ArrayList<>();
for (int i = 0; i < resIds.length; i++) {
carouselDataList.add(new CarouselData(i, "标题" + i, resIds[i]));
}
carouselView.start(carouselDataList);
data = new ArrayList<>();
for (int i = 0; i < 10; i++) {
data.add("ListView---->" + i);
}
listView.addHeaderView(headerView);
listView.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, data));
carouselView.setClickCallback(new CarouselView.ClickCallback() {
@Override
public void onClick(int id, int position) {
Toast.makeText(MainActivity.this, "你点击了第" + position + "项", Toast.LENGTH_SHORT).show();
}
});
}
}
以上是关于Android轮播图封装,下拉刷新相结合的主要内容,如果未能解决你的问题,请参考以下文章