自定义布局

本文介绍了一个自定义的Android Banner布局实现方法,通过ViewPager展示轮播图片,并使用LinearLayout显示指示器。文章详细阐述了如何初始化Banner组件、配置触摸事件以及设置图片加载等关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

自定义布局Banner类

package view;

import android.content.Context;
import android.content.res.TypedArray;
import android.net.wifi.aware.PublishConfig;
import android.os.Handler;
import android.support.annotation.AttrRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.Size;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.ContextMenu;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;

import com.example.asus.xviewpager.R;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;

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

/**
 * Created by asus on 2017/8/16.
 */
public class Banner extends FrameLayout{
    private  int size;
    private  int dq=10000;
    private int marger;
    private LinearLayout linear;
    private  Context context;
    private ViewPager vp;
    private List<String> list=new ArrayList<>();
    private Handler h=new Handler();
    public Banner(@NonNull Context context) {
        super(context);
        init(context,null);
    }
    public Banner(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context,attrs);
    }
    public Banner(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context,attrs);
    }
    public  void  init(Context context,AttributeSet attrs){
        this.context=context;
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.Banner);
        marger= typedArray.getDimensionPixelSize(R.styleable.Banner_marger,10);
        size=typedArray.getDimensionPixelSize(R.styleable.Banner_size,10);
        typedArray.recycle();
        View view = View.inflate(context, R.layout.bnner_fragmelayou, this);
        linear =  view.findViewById(R.id.linear);
        vp = view.findViewById(R.id.vp);
    }
   public  void  initvp(){
       list.add("https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=818840820,3682346499&fm=26&gp=0.jpg");
       list.add("https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=1243439538,3845509165&fm=26&gp=0.jpg");
       list.add("https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=1018053499,914759246&fm=26&gp=0.jpg");
       list.add("https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=1395936944,1390699296&fm=26&gp=0.jpg");
       vp.setAdapter(new Mypage());
       vp.setCurrentItem(10000);
       vp.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
           @Override
           public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
               for (int i = 0; i<4 ; i++) {
                  ImageView image = (ImageView) linear.getChildAt(i);
                   if(i==position%4){
                       image.setImageResource(R.drawable.hongdian);
                   }else {
                       image.setImageResource(R.drawable.baidian);
                   }
               }
           }

           @Override
           public void onPageSelected(int position) {

           }

           @Override
           public void onPageScrollStateChanged(int state) {

           }
       });

       h.postDelayed(task,2000);


    }
    Runnable task=new Runnable(){
        @Override
        public void run() {
            dq++;
            vp.setCurrentItem(dq);
            h.postDelayed(task,2000);
        }
    };
    public void initdata() {
        for (int i = 0; i <4 ; i++) {
            ImageView img=new ImageView(context);
            if(i==0){
                img.setImageResource(R.drawable.hongdian);
            }else {
                img.setImageResource(R.drawable.baidian);
            }
            LinearLayout.LayoutParams parmas=new LinearLayout.LayoutParams(20,20);
            parmas.leftMargin=marger;
            parmas.rightMargin=marger;
            linear.addView(img,parmas);
        }

    }
    class  Mypage extends PagerAdapter{
        @Override
        public int getCount() {
            return Integer.MAX_VALUE;
        }

        @Override
        public boolean isViewFromObject(View view, Object object) {
            return view==object;
        }

        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            View view = View.inflate(context, R.layout.vp_untim, null);
            ImageView img_tu=view.findViewById(R.id.img_tu);

            DisplayImageOptions option=new DisplayImageOptions.Builder()
                    .cacheInMemory(true)
                    .cacheOnDisk(true)
                    .build();
            ImageLoaderConfiguration con=new ImageLoaderConfiguration.Builder(context)
                    .defaultDisplayImageOptions(option)
                    .build();
            ImageLoader.getInstance().init(con);
            ImageLoader.getInstance().displayImage(list.get(position%4),img_tu);
            container.addView(view);
            return view ;
        }

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            container.removeView((View) object);
        }
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        int action = ev.getAction();
        if(action==MotionEvent.ACTION_DOWN||action==MotionEvent.ACTION_MOVE){
            h.removeCallbacks(task);
        }else {
             h.postDelayed(task,2000);
        }

        return super.dispatchTouchEvent(ev);
    }
    public  void cancell(){
        h.removeCallbacks(task);
        }
}
 R.layout.bnner_fragmelayou布局
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">



    <android.support.v4.view.ViewPager
        android:id="@+id/vp"
        android:layout_width="match_parent"
        android:layout_height="195dp"></android.support.v4.view.ViewPager>
    <LinearLayout
        android:id="@+id/linear"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="20dp"
        android:layout_marginTop="150dp"
        >

    </LinearLayout>

