溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

怎么在Android中實現(xiàn)一個輪播圖效果

發(fā)布時間:2020-12-22 16:03:40 來源:億速云 閱讀:691 作者:Leah 欄目:開發(fā)技術(shù)

本篇文章為大家展示了怎么在Android中實現(xiàn)一個輪播圖效果,內(nèi)容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。

1、程序啟動界面MainActivity

public class MainActivity extends AppCompatActivity implements ImageBannerFramLayout.FramLayoutLisenner{
  private ImageBannerFramLayout mGroup;
  private int[] ids = new int[] {
      R.drawable.i1,//圖片資源1
      R.drawable.i2,//圖片資源2
  };
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    //計算當前手機寬度
    DisplayMetrics displayMetrics = new DisplayMetrics();
    getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
    int width = displayMetrics.widthPixels;
    mGroup = (ImageBannerFramLayout) findViewById(R.id.image_group);
    mGroup.setLisenner(this);
    List<Bitmap> list = new ArrayList<>();
    for (int i = 0; i < ids.length; i++) {
      Bitmap bitmap = BitmapFactory.decodeResource(getResources(),ids[i]);
      list.add(bitmap);
    }
    mGroup.addBitmaps(list);
  }
 
  @Override
  public void chickImageIndex(int pos) {
    Toast.makeText(this,"索引值 = " + pos,Toast.LENGTH_SHORT).show();
  }
}

2、新建包view下面新建兩個類

1)新建ImageBarnnerViewGroup類繼承自ViewGroup

public class ImageBarnnerViewGroup extends ViewGroup {
  private int children;//我們View Group的子視圖總個數(shù)
  private int childwidth;//子視圖的寬度
  private int childheight;//子視圖的高度
 
  private int x;//此時的x的值代表的是第一次按下的位置的橫坐標,每一次移動過的過程中 移動之前的位置橫坐標
  private int index = 0;//代表名為每張圖片的索引
  private Scroller scroller;
 
  /**
   * 利用一個單擊變量開關(guān)進行判斷,離開屏幕的一瞬間判斷用戶的操作是點擊
   */
  private boolean isClick;//true的時候點擊事件,false的時候不是點擊事件
  private ImageBarnnerLister lister;
 
  private ImageBarnnerViewGroupLisnner barnnerViewGroupLisnner;
 
  public ImageBarnnerLister getLister() {
    return lister;
  }
 
  public void setLister(ImageBarnnerLister lister) {
    this.lister = lister;
  }
 
  public ImageBarnnerViewGroupLisnner getBarnnerViewGroupLisnner() {
    return barnnerViewGroupLisnner;
  }
  public void setBarnnerViewGroupLisnner(ImageBarnnerViewGroupLisnner barnnerViewGroupLisnner) {
    this.barnnerViewGroupLisnner = barnnerViewGroupLisnner;
  }
  public interface ImageBarnnerLister {
    void chickImageIndex(int pos);//pos代表的是我們當前的圖片的具體索引值
  }
  /**
   * 實現(xiàn)輪播圖底部圓點切換效果
   * 自定義一個繼承自FragmenLayou布局,利用FragmeLayout布局特性
   */
  
  //自動輪播
  private boolean isAuto = true;//默認情況下開啟輪播
  private Timer timer = new Timer();
  private TimerTask timerTask;
  
  @SuppressLint("HandlerLeak")
  private android.os.Handler autohandler = new android.os.Handler() {
    @Override
    public void handleMessage(Message msg) {
      switch (msg.what) {
        case 0://我們需要圖片的自動輪播
          if (++index >= children) {//如果是最后一張圖片,從第一張開始
            index = 0;
          }
          scrollTo(childwidth * index,0);
          barnnerViewGroupLisnner.selectImage(index);
          break;
        default:
      }
    }
  };
 
  private void startAuto() {
    isAuto = true;
 
  }
 
  private void stopAuto() {
    isAuto = false;
  }
 
  /**
   * 采用Timer,TimerTask,Handler三者結(jié)合的方式來實現(xiàn)自動輪播
   */
 
  public ImageBarnnerViewGroup(Context context) {
    super(context);
    initObj();
  }
 
  public ImageBarnnerViewGroup(Context context, AttributeSet attrs) {
    super(context, attrs);
    initObj();
  }
 
