Android--自定义控件---自动分页的GridView
最近,根据项目需求,需要一个能够自动分页的导航,所以便自定义了一个自动分页的GridView。
思路:继承RelativeLayout,然后在里面放了一个viewpager和一个GridView。。。我也不会说,还是直接上代码吧
先看看你效果图,分别是2行3列和1行3列(有自定义属性,可以自己定义几行几列)
接下来直接看源代码(很简单)
1 package custom.widget; 2 3 import android.annotation.TargetApi; 4 import android.content.Context; 5 import android.content.res.TypedArray; 6 import android.os.Build; 7 import android.support.v4.view.PagerAdapter; 8 import android.support.v4.view.ViewPager; 9 import android.util.AttributeSet; 10 import android.view.MotionEvent; 11 import android.view.View; 12 import android.view.ViewGroup; 13 import android.widget.AbsListView; 14 import android.widget.AdapterView; 15 import android.widget.BaseAdapter; 16 import android.widget.GridView; 17 import android.widget.LinearLayout; 18 import android.widget.RadioButton; 19 import android.widget.RadioGroup; 20 import android.widget.RelativeLayout; 21 22 import com.newair.automaticpagedemo.R; 23 24 import java.util.ArrayList; 25 import java.util.List; 26 27 /** 28 * Created by ouhimehime on 16/5/4. 29 * ----------自动分页的GridView---------- 30 */ 31 public class AutoMaticPageGridView extends RelativeLayout { 32 33 //分页所用 34 private ViewPager viewPager; 35 //导航点 36 private RadioGroup radioGroup; 37 //自定义行数 38 private int lines = 0; 39 //自定义列数 40 private int column = 0; 41 //自定义按钮样式 42 private int btn_res; 43 //自定义属性是否显示导航点 44 private boolean btn_isvisible; 45 //页数-需要动态计算 46 private int pages = 0; 47 //适配器 48 private BaseAutoAdapter adapter; 49 //Item的高度 50 private int itemHeight = 0; 51 52 //点击事件的接口 53 public interface OnItemClickCallBack { 54 void OnItemClicked(int position, Object object); 55 } 56 57 private OnItemClickCallBack onItemClickCallBack; 58 59 public void setOnItemClickListener(OnItemClickCallBack onItemClickCallBack) { 60 this.onItemClickCallBack = onItemClickCallBack; 61 } 62 63 64 public AutoMaticPageGridView(Context context) { 65 super(context); 66 } 67 68 public AutoMaticPageGridView(Context context, AttributeSet attrs) { 69 super(context, attrs); 70 init(context, attrs); 71 } 72 73 public AutoMaticPageGridView(Context context, AttributeSet attrs, int defStyleAttr) { 74 super(context, attrs, defStyleAttr); 75 init(context, attrs); 76 } 77 78 @TargetApi(Build.VERSION_CODES.LOLLIPOP) 79 public AutoMaticPageGridView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 80 super(context, attrs, defStyleAttr, defStyleRes); 81 init(context, attrs); 82 } 83 84 85 //初始化控件 86 private void init(Context context, AttributeSet attrs) { 87 //加载自定义属性 88 final TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.AutoMaticPageGridView); 89 lines = array.getInteger(R.styleable.AutoMaticPageGridView_auto_lines, 1);//行数 90 column = array.getInteger(R.styleable.AutoMaticPageGridView_auto_column, 4);//列数 91 btn_res = array.getResourceId(R.styleable.AutoMaticPageGridView_auto_button, 0);//btn的样式 92 btn_isvisible = array.getBoolean(R.styleable.AutoMaticPageGridView_auto_button_visible, true);//默认true 93 array.recycle(); 94 //分页用 95 viewPager = new ViewPager(context); 96 viewPager.setLayoutParams(new LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, 97 RelativeLayout.LayoutParams.MATCH_PARENT)); 98 addView(viewPager); 99 //导航点用 100 radioGroup = new RadioGroup(context); 101 radioGroup.setOrientation(LinearLayout.HORIZONTAL); 102 RelativeLayout.LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); 103 params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM); 104 params.addRule(RelativeLayout.CENTER_IN_PARENT); 105 radioGroup.setLayoutParams(params); 106 addView(radioGroup); 107 //如果不显示的话就隐藏 108 if (!btn_isvisible) { 109 radioGroup.setVisibility(GONE); 110 } 111 } 112 113 //设置适配器 114 public void setAdapter(BaseAutoAdapter baseAdapter) { 115 this.adapter = baseAdapter; 116 //计算页数 117 if ((adapter.getCounts() / (column * lines)) > 0) { 118 pages = (adapter.getCounts() / (column * lines)) + 1; //多一页 119 } else { 120 pages = adapter.getCounts(); 121 } 122 //添加radioButton 123 addRadioButton(pages); 124 this.post(new Runnable() { 125 @Override 126 public void run() { 127 itemHeight = getMeasuredHeight() / lines; 128 //显示viewpager 129 ViewPagerAdapter viewPagerAdapter = new ViewPagerAdapter(getContext()); 130 viewPager.setAdapter(viewPagerAdapter); 131 //设置联动 132 initLinkAgeEvent(); 133 } 134 }); 135 } 136 137 //添加RadioButton 138 private void addRadioButton(int pages) { 139 for (int i = 0; i < pages; i++) { 140 RadioButton radioButton = new RadioButton(getContext()); 141 radioButton.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, 142 LinearLayout.LayoutParams.WRAP_CONTENT)); 143 radioButton.setPadding(5, 5, 5, 5);//间距 144 radioButton.setId(i);//设置Id,方便联动 145 radioButton.setClickable(false); 146 if (btn_res != 0) { //设置按钮样式 147 radioButton.setButtonDrawable(btn_res); 148 } 149 radioGroup.addView(radioButton); 150 } 151 } 152 153 //给当前页计算数据数量 154 private List<View> getAdapterData(int position) { 155 List<View> cerrent = new ArrayList<>(); 156 if (position == pages - 1) { //如果等于最后一页 157 for (int i = position * (lines * column); i < adapter.getCounts(); i++) { 158 cerrent.add(adapter.getItemView(i, null)); 159 } 160 } else { 161 for (int i = position * (lines * column); i < position * (lines * column) + (lines * column); i++) { 162 cerrent.add(adapter.getItemView(i, null)); 163 } 164 } 165 return cerrent; 166 } 167 168 //ViewPager适配器 169 private class ViewPagerAdapter extends PagerAdapter { 170 171 private Context context; 172 173 public ViewPagerAdapter(Context context) { 174 this.context = context; 175 } 176 177 @Override 178 public int getCount() { 179 return pages; 180 } 181 182 @Override 183 public boolean isViewFromObject(View view, Object object) { 184 return view == object; 185 } 186 187 @Override 188 public Object instantiateItem(ViewGroup container, int position) { 189 CustomGridView gridView = new CustomGridView(context); 190 gridView.setLayoutParams(new AbsListView.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT, 191 AbsListView.LayoutParams.MATCH_PARENT)); 192 gridView.setNumColumns(column);//设置列数 193 gridView.setColumnWidth(GridView.AUTO_FIT); 194 GridViewAdapter adapter = new GridViewAdapter(getAdapterData(position), position); 195 gridView.setAdapter(adapter); 196 container.addView(gridView); 197 gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() { 198 @Override 199 public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 200 GridViewAdapter adapter1 = (GridViewAdapter) parent.getAdapter(); 201 onItemClickCallBack.OnItemClicked(adapter1.currentPage * (lines * column) + position, view); 202 } 203 }); 204 return gridView; 205 } 206 207 @Override 208 public void destroyItem(ViewGroup container, int position, Object object) { 209 container.removeView((GridView) object); 210 } 211 } 212 213 //GridView的适配器 214 private class GridViewAdapter extends BaseAdapter { 215 216 private List<View> views;//数据量 217 public int currentPage; //当前页 218 219 public GridViewAdapter(List<View> counts, int currentPage) { 220 this.views = counts; 221 this.currentPage = currentPage; 222 } 223 224 @Override 225 public int getCount() { 226 return views.size(); 227 } 228 229 @Override 230 public Object getItem(int position) { 231 return position; 232 } 233 234 @Override 235 public long getItemId(int position) { 236 return position; 237 } 238 239 @Override 240 public View getView(int position, View convertView, ViewGroup parent) { 241 if (convertView == null) { 242 convertView = views.get(position); 243 convertView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, itemHeight)); 244 } 245 return convertView; 246 } 247 248 } 249 250 //自定义GridView,禁止滑动 251 private class CustomGridView extends GridView { 252 253 public CustomGridView(Context context) { 254 super(context); 255 } 256 257 public CustomGridView(Context context, AttributeSet attrs) { 258 super(context, attrs); 259 } 260 261 public CustomGridView(Context context, AttributeSet attrs, int defStyleAttr) { 262 super(context, attrs, defStyleAttr); 263 } 264 265 @TargetApi(Build.VERSION_CODES.LOLLIPOP) 266 public CustomGridView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 267 super(context, attrs, defStyleAttr, defStyleRes); 268 } 269 270 @Override 271 public boolean dispatchTouchEvent(MotionEvent ev) { 272 if (ev.getAction() == MotionEvent.ACTION_MOVE) { 273 return true;//禁止GridView进行滑动 274 } 275 return super.dispatchTouchEvent(ev); 276 } 277 } 278 279 //初始化联动联动事件 280 private void initLinkAgeEvent() { 281 //默认选中第一个 282 viewPager.setCurrentItem(0); 283 radioGroup.check(radioGroup.getChildAt(0).getId()); 284 //滑动换页事件 285 viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { 286 @Override 287 public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 288 289 } 290 291 @Override 292 public void onPageSelected(int position) { 293 radioGroup.check(position); 294 } 295 296 @Override 297 public void onPageScrollStateChanged(int state) { 298 299 } 300 }); 301 } 302 303 }
这个组件也有个适配器,很简单,就是定义了几个抽象方法
package custom.widget; import android.view.View; import android.view.ViewGroup; /** * Created by ouhimehime on 16/5/4. * -----适配器=------ */ public abstract class BaseAutoAdapter { public abstract int getCounts(); //返回数据数量 public abstract Object getItem(int position); //当前Item的数据 public abstract View getItemView(int position, ViewGroup parent); //返回Item的布局 }
还自定义了一部分属性,方便使用起来好控制
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="AutoMaticPageGridView"> <!-- 行数 --> <attr name="auto_lines" format="integer" /> <!-- 列数 --> <attr name="auto_column" format="integer" /> <!-- button的样式 --> <attr name="auto_button" format="reference" /> <!-- 是否显示导航点 --> <attr name="auto_button_visible" format="boolean" /> </declare-styleable> </resources>
-----------------------------------------------------------------------以上就是源代码了-----------------------------------------------------------------------------
下面是如何使用:(就当做一个控件来使用就可以)
①、先看布局文件XML,控件的高度是可以自己定义的
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:auto="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity"> <custom.widget.AutoMaticPageGridView android:id="@+id/automatic" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" auto:auto_button="@drawable/btn_status_style" auto:auto_column="3" auto:auto_lines="2" /> <LinearLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="2"/> </LinearLayout>
②、再看适配器代码,适配器需要继承BaseAutoAdapter
package adapter; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import com.newair.automaticpagedemo.R; import java.util.List; import custom.widget.BaseAutoAdapter; /** * Created by ouhimehime on 16/5/4. * ------------适配器------------ */ public class MyAutoMaticPageAdapter extends BaseAutoAdapter { private Context context; private List<Integer> myData; public MyAutoMaticPageAdapter(Context context, List<Integer> myData) { this.context = context; this.myData = myData; } @Override public int getCounts() { return myData.size(); } @Override public Object getItem(int position) { return myData.get(position); } @Override public View getItemView(int position, ViewGroup parent) { View view = LayoutInflater.from(context).inflate(R.layout.item_layout, null); return view; } }
③、再看主布局代码,为了方便我就随便放了放了10条数据
package com.newair.automaticpagedemo; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.widget.Toast; import java.util.ArrayList; import java.util.List; import adapter.MyAutoMaticPageAdapter; import custom.widget.AutoMaticPageGridView; public class MainActivity extends AppCompatActivity { private AutoMaticPageGridView automatic; private MyAutoMaticPageAdapter adapter; private List<Integer> myData; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); automatic = (AutoMaticPageGridView) findViewById(R.id.automatic); myData = new ArrayList<>(); for (int i = 0; i < 10; i++) { myData.add(i); } adapter = new MyAutoMaticPageAdapter(this, myData); automatic.setAdapter(adapter); //点击事件 automatic.setOnItemClickListener(new AutoMaticPageGridView.OnItemClickCallBack() { @Override public void OnItemClicked(int position, Object object) { Toast.makeText(MainActivity.this, position + "--", Toast.LENGTH_SHORT).show(); } }); } }
------------------------------------------------------------------------以上是如何使用----------------------------------------------------------------------------------
以上就是自己定义了一个自动分页的控件,写的不好,希望各位见谅。
新人学习中,也不太会总结,有做的不对的地方希望各位大神指出,谢谢。