<?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">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.example.app12.widget.BannerFlipper
android:id="@+id/bf_banner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
></com.example.app12.widget.BannerFlipper>
<TextView
android:id="@+id/tv_banner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=" 点击图片 "
android:layout_gravity="center"
android:textSize="17dp"
android:textColor="@color/black"/>
</LinearLayout>
</LinearLayout>
banner_flipper.xml ,定义ViewFlipper和RadioGroup,用于在BannerFlipper工具中定义横幅图片和圆点
<?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="match_parent"
android:orientation="vertical">
<ViewFlipper
android:id="@+id/vf_banner"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:flipInterval="3000"
android:layerType="software"></ViewFlipper>
<RadioGroup
android:id="@+id/rg_banner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="2dp"
android:orientation="horizontal"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"></RadioGroup>
</RelativeLayout>
drawable中的 indicator_selector.xml ,定义圆点,其中icon_point_n和icon_point_c为灰色圆点和红色圆点
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="false" android:drawable="@drawable/icon_point_n" />
<item android:state_checked="true" android:drawable="@drawable/icon_point_c" />
</selector>
anim包中定义了灰度动画和平移动画
push_left_in.xml,描述向左翻页时右边页面的移入行为
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:duration="1500" android:fromXDelta="100.0%p" android:toXDelta="0.0" />
<alpha android:duration="1500" android:fromAlpha="0.1" android:toAlpha="1.0" />
</set>
push_left_out.xml ,描述向左翻页时左边页面的移出行为
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:duration="1500" android:fromXDelta="0.0" android:toXDelta="-100.0%p" />
<alpha android:duration="1500" android:fromAlpha="1.0" android:toAlpha="0.1" />
</set>
类推,向右翻页时,就是fromXDelta和toXDelta变为相反数
package com.example.app12.widget;
import android.app.Activity;
import android.content.Context;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.LayoutParams;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.RelativeLayout;
import android.widget.ViewFlipper;
import com.example.app12.R;
import com.example.app12.util.Utils;
import java.util.ArrayList;
/**
* Created by Will.Shen on 2021/8/25.
*/
public class BannerFlipper extends RelativeLayout {
private String TAG = "BAnnerFlipper";
private Context mContext;
private ViewFlipper vf_banner2;
private RadioGroup rg_binner;
private int dip_15;
private GestureDetector mGesture;//手势检测器对象
private float mFlipGap = 20f;//触发飞掠事件的距离阈值
private LayoutInflater mInflater;
private int mcount = 0;
public BannerFlipper(Context context, AttributeSet attrs) {
super(context,attrs);
mContext = context;
initView();
}
//初始化试图
private void initView() {
Log.e(TAG,"----------initView-----------");
mInflater = ((Activity)mContext).getLayoutInflater();
View view = mInflater.inflate(R.layout.banner_flipper,null);
vf_banner2 = (ViewFlipper)view.findViewById(R.id.vf_banner);
rg_binner = (RadioGroup)view.findViewById(R.id.rg_banner);
addView(view);
dip_15 = Utils.dip2px(mContext,15);
mGesture = new GestureDetector(mContext,new BannerGestureListener());
}
public boolean dispatchTouchEvent(MotionEvent event) {
mGesture.onTouchEvent(event);
return true;
}
//定义手势检测监听器
final class BannerGestureListener implements GestureDetector.OnGestureListener {
@Override
public boolean onDown(MotionEvent e) {
return true;
}
@Override
public void onShowPress(MotionEvent e) {
}
//在点击时触发
@Override
public boolean onSingleTapUp(MotionEvent e) {
int position = vf_banner2.getDisplayedChild();
mListener.onBannerClick(position);
return true;
}
//在手势滑动的过程中触发
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
return false;
}
@Override
public void onLongPress(MotionEvent e) {
}
//手势飞快掠过时触发
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
if (e1.getX() - e2.getX() > mFlipGap) {//从右往左掠过
startFlip();
return true;
}
if (e1.getX() - e2.getX() < -mFlipGap) {//从左往右
backFlip();
return true;
}
return false;
}
}
private void startFlip() {
Log.e(TAG,"----------startFlip-----------");
vf_banner2.startFlipping();//开始轮播
vf_banner2.setInAnimation(AnimationUtils.loadAnimation(mContext, R.anim.push_left_in));
vf_banner2.setOutAnimation(AnimationUtils.loadAnimation(mContext, R.anim.push_left_out));
vf_banner2.getOutAnimation().setAnimationListener(new BannerAnimationListener(this));
vf_banner2.showNext();
}
private void backFlip() {
vf_banner2.startFlipping();
vf_banner2.setInAnimation(AnimationUtils.loadAnimation(mContext, R.anim.push_right_in));
vf_banner2.setOutAnimation(AnimationUtils.loadAnimation(mContext, R.anim.push_right_out));
vf_banner2.getOutAnimation().setAnimationListener(new BannerAnimationListener(this));
vf_banner2.showPrevious();
vf_banner2.setInAnimation(AnimationUtils.loadAnimation(mContext, R.anim.push_left_in));
vf_banner2.setOutAnimation(AnimationUtils.loadAnimation(mContext, R.anim.push_left_out));
vf_banner2.getOutAnimation().setAnimationListener(new BannerAnimationListener(this));
}
//设置飞掠试图的队列
public void setImage(ArrayList<Integer> imageList) {
Log.e(TAG,"----------setImage-----------");
for (int i = 0;i < imageList.size();i++) {
Log.e(TAG,"----------imageList-----------");
Integer imageID = ((Integer)imageList.get(i).intValue());
ImageView iv_item = new ImageView(mContext);
iv_item.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT));
iv_item.setScaleType(ImageView.ScaleType.FIT_XY);
iv_item.setImageResource(imageID);
vf_banner2.addView(iv_item);
}
mcount = imageList.size();
for (int i = 0;i < imageList.size();i++) {
RadioButton radio = new RadioButton(mContext);
radio.setLayoutParams(new RadioGroup.LayoutParams(dip_15,dip_15));
radio.setGravity(Gravity.CENTER);
radio.setButtonDrawable(R.drawable.indicator_selector);
rg_binner.addView(radio);
}
vf_banner2.setDisplayedChild(imageList.size()-1);
startFlip();
}
private BannerClickListener mListener;//声明横幅点击的监听器对象
public void setOnBannerListener(BannerClickListener listener) {
mListener = listener;
}
public interface BannerClickListener{//横幅点击的监听器
void onBannerClick(int position);
}
private class BannerAnimationListener implements Animation.AnimationListener { //设置圆点的监听器
private BannerAnimationListener(BannerFlipper bf) {
}
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {//设置圆点颜色变化
int position = vf_banner2.getDisplayedChild();
((RadioButton)rg_binner.getChildAt(position)).setChecked(true);
}
@Override
public void onAnimationRepeat(Animation animation) {
}
}
}
package com.example.app12;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.example.app12.util.DisplayUtil;
import com.example.app12.widget.BannerFlipper;
import java.util.ArrayList;
/**
* Created by Will.Shen on 2021/8/25.
*/
public class BannerActivity extends AppCompatActivity implements BannerFlipper.BannerClickListener {
private BannerFlipper bf_banner;
private TextView tv_banner;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_banner);
bf_banner = (BannerFlipper) findViewById(R.id.bf_banner);
tv_banner = (TextView) findViewById(R.id.tv_banner);
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) bf_banner.getLayoutParams();
params.height = (int) (DisplayUtil.getSreenWidth(this) * 250f/ 640f);
bf_banner.setLayoutParams(params);
ArrayList<Integer> imageArray = new ArrayList<>();
imageArray.add(Integer.valueOf(R.drawable.guide_bg1));
imageArray.add(Integer.valueOf(R.drawable.guide_bg2));
imageArray.add(Integer.valueOf(R.drawable.guide_bg3));
bf_banner.setImage(imageArray);
bf_banner.setOnBannerListener(this);
}
@Override
public void onBannerClick(int position) {
String desc = String.format("你点击了第%d张图",position);
tv_banner.setText(desc);
}
}
Utils
package com.example.app12.util;
import android.annotation.SuppressLint;
import android.content.Context;
import android.view.Menu;
import android.view.ViewConfiguration;
import android.view.Window;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* Created by ouyangshen on 2016/9/11.
*/
public class Utils {
//根据手机的分辨率从 dp 的单位 转成为 px(像素)
public static int dip2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
//根据手机的分辨率从 px(像素) 的单位 转成为 dp
public static int px2dip(Context context, float pxValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (pxValue / scale + 0.5f);
}
@SuppressLint("SimpleDateFormat")
public static String getNowDateTime(String format) {
SimpleDateFormat sdf = new SimpleDateFormat(format);
return sdf.format(new Date());
}
//如果设备有物理菜单按键,需要将其屏蔽才能显示OverflowMenu
//API18以下需要该函数在右上角强制显示选项菜单
public static void forceShowOverflowMenu(Context context) {
try {
ViewConfiguration config = ViewConfiguration.get(context);
Field menuKeyField = ViewConfiguration.class.
getDeclaredField("sHasPermanentMenuKey");
if (menuKeyField != null) {
menuKeyField.setAccessible(true);
menuKeyField.setBoolean(config, false);
}
} catch (Exception e) {
e.printStackTrace();
}
}
// 显示OverflowMenu的Icon
public static void setOverflowIconVisible(int featureId, Menu menu) {
// ActionBar的featureId是8,Toolbar的featureId是108
if (featureId % 100 == Window.FEATURE_ACTION_BAR && menu != null) {
if (menu.getClass().getSimpleName().equals("MenuBuilder")) {
try {
Method m = menu.getClass().getDeclaredMethod(
"setOptionalIconsVisible", Boolean.TYPE);
m.setAccessible(true);
m.invoke(menu, true);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
DisplayUtils
package com.example.app12.util;
import android.content.Context;
import android.util.DisplayMetrics;
import android.view.WindowManager;
/**
* Created by ouyangshen on 2016/9/11.
*/
public class DisplayUtil {
public static int getSreenWidth(Context ctx) {
WindowManager wm = (WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics dm = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(dm);
return dm.widthPixels;
}
public static int getSreenHeight(Context ctx) {
WindowManager wm = (WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics dm = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(dm);
return dm.heightPixels;
}
public static float getSreenDensity(Context ctx) {
WindowManager wm = (WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics dm = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(dm);
return dm.density;
}
}