  public ImageBarnnerViewGroup(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
    super(context, attrs, defStyleAttr, defStyleRes);
    initObj();
  }
 
 
  private void initObj() {
    scroller = new Scroller(getContext());
 
    timerTask = new TimerTask() {
      @Override
      public void run() {
        if (isAuto) {//開啟輪播圖
          autohandler.sendEmptyMessage(0);
        }
      }
    };
    timer.schedule(timerTask,100,3000);
  }
 
  @Override
  public void computeScroll() {
    super.computeScroll();
    if (scroller.computeScrollOffset()) {
      scrollTo(scroller.getCurrX(),0);
      invalidate();//重繪
    }
  }
 
  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    //1.求出子視圖的個數(shù)
    children = getChildCount();//我們可以知道自試圖的個數(shù)
    if (0 == children)
    {
      setMeasuredDimension(0,0);
    } else {
      measureChildren(widthMeasureSpec, heightMeasureSpec);
      //此時我們以第一個子視圖=為基準,也就是說我們的View Group
      View view = getChildAt(0);
      childwidth = view.getMeasuredWidth();
      childheight = view.getMeasuredHeight();
      int width = view.getMeasuredWidth() * children;
      setMeasuredDimension(width,childheight);
    }
    //2.測量子視圖的寬度和高度
    //3.根據(jù)子視圖的狂賭和高度,求出該ViewGroup的寬度和高度
  }
 
  @Override
  public boolean onInterceptTouchEvent(MotionEvent ev) {
    return super.onInterceptTouchEvent(ev);
  }
  /**
   * 用兩種方式來實現(xiàn)輪播圖的手動輪播
   * 1,利用scrollTo,scrollBy 完成輪播圖的手動輪播
   * 1,利用Scroller 對象完成輪播圖的手動效果
   * @param event
   * @return
   */
 
  @Override
  public boolean onTouchEvent(MotionEvent event) {
    switch (event.getAction()) {
      case MotionEvent.ACTION_DOWN://表示用戶按下的一瞬間
        stopAuto();//停止圖片輪播
        if (!scroller.isFinished()) {
          scroller.abortAnimation();
        }
        isClick = true;
        x=(int)event.getX();
        break;
      case MotionEvent.ACTION_MOVE://表示用戶按下之后在屏幕上移動的過程
        int moveX = (int) event.getX();
        int distance = moveX - x;
        scrollBy(-distance,0);
        x = moveX;
        isClick = false;
        break;
      case MotionEvent.ACTION_UP://標識的是用戶抬起的一瞬間
        int scrollX = getScrollX();
        index = (scrollX + childwidth / 2) / childwidth;
        if (index < 0) {  //已經(jīng)滑動到了最左邊
          index = 0;
        } else if (index > children - 1) {//說明已經(jīng)滑動到了最右邊
          index = children - 1;
        }
 
        if (isClick) { //點擊事件
          lister.chickImageIndex(index);
        } else {
          int dx = index * childwidth - scrollX;
          scroller.startScroll(scrollX,0,dx,0);
          postInvalidate();
          barnnerViewGroupLisnner.selectImage(index);
        }
        startAuto();//開啟圖片輪播
        break;
      default:
    }
    return true;
    //返回true的目的是告訴該View Group容器的父View 我們已經(jīng)處理好了該事件
  }
 
  @Override
  protected void onLayout(boolean b, int i, int i1, int i2, int i3) {
    if (b) {
      int lefrMargin = 0;
      for (int j = 0; j < children; j++) {
        View view = getChildAt(j);
        view.layout(lefrMargin,0,lefrMargin + childwidth,childheight);
        lefrMargin += childwidth;
      }
    }
  }
 
  public interface ImageBarnnerViewGroupLisnner{
    void selectImage(int index);
  }
}

2)新建ImageBannerFramLayout類繼承自FrameLayout實現(xiàn)兩個接口

public class ImageBannerFramLayout extends FrameLayout implements ImageBarnnerViewGroup.ImageBarnnerViewGroupLisnner,ImageBarnnerViewGroup.ImageBarnnerLister{
 
  private ImageBarnnerViewGroup imageBarnnerViewGroup;
  private LinearLayout linearLayout;
 
  private FramLayoutLisenner lisenner;
 
