自定义布局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 时相同。