横向滑动的广告(网格控件)
2016-11-21 21:21
309 查看
转载请标明出处:
http://blog.csdn.net/hai_qing_xu_kong/article/details/53264494
本文出自:【顾林海的博客】
![](https://img-blog.csdn.net/20161121211024277)
![](https://img-blog.csdn.net/20161121211039679)
![](https://img-blog.csdn.net/20161121211052039)
gv_attrs:
在activity_main中的使用 :
OK,目前我们是想创建一个一行两列,行间距和列间距都是10dp,四周间距是5dp的GVPager控件,创建GVPager类。
GVPager类继承自ViewPager,上面的代码是获取自定义的属性值,这里面重写了setPadding方法,并手动将左右边距设置0,这是为什么呢?因为我们设置的是ViewPager内部View的左右边距,而不是设置ViewPager的左右间距。
接着给ViewPager设置相应的PagerAdapter,ViewPager显示的每一个Item View都是一个HGridView,效果图可以看出ItemView实际上是类似与GridView一样,是以列表形式展示的,ViewPager的每一个View都是一个AdapterView,也就是这里的HGridView是一个继承自AdapterView的类。
GVPager适配器:
HGridView继承自AdapterView, 而AdapterView继承自ViewGroup,因此,还得实现onMeasure和onLayout方法,用于子View的测量和定位:
setAdapter方法主要做了以下几件事:
填充adapter中的View。
如果该AdapterView之前的子View数量大于新添加的子View数,需要移除多余的View。
填充完每屏的子View后,就需要我们测量子View的大小,实现onMeasure方法,子View的宽高我们可以根据下图分析,剩下做的就是给子View定位。具体看一下代码,相信大家都能看懂。 :
![](https://img-blog.csdn.net/20161121211813905)
由上图可以计算出子View的宽高:
宽=(AdapterView_Width-paddingLeft-paddingRight-(列Margin)*(列数-1))/列数
高=(AdapterView_Height-(行Margin)*(行数-1))/行数
既然HGridView定义完毕,接着就得给我们的AdapterView绑定适配器,适配器所要做的事情就是定义ViewPager中每一个HGridView显示多少个View以及所要显示的View:
GVPager和HGridView已经定义完毕,接下来所做的事情就是给他们绑定适配器 :
到这里横向滚动的网格广告已经定义完毕,剩下的自动滚动和动画就不介绍了,下面给出这个控件的一些公共方法:
github项目源码地址:点击【项目源码】
http://blog.csdn.net/hai_qing_xu_kong/article/details/53264494
本文出自:【顾林海的博客】
前言
很早以前写过一篇自定义广告控件的文章,这篇文章也是自定义广告控件,不同的是内部包含的是列表,具体看效果图:使用方式
<?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" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/darker_gray"> <glh.gvpager.view.GVPager android:id="@+id/gvp" android:layout_width="match_parent" android:layout_height="100dp" android:padding="5dp" app:columnMargin="10dp" app:columnNumber="2" app:rowMargin="10dp" app:rowNumber="1" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/gvp" android:layout_centerHorizontal="true" android:orientation="horizontal"> <glh.gvpager.view.IndicatorView android:id="@+id/indicator" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> </RelativeLayout>
package glh.gvpager; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import java.util.Random; import glh.gvpager.view.GVPager; import glh.gvpager.view.IndicatorView; public class MainActivity extends AppCompatActivity { private IndicatorView indicator; private GVPager mGVPager; private int[] resourceId = {R.drawable.demo1, R.drawable.demo2, R.drawable.demo3, R.drawable.demo4,R.drawable.demo5, R.drawable.demo6, R.drawable.demo1, R.drawable.demo2,R.drawable.demo3, R.drawable.demo1}; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); GridPagerAdapter gridPagerAdapter = new GridPagerAdapter(10); mGVPager = (GVPager) findViewById(R.id.gvp); indicator = (IndicatorView) findViewById(R.id.indicator); mGVPager.setIndicator(indicator); mGVPager.setAutoDuration(500); mGVPager.setPageTransformer(new CubeTransformer()); mGVPager.setAdapter(gridPagerAdapter); mGVPager.play(); } @Override protected void onDestroy() { mGVPager.stop(); super.onDestroy(); } public class GridPagerAdapter extends BaseAdapter { int mSize; public GridPagerAdapter(int size) { mSize = size; } @Override public int getCount() { return mSize; } @Override public Object getItem(int position) { return position; } @Override public long getItemId(int position) { return position; } @Override public View getView(final int position, View convertView, ViewGroup parent) { ViewHolder viewHolder; if (convertView == null) { viewHolder = new ViewHolder(); convertView = getLayoutInflater().inflate(R.layout.item_gvp, null); viewHolder.iv_demo = (ImageView) convertView.findViewById(R.id.iv_demo); convertView.setTag(viewHolder); } else { viewHolder = (ViewHolder) convertView.getTag(); } viewHolder.iv_demo.setImageResource(resourceId[position]); return convertView; } } static class ViewHolder { ImageView iv_demo; } }
原理说明
左右滑动视图的最好方案非ViewPager莫属,因此创建一个继承ViewPager的类,并且定义一些属性:gv_attrs:
<resources> <declare-styleable name="GridViewPager"> <attr name="columnNumber" format="integer" />//列数 <attr name="rowNumber" format="integer" />//行数 <attr name="columnMargin" format="dimension" />//列间距 <attr name="rowMargin" format="dimension" />//行间距 <attr name="android:paddingLeft" /> <attr name="android:paddingRight" /> <attr name="android:padding" /> </declare-styleable> </resources>
在activity_main中的使用 :
<glh.gvpager.view.GVPager android:id="@+id/gvp" android:layout_width="match_parent" android:layout_height="300dp" android:padding="5dp" app:columnMargin="10dp" app:columnNumber="2" app:rowMargin="10dp" app:rowNumber="1" />
OK,目前我们是想创建一个一行两列,行间距和列间距都是10dp,四周间距是5dp的GVPager控件,创建GVPager类。
public class GVPager extends ViewPager { private static final int DEFAULT_COLUMN_NUMBER = 2; private static final int DEFAULT_ROW_NUMBER = 3; private int mRowNumber = DEFAULT_ROW_NUMBER;// 行 private int mColumnNumber = DEFAULT_COLUMN_NUMBER;// 列 private float mColumnMargin = 0;//列间距 private float mRowMargin = 0;//行间距 private int mPaddingLeft = 0;//左边距 private int mPaddingRight = 0;//右边距 public GVPager(Context context) { this(context, null); } public GVPager(Context context, AttributeSet attrs) { super(context, attrs); getAttributeSet(attrs); } /** * 获取设置的属性值 * * @param _attrs AttributeSet */ private void getAttributeSet(AttributeSet _attrs) { if (_attrs != null) { TypedArray typedArray = getContext().obtainStyledAttributes(_attrs, R.styleable.GridViewPager); int count = typedArray.getIndexCount(); for (int i = 0; i < count; i++) { int attr = typedArray.getIndex(i); switch (attr) { case R.styleable.GridViewPager_columnNumber: mColumnNumber = typedArray.getInt(attr, -1); break; case R.styleable.GridViewPager_rowNumber: mRowNumber = typedArray.getInt(attr, -1); break; case R.styleable.GridViewPager_columnMargin: mColumnMargin = typedArray.getDimension(attr, 0); break; case R.styleable.GridViewPager_rowMargin: mRowMargin = typedArray.getDimension(attr, 0); break; case R.styleable.GridViewPager_android_padding: int padding = typedArray.getDimensionPixelSize(attr, 0); setPadding(padding, padding, padding, padding); break; case R.styleable.GridViewPager_android_paddingLeft: mPaddingLeft = typedArray.getDimensionPixelSize(attr, 0); break; case R.styleable.GridViewPager_android_paddingRight: mPaddingRight = typedArray.getDimensionPixelSize(attr, 0); break; default: break; } } typedArray.recycle(); } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } @Override public void setPadding(int left, int top, int right, int bottom) { mPaddingLeft = left; mPaddingRight = right; super.setPadding(0, top, 0, bottom); } }
GVPager类继承自ViewPager,上面的代码是获取自定义的属性值,这里面重写了setPadding方法,并手动将左右边距设置0,这是为什么呢?因为我们设置的是ViewPager内部View的左右边距,而不是设置ViewPager的左右间距。
接着给ViewPager设置相应的PagerAdapter,ViewPager显示的每一个Item View都是一个HGridView,效果图可以看出ItemView实际上是类似与GridView一样,是以列表形式展示的,ViewPager的每一个View都是一个AdapterView,也就是这里的HGridView是一个继承自AdapterView的类。
GVPager适配器:
private List<HGridView> mHGridViewList = null;//内嵌的GridView private class GridPagerAdapter extends PagerAdapter { @Override public int getCount() { return mHGridViewList.size(); } @Override public boolean isViewFromObject(View arg0, Object arg1) { return arg0 == arg1; } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView((View) object); } @Override public Object instantiateItem(ViewGroup container, int position) { container.addView(mHGridViewList.get(position), new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); return mHGridViewList.get(position); } }
HGridView继承自AdapterView, 而AdapterView继承自ViewGroup,因此,还得实现onMeasure和onLayout方法,用于子View的测量和定位:
public class HGridView extends AdapterView<ListAdapter> { private ListAdapter adapter; public HGridView() { super(GVPager.this.getContext()); } @Override public ListAdapter getAdapter() { return adapter; } @Override public void setAdapter(ListAdapter listAdapter) { this.adapter = listAdapter; int oldChildCount = getChildCount(); int newChildCount = adapter.getCount(); int deleteChildCount = oldChildCount - newChildCount; for (int i = oldChildCount; i < newChildCount; i++) { View child = adapter.getView(i, null, this); addViewInLayout(child, i, new LayoutParams(0, 0)); } if (deleteChildCount > 0) { removeViewsInLayout(newChildCount, deleteChildCount); } } @Override public View getSelectedView() { if (getChildCount() > 0) { return getChildAt(0); } return null; } @Override public void setSelection(int i) { } @Override public int getPaddingLeft() { return mPaddingLeft; } @Override public int getPaddingRight() { return mPaddingRight; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { /* 获取子View宽高 */ int width = (int) ((MeasureSpec.getSize(widthMeasureSpec) - getPaddingLeft() - getPaddingRight() - mColumnMargin * (mColumnNumber - 1)) / mColumnNumber); int height = (int) ((MeasureSpec.getSize(heightMeasureSpec) - mRowMargin * (mRowNumber - 1)) / mRowNumber); int count = getChildCount(); for (int i = 0; i < count; i++) { View child = getChildAt(i); /* 给子View设置宽高 */ LayoutParams layoutParams = child.getLayoutParams(); layoutParams.width = width; layoutParams.height = height; child.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)); } setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec), getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec)); } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { int childCount = getChildCount(); int childLeft = 0; int childTop = 0; for (int i = 0; i < childCount && i < mRowNumber * mColumnNumber; i++) { View child = getChildAt(i); int x = i % mColumnNumber; if (x == 0) { /* 每一行的第一个子View */ childLeft = getPaddingLeft(); } LayoutParams layoutParams = child.getLayoutParams(); child.layout(childLeft, childTop, childLeft + layoutParams.width, childTop + layoutParams.height); childLeft += layoutParams.width + mColumnMargin; if (x == mColumnNumber - 1) { /* 每一行最后一个子View,要另起一行 */ childTop += layoutParams.height + mRowMargin; } } } }
setAdapter方法主要做了以下几件事:
填充adapter中的View。
如果该AdapterView之前的子View数量大于新添加的子View数,需要移除多余的View。
填充完每屏的子View后,就需要我们测量子View的大小,实现onMeasure方法,子View的宽高我们可以根据下图分析,剩下做的就是给子View定位。具体看一下代码,相信大家都能看懂。 :
由上图可以计算出子View的宽高:
宽=(AdapterView_Width-paddingLeft-paddingRight-(列Margin)*(列数-1))/列数
高=(AdapterView_Height-(行Margin)*(行数-1))/行数
既然HGridView定义完毕,接着就得给我们的AdapterView绑定适配器,适配器所要做的事情就是定义ViewPager中每一个HGridView显示多少个View以及所要显示的View:
private class GridAdapter extends BaseAdapter { private int page; private int size; private BaseAdapter adapter; public GridAdapter(int _page, int _size, BaseAdapter _adapter) { this.size = _size; this.page = _page; this.adapter = _adapter; } @Override public int getCount() { if (adapter.getCount() % size == 0 || page < adapter.getCount() / size) { return size; } return adapter.getCount() % size; } @Override public Object getItem(int i) { return adapter.getItem(page * size + i); } @Override public long getItemId(int i) { return adapter.getItemId(page * size + i); } @Override public View getView(int i, View view, ViewGroup viewGroup) { return adapter.getView(page * size + i, view, viewGroup); } }
GVPager和HGridView已经定义完毕,接下来所做的事情就是给他们绑定适配器 :
private void resetAdapter() { // 行*列=当前屏的总个数 int pageSize = mColumnNumber * mRowNumber; if (pageSize <= 0) return; if (mAdapter.getCount() == 0) { mHGridViewList.removeAll(mHGridViewList); } int pageCount = mAdapter.getCount() / pageSize; int listSize = mHGridViewList.size() - 1; HGridView hGridView; GridAdapter gridAdapter; for (int i = 0, page = (mAdapter.getCount() % pageSize == 0) ? pageCount-- : pageCount; i <= Math.max(listSize, page); i++) { if (i <= listSize && i <= page) { // 更新 hGridView = mHGridViewList.get(i); gridAdapter = new GridAdapter(i, pageSize, mAdapter); hGridView.setAdapter(gridAdapter); mHGridViewList.set(i, hGridView); continue; } if (i > listSize && i <= page) { // 添加 hGridView = new HGridView(); gridAdapter = new GridAdapter(i, pageSize, mAdapter); hGridView.setAdapter(gridAdapter); mHGridViewList.add(hGridView); continue; } if (i > page && i <= listSize) {// 以设置的Adapter中的个数为准,超过移除View mHGridViewList.remove(page + 1);// 每次都移除page+1位置的GridView continue; } } super.setAdapter(new GridPagerAdapter()); if (mSelection >= 0) { setSelection(mSelection); } }
到这里横向滚动的网格广告已经定义完毕,剩下的自动滚动和动画就不介绍了,下面给出这个控件的一些公共方法:
设置ViewPager的Adapter public void setAdapter(BaseAdapter _adapter) 刷新 public void notifyDataSetChanged() 定位位置 public void setSelection(int position) 获取总页数 public int getPageCount() 获取总个数 public int getPageSize() 设置指示器 public void setIndicator(IndicatorView _indicator) 自动切换开启. public void play() 停止播放 public void stop() 设置ViewPager的切换动画 public void setPageTransformer(PageTransformer _pageTransformer) 滑动速度 public void setAutoDuration(int _duration)
项目下载地址
以下是完整的github项目地址,欢迎多多star和fork。github项目源码地址:点击【项目源码】
相关文章推荐
- Android导航菜单横向左右滑动并和下方的控件实现联动
- Android导航菜单横向左右滑动并和下方的控件实现联动
- 导航菜单横向左右滑动并和下方的控件实现联动(有效果图)
- 单行横向滑动的日历calendar控件
- Android 自定义 HorizontalScrollView 打造再多图片(控件)也不怕 OOM 的横向滑动效果
- Android 自定义 HorizontalScrollView 打造再多图片(控件)也不怕 OOM 的横向滑动效果
- Android 自定义 HorizontalScrollView 打造再多图片(控件)也不怕 OOM 的横向滑动效果
- 仿知乎广告控件,广告图随滑动控件滑动
- Android 自定义 HorizontalScrollView 打造再多图片(控件)也不怕 OOM 的横向滑动效果
- [置顶] Android横向滑动加载更多的控件的实现---HorizontalScrollSlideView
- WP8__实现ListBox横向滑动及子项绑定图片等控件
- Android 自定义 HorizontalScrollView 打造再多图片(控件)也不怕 OOM 的横向滑动效果
- Android 自定义 HorizontalScrollView 打造再多图片(控件)也不怕 OOM 的横向滑动效果
- Android 自定义 HorizontalScrollView 打造再多图片(控件)也不怕 OOM 的横向滑动效果
- 自定义控件 横向滑动控件 总结
- Android 自定义 HorizontalScrollView 打造再多图片(控件)也不怕 OOM 的横向滑动效果
- Android 自定义 HorizontalScrollView 打造再多图片(控件)也不怕 OOM 的横向滑动效果
- Android 自定义 HorizontalScrollView 打造再多图片(控件)也不怕 OOM 的横向滑动效果
- Android 自定义 HorizontalScrollView 打造再多图片(控件)也不怕 OOM 的横向滑动效果
- Android 自定义 HorizontalScrollView 打造再多图片(控件)也不怕 OOM 的横向滑动效果