  public FramLayoutLisenner getLisenner() {
    return lisenner;
  }
 
  public void setLisenner(FramLayoutLisenner lisenner) {
    this.lisenner = lisenner;
  }
 
  public ImageBannerFramLayout(@NonNull Context context) {
    super(context);
    initImageBarnnerViewGroup();
    initDotLinearlayout();
  }
 
 
 
  public ImageBannerFramLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
    initImageBarnnerViewGroup();
    initDotLinearlayout();
  }
 
  public ImageBannerFramLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    initImageBarnnerViewGroup();
    initDotLinearlayout();
  }
 
  public void addBitmaps(List<Bitmap> list) {
    for (int i = 0; i < list.size(); i++) {
      Bitmap bitmap = list.get(i);
      addBitmapToImageBarnnerViewGroup(bitmap);
      addDotToLinearlayout();
    }
  }
 
  private void addDotToLinearlayout() {
    ImageView iv = new ImageView(getContext());
    LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams
        (LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.MATCH_PARENT);
    layoutParams.setMargins(5,5,5,5);
    iv.setLayoutParams(layoutParams);
    iv.setImageResource(R.drawable.dot_normal);
    linearLayout.addView(iv);
  }
 
  private void addBitmapToImageBarnnerViewGroup(Bitmap bitmap) {
    ImageView imageView = new ImageView(getContext());
    imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
    imageView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT));
    imageView.setImageBitmap(bitmap);
    imageBarnnerViewGroup.addView(imageView);
  }
 
  //初始化自定義圖片輪播功能核心類
  private void initImageBarnnerViewGroup() {
    imageBarnnerViewGroup = new ImageBarnnerViewGroup(getContext());
    FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams
        (FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT);
    imageBarnnerViewGroup.setLayoutParams(layoutParams);
    imageBarnnerViewGroup.setBarnnerViewGroupLisnner(this);//將linsnner傳遞給Framlayout
    imageBarnnerViewGroup.setLister(this);
    addView(imageBarnnerViewGroup);
  }
 
  //初始化底部圓點布局
  private void initDotLinearlayout() {
    linearLayout = new LinearLayout(getContext());
    FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams
        (FrameLayout.LayoutParams.MATCH_PARENT, 40);
    linearLayout.setLayoutParams(layoutParams);
    linearLayout.setOrientation(LinearLayout.HORIZONTAL);
    linearLayout.setGravity(Gravity.CENTER);
 
    linearLayout.setBackgroundColor(Color.RED);
    addView(linearLayout);
 
    FrameLayout.LayoutParams layoutParams1 = (LayoutParams) linearLayout.getLayoutParams();
    layoutParams.gravity = Gravity.BOTTOM;
    linearLayout.setLayoutParams(layoutParams1);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
      linearLayout.setAlpha(0.5f);
    } else {
      linearLayout.getBackground().setAlpha(100);
    }
  }
 
 
  @Override
  public void selectImage(int index) {
    int count = linearLayout.getChildCount();
    for (int i = 0;i < count; i++) {
      ImageView iv = (ImageView) linearLayout.getChildAt(i);
      if (i == index) {
        iv.setImageResource(R.drawable.dot_select);
      } else {
        iv.setImageResource(R.drawable.dot_normal);
      }
    }
  }
 
  @Override
  public void chickImageIndex(int pos) {
    lisenner.chickImageIndex(pos);
  }
 
  public interface FramLayoutLisenner{
    void chickImageIndex(int pos);
  }
}

3、程序布局頁面activity_main

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  tools:context=".MainActivity">
  <com.example.tony.imagegroup.view.ImageBannerFramLayout
    android:id="@+id/image_group"
    android:layout_width="match_parent"
    android:layout_height="200dp">
  </com.example.tony.imagegroup.view.ImageBannerFramLayout>
</RelativeLayout>

4、新建兩個drawable資源文件dot_normal.xml和dot_select.xml,實現(xiàn)輪播圖底部小圓點

不同的是前者顏色為白色后者為黑色

<?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"/>
  <size android:height="10dp"
    android:width="10dp"/>
</shape>

上述內(nèi)容就是怎么在Android中實現(xiàn)一個輪播圖效果,你們學(xué)到知識或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識儲備,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI