Android自定义控件:广告条效果

一、效果展示

<iframe allowfullscreen="true" data-mediaembed="bilibili" id="cu3TyYH0-1616760405861" src="https://player.bilibili.com/player.html?aid=289784656"></iframe>

Android自定义控件:广告栏效果

二、ListView和ViewPager的使用步骤

(1)ListView的使用

  1. 在布局文件中定义ListView
  2. 在代码中实例化ListView
  3. 准备数据
  4. 设置适配器–item布局–绑定数据

(2)ViewPager的使用

  1. 在布局文件中定义ViewPager
  2. 在代码中实例化ViewPager
  3. 准备数据
  4. 设置适配器(PagerAdapter)–item布局–绑定数据

三、广告条效果

(1)activity_guanggaotiao.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="match_parent">

<!--    定义一个ViewPager-->
    <androidx.viewpager.widget.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="180dp" />

    <LinearLayout
        android:background="#44000000"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:padding="5dp"
        android:layout_alignBottom="@id/viewpager">

<!--        设置标题-->
        <TextView
            android:id="@+id/tv_title"
            android:layout_gravity="center_horizontal"
            android:padding="3dp"
            android:text="这是一个TextView"
            android:textColor="#ffffff"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>

<!--        用来安放滑动的点-->
        <LinearLayout
            android:id="@+id/ll_point_group"
            android:layout_gravity="center_horizontal"
            android:orientation="horizontal"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>

    </LinearLayout>

</RelativeLayout>

(2)Guanggaotiao.java文件

package com.swpuiot.test;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;

import java.util.ArrayList;

public class Guanggaotiao extends AppCompatActivity {

    //设置一个标签
    private static final String TAG = Guanggaotiao.class.getSimpleName();

    //定义布局文件中需要用到的变量
    private ViewPager viewPager;
    private TextView tv_title;
    private LinearLayout ll_point_group;

    //定义图片列表
    private ArrayList<ImageView> imageViews;

    //图片资源id
    private final int[] imageIds = {
            R.drawable.a,
            R.drawable.b,
            R.drawable.c,
            R.drawable.d,
            R.drawable.e
    };
    //图片标题集合
    private final String[] imageDescriptions = {
            "风景美如画",
            "桂林山水甲天下",
            "阳朔山水甲桂林",
            "行千里致广大",
            "绿水青山就是金山银山"
    };

    //上一次圆点高亮显示的位置
    private int prePosition = 0;

    //是否已经滚动
    private boolean isDragging= false;

    //利用handler让子线程延迟4秒通知主线程更新ui到ViewPager的下一张图片
    private Handler handler = new Handler(){
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);

            int item = viewPager.getCurrentItem()+1;
            viewPager.setCurrentItem(item);

