android 轮播图手动循环滑动+自动循环滑动

一个可以手动滑动和自动滑动的轮播图效果。

文章后面会嵌入源码。

效果图;

package com.adtest;


import net.tsz.afinal.FinalBitmap;
import android.app.Activity;
import android.os.Bundle;
import android.widget.LinearLayout;
import android.widget.Toast;


import com.tianshicoffeeom.adutil.MyAdGallery;
import com.tianshicoffeeom.adutil.MyAdGallery.MyOnItemClickListener;


public class MainActivity extends Activity {
private MyAdGallery gallery; // 广告控件
LinearLayout ovalLayout; // 圆点容器
/** 图片id的数组,本地测试用 */
private int[] imageId = new int[] { R.drawable.img01, R.drawable.img02,
R.drawable.img03, R.drawable.img04 };


// /** 图片网络路径数组 */
// private String[] mris = {
// "https://img-my.csdn.net/uploads/201312/14/1386989803_3335.PNG",
// "https://img-my.csdn.net/uploads/201312/14/1386989613_6900.jpg",
// "https://img-my.csdn.net/uploads/201312/14/1386989802_7236.PNG" };


@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
FinalBitmap.create(this); // android 框架 这里用于加载网络图片 ,
gallery = (MyAdGallery) findViewById(R.id.adgallery); // 获取Gallery组件
ovalLayout = (LinearLayout) findViewById(R.id.ovalLayout);// 获取圆点容器
// 第二和第三参数 2选1 ,参数2为 图片网络路径数组 ,参数3为图片id的数组,本地测试用 ,2个参数都有优先采用 参数2
gallery.start(this, null, imageId, 3000, ovalLayout,
R.drawable.dot_focused, R.drawable.dot_normal);
gallery.setMyOnItemClickListener(new MyOnItemClickListener() {
public void onItemClick(int curIndex) {
Toast.makeText(MainActivity.this, "点击的图片下标为:" + curIndex,
Toast.LENGTH_SHORT).show();
// System.out.println(curIndex);
}
});


}


@Override
protected void onStop() {
gallery.stopTimer();
super.onStop();
}


@Override
protected void onRestart() {
gallery.startTimer();
super.onRestart();
}
}

//  自定义Gallery类

package com.tianshicoffeeom.adutil;


import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;


import net.tsz.afinal.FinalBitmap;
import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.Gallery;
import android.widget.ImageView;
import android.widget.LinearLayout;


/**
 * 无限滚动广告栏组件
 */