</FrameLayout>
asstrs 属性  在values文件夹写

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="Banner">
    <attr name="size" format="dimension"></attr>
    <attr name="marger" format="dimension"></attr>
    </declare-styleable>
</resources>
圆点

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval"
    >
<size android:width="30dp" android:height="30dp"></size>
    <solid android:color="#fff"></solid>
</shape>
附加

事件分发:public booleandispatchTouchEvent(MotionEvent ev)

Touch事件发生时 Activity 的 dispatchTouchEvent(MotionEvent ev) 方法会以隧道方式(从根元素依次往下传递直到最内层子元素或在中间某一元素中由于某一条件停止传递)将事件传递给最外层 View 的 dispatchTouchEvent(MotionEvent ev) 方法,并由该 View 的 dispatchTouchEvent(MotionEvent ev) 方法对事件进行分发。dispatchTouchEvent 的事件分发逻辑如下:

如果 return true,事件会分发给当前 View 并由 dispatchTouchEvent 方法进行消费,同时事件会停止向下传递;

如果 returnfalse,事件分发分为两种情况:

如果当前 View 获取的事件直接来自 Activity,则会将事件返回给 Activity 的 onTouchEvent 进行消费;

如果当前 View 获取的事件来自外层父控件,则会将事件返回给父 View 的  onTouchEvent 进行消费。

如果返回系统默认的 super.dispatchTouchEvent(ev),事件会自动的分发给当前 View 的 onInterceptTouchEvent 方法。

 事件拦截:public booleanonInterceptTouchEvent(MotionEvent ev) 

在外层 View 的 dispatchTouchEvent(MotionEvent ev) 方法返回系统默认的 super.dispatchTouchEvent(ev) 情况下,事件会自动的分发给当前 View 的 onInterceptTouchEvent 方法。onInterceptTouchEvent 的事件拦截逻辑如下:

如果 onInterceptTouchEvent返回 true,则表示将事件进行拦截,并将拦截到的事件交由当前 View 的 onTouchEvent 进行处理;

如果onInterceptTouchEvent 返回 false,则表示将事件放行,当前 View 上的事件会被传递到子 View 上,再由子 View 的 dispatchTouchEvent 来开始这个事件的分发;

如果onInterceptTouchEvent 返回 super.onInterceptTouchEvent(ev),事件默认会被拦截,并将拦截到的事件交由当前 View 的 onTouchEvent 进行处理。

 事件响应:public booleanonTouchEvent(MotionEvent ev)

在 dispatchTouchEvent 返回 super.dispatchTouchEvent(ev) 并且onInterceptTouchEvent 返回 true 或返回 super.onInterceptTouchEvent(ev) 的情况下onTouchEvent 会被调用。onTouchEvent 的事件响应逻辑如下:

如果事件传递到当前 View 的 onTouchEvent 方法,而该方法返回了 false,那么这个事件会从当前 View 向上传递,并且都是由上层 View 的 onTouchEvent 来接收,如果传递到上面的 onTouchEvent 也返回 false,这个事件就会“消失”,而且接收不到下一次事件。

如果返回了 true 则会接收并消费该事件。

如果返回super.onTouchEvent(ev) 默认处理事件的逻辑和返回 false 时相同。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值