            //延迟发消息
            handler.sendEmptyMessageDelayed(0,4000);
        }
    };

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_guanggaotiao);

        //将系统自带的标题栏去掉
        ActionBar actionBar = getSupportActionBar();
        actionBar.hide();

        //调用实例化布局控件的方法
        initView();

        //实例化图片列表
        imageViews = new ArrayList<>();
        for (int i = 0; i < imageIds.length; i++) {

            ImageView imageView = new ImageView(this);
            imageView.setBackgroundResource(imageIds[i]);

            //将设置了图片资源的imageView添加到imageViews图片列表中
            imageViews.add(imageView);

            //动态添加点
            ImageView point = new ImageView(this);
            point.setBackgroundResource(R.drawable.point_selector);
            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(8,8);

            //第一个默认是红色
            if(i == 0){
                point.setEnabled(true);
            }else{
                //不是第一个的话,将点设置成灰色,距左边控件8dp
                point.setEnabled(false);
                params.leftMargin = 8;
            }

            //每个点的参数width=8 height=8
            point.setLayoutParams(params);

            //将点添加到LinearLayout中
            ll_point_group.addView(point);
        }
        //4. 设置适配器(PagerAdapter)-item布局-绑定数据
        viewPager.setAdapter(new MyPagerAdapter());

        //设置监听ViewPager页面的改变
        viewPager.addOnPageChangeListener(new MyOnPageChangeListener());

        //设置中间位置,左右都能够滑动,需要保证item为imageViews.size()的整数倍
        int item = Integer.MAX_VALUE/2 - Integer.MAX_VALUE/2%imageViews.size();
        viewPager.setCurrentItem(item);

        tv_title.setText(imageDescriptions[prePosition]);

        //隔3秒钟发消息
        handler.sendEmptyMessageDelayed(0,3000);
    }

    //实例化布局控件的方法
    private void initView() {
        viewPager = findViewById(R.id.viewpager);
        tv_title = findViewById(R.id.tv_title);
        ll_point_group = findViewById(R.id.ll_point_group);
    }

    //自定义监听ViewPager页面的改变的类
    class MyOnPageChangeListener implements ViewPager.OnPageChangeListener{
        /**
         * 当页面滚动了的时候回调这个方法
         * @param position  当前页面的位置
         * @param positionOffset    滑动页面的百分比
         * @param positionOffsetPixels  在屏幕上滑动的像素
         */
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

        }


        /**
         * 当某个页面被选中了的时候回调
         * @param position  被选中页面的位置
         */
        @Override
        public void onPageSelected(int position) {

            int realPosition = position%imageViews.size();

            //设置对应页面的文本信息
            tv_title.setText(imageDescriptions[realPosition]);
            //把上一个高亮的设置为默认-灰色
            ll_point_group.getChildAt(prePosition).setEnabled(false);
            //当前的设置为高亮-红色
            ll_point_group.getChildAt(realPosition).setEnabled(true);

            prePosition = realPosition;
        }

        /**
         * 当页面滚动状态变化的时候回调这个方法
         * 静止 -> 滑动
         * 滑动 -> 静止
         * 静止 -> 拖拽
         * @param state
         */
        @Override
        public void onPageScrollStateChanged(int state) {
            if(state == ViewPager.SCROLL_STATE_DRAGGING){
                isDragging = true;
                Log.e(TAG, "SCROLL_STATE_DRAGGING---------------------- ");
            }else if(state == ViewPager.SCROLL_STATE_SETTLING){
                Log.e(TAG, "onPageScrollStateChanged---------------------- ");
            }else if(state == ViewPager.SCROLL_STATE_IDLE && isDragging){
                isDragging = false;
                Log.e(TAG, "onPageScrollStateChanged---------------------- ");
                handler.removeCallbacksAndMessages(null);
                handler.sendEmptyMessageDelayed(0,4000);
            }
        }
    }

    //自定义ViewPager适配器的类
    class MyPagerAdapter extends PagerAdapter {
        /**
         * 相当于getView方法
         * @param container ViewPager自身
         * @param position  当前实例化页面的位置
         * @return
         */
        @NonNull
        @Override
        public Object instantiateItem(@NonNull ViewGroup container, int position) {

            int realPosition = position%imageViews.size();

            final ImageView imageView = imageViews.get(realPosition);
            //添加到ViewPager中
            container.addView(imageView);
            Log.e(TAG, "instantiateItem==" + position + ",---imageView==" + imageView);

            //添加触摸事件
            imageView.setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View view, MotionEvent motionEvent) {
                    switch (motionEvent.getAction()){
                        //手指按下控件
                        case MotionEvent.ACTION_DOWN:
                            Log.e(TAG, "onTouch: 手指按下");
                            handler.removeCallbacksAndMessages(null);
                            break;
                        //手指在控件上移动
                        case MotionEvent.ACTION_CANCEL:
                            Log.e(TAG, "onTouch: 事件取消");
                            handler.removeCallbacksAndMessages(null);
                            handler.sendEmptyMessageDelayed(0,4000);
                            break;
                        //手指离开
                        case MotionEvent.ACTION_UP:
                            Log.e(TAG, "onTouch: 手指离开");
                            handler.sendEmptyMessageDelayed(0,4000);
                            break;
                    }
                    return false;
                }
            });

            //添加点击事件
            imageView.setTag(position);
            imageView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Log.e(TAG, "onClick: 点击事件");
                    int position = (int) view.getTag()%imageViews.size();
                    String text = imageDescriptions[position];
                    Toast.makeText(Guanggaotiao.this, "text==" + text, Toast.LENGTH_SHORT).show();
                }
            });

            return imageView;
        }

        /**
         * 释放资源
         * @param container viewpager
         * @param position  要释放的位置
         * @param object    要释放的页面
         */
        @Override
        public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
            Log.e(TAG, "destroyItem==" + position + ",---object==" + object);
            container.removeView((View) object);
        }

        /**
         * 得到图片总数
         * @return
         */
        @Override
        public int getCount() {
//            return imageViews.size();
            //将数值返回很大,以便于能够左右无限滑动
            return Integer.MAX_VALUE;
        }

        /**
         * 比较view和object是否同一个实例
         * @param view  页面
         * @param object    方法instantiateItem返回的结果
         * @return
         */
        @Override
        public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
            return view == object;
        }
    }
}

(3)其中涉及到的drawable文件point_selector.xml、point_normal.xml和point_presss.xml

  • point_selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_enabled="false" android:drawable="@drawable/point_normal"/>
    <item android:state_enabled="true" android:drawable="@drawable/point_press"/>
</selector>
  • point_normal.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
    <size android:width="8dp" android:height="8dp"/>
    <solid android:color="#44000000"/>
</shape>
  • point_press.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
    <size android:height="8dp" android:width="8dp"/>
    <solid android:color="#ff0000"/>
</shape>
上一篇:ViewPager实现翻页效果&导航点


下一篇:Android可以响应局部、部分点击事件的View、ImageView