@SuppressWarnings("deprecation")
public class MyAdGallery extends Gallery implements
android.widget.AdapterView.OnItemClickListener,
android.widget.AdapterView.OnItemSelectedListener, OnTouchListener {
/** 显示的Activity */
private Context mContext;
/** 条目单击事件接口 */
private MyOnItemClickListener mMyOnItemClickListener;
/** 图片切换时间 */
private int mSwitchTime;
/** 自动滚动的定时器 */
private Timer mTimer;
/** 圆点容器 */
private LinearLayout mOvalLayout;
/** 当前选中的数组索引 */
private int curIndex = 0;
/** 上次选中的数组索引 */
private int oldIndex = 0;
/** 圆点选中时的背景ID */
private int mFocusedId;
/** 圆点正常时的背景ID */
private int mNormalId;
/** 图片资源ID组 */
private int[] mAdsId;
/** 图片网络路径数组 */
private String[] mUris;
/** ImageView组 */
List<ImageView> listImgs;


public MyAdGallery(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}


public MyAdGallery(Context context) {
super(context);
}


public MyAdGallery(Context context, AttributeSet attrs) {
super(context, attrs);
}


/**
* @param context
*            显示的Activity ,不能为null
* @param mris
*            图片的网络路径数组 ,为空时 加载 adsId
* @param adsId
*            图片组资源ID ,测试用
* @param switchTime
*            图片切换时间 写0 为不自动切换
* @param ovalLayout
*            圆点容器 ,可为空
* @param focusedId
*            圆点选中时的背景ID,圆点容器可为空写0
* @param normalId
*            圆点正常时的背景ID,圆点容器为空写0
*/
public void start(Context context, String[] mris, int[] adsId,
int switchTime, LinearLayout ovalLayout, int focusedId, int normalId) {
this.mContext = context;
this.mUris = mris;
this.mAdsId = adsId;
this.mSwitchTime = switchTime;
this.mOvalLayout = ovalLayout;
this.mFocusedId = focusedId;
this.mNormalId = normalId;
ininImages();// 初始化图片组
setAdapter(new AdAdapter());
this.setOnItemClickListener(this);
this.setOnTouchListener(this);
this.setOnItemSelectedListener(this);
this.setSoundEffectsEnabled(false);
this.setAnimationDuration(700); // 动画时间
this.setUnselectedAlpha(1); // 未选中项目的透明度
// 不包含spacing会导致onKeyDown()失效!!! 失效onKeyDown()前先调用onScroll(null,1,0)可处理
setSpacing(0);
// 取靠近中间 图片数组的整倍数
setSelection((getCount() / 2 / listImgs.size()) * listImgs.size()); // 默认选中中间位置为起始位置
setFocusableInTouchMode(true);
initOvalLayout();// 初始化圆点
startTimer();// 开始自动滚动任务
}


/** 初始化图片组 */
private void ininImages() {
listImgs = new ArrayList<ImageView>(); // 图片组
int len = mUris != null ? mUris.length : mAdsId.length;
for (int i = 0; i < len; i++) {
ImageView imageview = new ImageView(mContext); // 实例化ImageView的对象
imageview.setScaleType(ImageView.ScaleType.FIT_XY); // 设置缩放方式
imageview.setLayoutParams(new Gallery.LayoutParams(
Gallery.LayoutParams.MATCH_PARENT,
Gallery.LayoutParams.MATCH_PARENT));
if (mUris == null) {// 本地加载图片
imageview.setImageResource(mAdsId[i]); // 为ImageView设置要显示的图片
} else { // 网络加载图片
FinalBitmap.create(mContext)
.display(imageview, mUris[i], imageview.getWidth(),
imageview.getHeight(), null, null, true);
}
listImgs.add(imageview);
}


}


/** 初始化圆点 */
private void initOvalLayout() {
if (mOvalLayout != null && listImgs.size() < 2) {// 如果只有一第图时不显示圆点容器
mOvalLayout.getLayoutParams().height = 0;
} else if (mOvalLayout != null) {
// 圆点的大小是 圆点窗口的 70%;
int Ovalheight = (int) (mOvalLayout.getLayoutParams().height * 0.7);
// 圆点的左右外边距是 圆点窗口的 20%;
int Ovalmargin = (int) (mOvalLayout.getLayoutParams().height * 0.2);
android.widget.LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
Ovalheight, Ovalheight);
layoutParams.setMargins(Ovalmargin, 0, Ovalmargin, 0);
for (int i = 0; i < listImgs.size(); i++) {
View v = new View(mContext); // 员点
v.setLayoutParams(layoutParams);
v.setBackgroundResource(mNormalId);
mOvalLayout.addView(v);
}
// 选中第一个
mOvalLayout.getChildAt(0).setBackgroundResource(mFocusedId);
}
}


/** 无限循环适配器 */
class AdAdapter extends BaseAdapter {
@Override
public int getCount() {
if (listImgs.size() < 2)// 如果只有一张图时不滚动
return listImgs.size();
return Integer.MAX_VALUE;
}


@Override
public View getView(int position, View convertView, ViewGroup parent) {
return listImgs.get(position % listImgs.size()); // 返回ImageView
}


@Override
public Object getItem(int position) {
return null;
}


@Override
public long getItemId(int position) {
return position;
}
}


public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
int kEvent;
if (isScrollingLeft(e1, e2)) { // 检查是否往左滑动
kEvent = KeyEvent.KEYCODE_DPAD_LEFT;
} else { // 检查是否往右滑动
kEvent = KeyEvent.KEYCODE_DPAD_RIGHT;
}
onKeyDown(kEvent, null);
return true;


}


/** 检查是否往左滑动 */
private boolean isScrollingLeft(MotionEvent e1, MotionEvent e2) {
return e2.getX() > (e1.getX() + 50);
}


@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
float distanceY) {
return super.onScroll(e1, e2, distanceX, distanceY);
}


@Override
public boolean onTouch(View v, MotionEvent event) {
if (MotionEvent.ACTION_UP == event.getAction()
|| MotionEvent.ACTION_CANCEL == event.getAction()) {
startTimer();// 开始自动滚动任务
} else {
stopTimer();// 停止自动滚动任务
}
return false;
}


/** 图片切换事件 */
@Override
public void onItemSelected(AdapterView<?> arg0, View arg1, int position,
long arg3) {
curIndex = position % listImgs.size();
if (mOvalLayout != null && listImgs.size() > 1) { // 切换圆点
mOvalLayout.getChildAt(oldIndex).setBackgroundResource(mNormalId); // 圆点取消
mOvalLayout.getChildAt(curIndex).setBackgroundResource(mFocusedId);// 圆点选中
oldIndex = curIndex;
}
}


@Override
public void onNothingSelected(AdapterView<?> arg0) {
}


/** 项目点击事件 */
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int position,
long arg3) {
if (mMyOnItemClickListener != null) {
mMyOnItemClickListener.onItemClick(curIndex);
}
}


/** 设置项目点击事件监听器 */
public void setMyOnItemClickListener(MyOnItemClickListener listener) {
mMyOnItemClickListener = listener;
}


/** 项目点击事件监听器接口 */
public interface MyOnItemClickListener {
/**
* @param curIndex
*            //当前条目在数组中的下标
*/
void onItemClick(int curIndex);
}


/** 停止自动滚动任务 */
public void stopTimer() {
if (mTimer != null) {
mTimer.cancel();
mTimer = null;
}
}


/** 开始自动滚动任务 图片大于1张才滚动 */
public void startTimer() {
if (mTimer == null && listImgs.size() > 1 && mSwitchTime > 0) {
mTimer = new Timer();
mTimer.schedule(new TimerTask() {
public void run() {
handler.sendMessage(handler.obtainMessage(1));
}
}, mSwitchTime, mSwitchTime);
}
}


/** 处理定时滚动任务 */
@SuppressLint("HandlerLeak")
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
// 不包含spacing会导致onKeyDown()失效!!!
// 失效onKeyDown()前先调用onScroll(null,1,0)可处理
onScroll(null, null, 1, 0);
onKeyDown(KeyEvent.KEYCODE_DPAD_RIGHT, null);
}
};
}

源码下载地址icon-default.png?t=N7T8http://download.csdn.net/detail/u013752594/8897911

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Android Studio中,实现轮播图循环播放通常会使用到库如Glide、Volley、Picasso或Android自身的RecyclerView结合Adapter来展示图片,并配合ViewFlipper、ViewPager或Lottie等组件来实现动画效果。以下是一个简单的步骤: 1. **添加依赖**: 使用Gradle添加一个轮播图库依赖,比如`androidx.recyclerview:recyclerview:1.2.1`(RecyclerView)和`com.github.bumptech.glide:glide:4.12.0`(Glide)。 2. **创建布局**: 创建一个包含RecyclerView的布局文件,RecyclerView作为轮播容器。 ```xml <androidx.recyclerview.widget.RecyclerView android:id="@+id/scroll_view" android:layout_width="match_parent" android:layout_height="wrap_content" /> ``` 3. **设置Adapter**: 为RecyclerView创建一个自定义的Adapter,其中包含轮播的图片列表。 ```java public class SlideAdapter extends RecyclerView.Adapter<SlideAdapter.MyViewHolder> { private List<String> images; // ... 其他构造函数和方法 @NonNull @Override public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View itemView = LayoutInflater.from(parent.getContext()) .inflate(R.layout.slide_item, parent, false); return new MyViewHolder(itemView); } // ... 填充视图,处理点击事件和设置轮播逻辑 class MyViewHolder extends RecyclerView.ViewHolder { ImageView slideImageView; MyViewHolder(@NonNull View itemView) { super(itemView); slideImageView = itemView.findViewById(R.id.slide_image_view); } } // ... 实现滚动到下一个图片的逻辑 public void setNextImage() { if (position < images.size() - 1) { position++; } else { position = 0; // 循环开始 } notifyItemChanged(position); // 刷新当前项 } } ``` 4. **轮播逻辑**: 在你的Activity或Fragment中设置Adapter并处理滑动事件,使其在用户滑动自动切换到下一个图片。 ```java SlideAdapter adapter = new SlideAdapter(yourImageList); recyclerView.setAdapter(adapter); recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); if (dy > 0) { // 用户上滑 adapter.setNextImage(); } } }); ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值