Android水平(横向)翻页列表,类似于水平方向的GridView,行列自定义,但要翻页切换,考虑加载性能,当Item数据很多时加载和翻页要流畅,翻页时要有动画效果,效果图如下:
实现方式:
1:翻页可用ViewPager来做,每页内多行排列Item,考虑到翻页切换数据和加载的速度不能嵌套GridView,直接使用View来显示。
2:缓存被ViewPager销毁的View,以此来提高当数据量很大时的系统资源消耗问题。
代码实现如下:
1:最主要的是编写一个自定义的PagerAdapter类,用来给ViewPager适配数据,默认情况下ViewPager会缓存相邻两页面的View,我们定义一个List<View>用来缓存被destroy后的view,当ViewPager需要实例化一个新View用来显示时,判断是否有缓存的View,如果有则拿出来使用,如果没有实例化一个新的view,写一个Item的布局文件,这里每页面10个,通过ViewHolder来处理各小Item,每次实例化新的页面时给view设置当前页10个item的数据(从List中获得,判断当前页需要显示的position,从List中取出相应的数据,最后一页显示不完的地方留空)。具体实现代码如下:
/** * @author Homgwu */ public class MainViewPagerAdapter extends PagerAdapter implements OnClickListener { private List<ItemEntity> singerList = new ArrayList<ItemEntity>(); private Context mContext; private int pagerCount = 0; /** * 用来缓存被viewpager destroy掉的view,以便重复使用 */ private List<View> cacheViews = new ArrayList<View>(); private LayoutInflater mInflater; // private static final int TAG_VIEWHOLDER = 1; // private static final int TAG_ITEMDATA = 2; /** * 一页内的item个数 */ private double itemInCount = 10.0; public MainViewPagerAdapter(List<ItemEntity> itemList, Context mContext) { super(); this.singerList = itemList; this.mContext = mContext; pagerCount = (int) Math.ceil(itemList.size() / itemInCount); mInflater = LayoutInflater.from(this.mContext); } public void updateData(List<ItemEntity> singerList) { this.singerList = singerList; notifyDataSetChanged(); } @Override public int getCount() { return pagerCount; } @Override public boolean isViewFromObject(View arg0, Object arg1) { return arg0 == arg1; } @Override public void destroyItem(ViewGroup container, int position, Object object) { View view = (View) object; ((ViewPager) container).removeView(view); //隐藏页面内的item clearViewContent((ViewHolder) view.getTag()); //添加到缓存 cacheViews.add(view); } @Override public int getItemPosition(Object object) { return POSITION_NONE; } @Override public Object instantiateItem(ViewGroup container, int position) { View view = null; ViewHolder viewHolder = null; //没有缓存的view时新建一个用来显示 if (cacheViews.isEmpty()) { view = mInflater.inflate(R.layout.viewpager_item, container, false); viewHolder = new ViewHolder(view); view.setTag(viewHolder); } else { //有缓存的view时取出使用 view = cacheViews.remove(0); viewHolder = (ViewHolder) view.getTag(); } //设置页面内的各item initItemData(viewHolder, view, position); container.addView(view); return view; } private void initItemData(ViewHolder viewHolder, View view, int position) { int totalInItemCount = singerList.size(); int tempitemInCount= (int) itemInCount; //每页显示10个item for (int i = 0; i < tempitemInCount; i++) { //计算当前页要显示的item在arraylist中的position。 int inItemPosition = position *tempitemInCount + i; //如果最后一页显示不满时跳出循环,后面的item不再显示 if (inItemPosition >= totalInItemCount) { break; } ItemEntity itemEntity = singerList.get(inItemPosition); switch (i) { case 0: viewHolder.bgIV1 .setBackgroundResource(R.mipmap.item_bg); viewHolder.titleTV1.setText(itemEntity.name); viewHolder.itemRL1.setVisibility(View.VISIBLE); viewHolder.itemRL1.setTag(itemEntity); viewHolder.itemRL1.setOnClickListener(this); break; case 1: viewHolder.bgIV2 .setBackgroundResource(R.mipmap.item_bg); viewHolder.titleTV2.setText(itemEntity.name); viewHolder.itemRL2.setVisibility(View.VISIBLE); viewHolder.itemRL2.setTag(itemEntity); viewHolder.itemRL2.setOnClickListener(this); break; case 2: viewHolder.bgIV3 .setBackgroundResource(R.mipmap.item_bg); viewHolder.titleTV3.setText(itemEntity.name); viewHolder.itemRL3.setVisibility(View.VISIBLE); viewHolder.itemRL3.setTag(itemEntity); viewHolder.itemRL3.setOnClickListener(this); break; case 3: viewHolder.bgIV4 .setBackgroundResource(R.mipmap.item_bg); viewHolder.titleTV4.setText(itemEntity.name); viewHolder.itemRL4.setVisibility(View.VISIBLE); viewHolder.itemRL4.setTag(itemEntity); viewHolder.itemRL4.setOnClickListener(this); break; case 4: viewHolder.bgIV5 .setBackgroundResource(R.mipmap.item_bg); viewHolder.titleTV5.setText(itemEntity.name); viewHolder.itemRL5.setVisibility(View.VISIBLE); viewHolder.itemRL5.setTag(itemEntity); viewHolder.itemRL5.setOnClickListener(this); break; case 5: viewHolder.bgIV6 .setBackgroundResource(R.mipmap.item_bg); viewHolder.titleTV6.setText(itemEntity.name); viewHolder.itemRL6.setVisibility(View.VISIBLE); viewHolder.itemRL6.setTag(itemEntity); viewHolder.itemRL6.setOnClickListener(this); break; case 6: viewHolder.bgIV7 .setBackgroundResource(R.mipmap.item_bg); viewHolder.titleTV7.setText(itemEntity.name); viewHolder.itemRL7.setVisibility(View.VISIBLE); viewHolder.itemRL7.setTag(itemEntity); viewHolder.itemRL7.setOnClickListener(this); break; case 7: viewHolder.bgIV8 .setBackgroundResource(R.mipmap.item_bg); viewHolder.titleTV8.setText(itemEntity.name); viewHolder.itemRL8.setVisibility(View.VISIBLE); viewHolder.itemRL8.setTag(itemEntity); viewHolder.itemRL8.setOnClickListener(this); break; case 8: viewHolder.bgIV9 .setBackgroundResource(R.mipmap.item_bg); viewHolder.titleTV9.setText(itemEntity.name); viewHolder.itemRL9.setVisibility(View.VISIBLE); viewHolder.itemRL9.setTag(itemEntity); viewHolder.itemRL9.setOnClickListener(this); break; case 9: viewHolder.bgIV10 .setBackgroundResource(R.mipmap.item_bg); viewHolder.titleTV10.setText(itemEntity.name); viewHolder.itemRL10.setVisibility(View.VISIBLE); viewHolder.itemRL10.setTag(itemEntity); viewHolder.itemRL10.setOnClickListener(this); break; default: break; } } } /** * 隐藏各item * @param viewHolder */ private void clearViewContent(ViewHolder viewHolder) { viewHolder.itemRL1.setVisibility(View.GONE); viewHolder.itemRL2.setVisibility(View.GONE); viewHolder.itemRL3.setVisibility(View.GONE); viewHolder.itemRL4.setVisibility(View.GONE); viewHolder.itemRL5.setVisibility(View.GONE); viewHolder.itemRL6.setVisibility(View.GONE); viewHolder.itemRL7.setVisibility(View.GONE); viewHolder.itemRL8.setVisibility(View.GONE); viewHolder.itemRL9.setVisibility(View.GONE); viewHolder.itemRL10.setVisibility(View.GONE); } @Override public void onClick(View arg0) { //点击到对应item ItemEntity itemEntity = (ItemEntity) arg0.getTag(); Toast.makeText(mContext, itemEntity.name, Toast.LENGTH_SHORT).show(); } /** * viewHolder */ static class ViewHolder { public ImageView bgIV1, bgIV2, bgIV3, bgIV4, bgIV5, bgIV6, bgIV7, bgIV8, bgIV9, bgIV10; public TextView titleTV1, titleTV2, titleTV3, titleTV4, titleTV5, titleTV6, titleTV7, titleTV8, titleTV9, titleTV10; public RelativeLayout itemRL1, itemRL2, itemRL3, itemRL4, itemRL5, itemRL6, itemRL7, itemRL8, itemRL9, itemRL10; public ViewHolder(View itemView) { bgIV1 = (ImageView) itemView .findViewById(R.id.fragment_music_singer_item_image_iv_one); titleTV1 = (TextView) itemView .findViewById(R.id.fragment_music_singer_item_name_tv_one); bgIV2 = (ImageView) itemView .findViewById(R.id.fragment_music_singer_item_image_iv_two); titleTV2 = (TextView) itemView .findViewById(R.id.fragment_music_singer_item_name_tv_two); bgIV3 = (ImageView) itemView .findViewById(R.id.fragment_music_singer_item_image_iv_three); titleTV3 = (TextView) itemView .findViewById(R.id.fragment_music_singer_item_name_tv_three); bgIV4 = (ImageView) itemView .findViewById(R.id.fragment_music_singer_item_image_iv_four); titleTV4 = (TextView) itemView .findViewById(R.id.fragment_music_singer_item_name_tv_four); bgIV5 = (ImageView) itemView .findViewById(R.id.fragment_music_singer_item_image_iv_five); titleTV5 = (TextView) itemView .findViewById(R.id.fragment_music_singer_item_name_tv_five); bgIV6 = (ImageView) itemView .findViewById(R.id.fragment_music_singer_item_image_iv_six); titleTV6 = (TextView) itemView .findViewById(R.id.fragment_music_singer_item_name_tv_six); bgIV7 = (ImageView) itemView .findViewById(R.id.fragment_music_singer_item_image_iv_seven); titleTV7 = (TextView) itemView .findViewById(R.id.fragment_music_singer_item_name_tv_seven); bgIV8 = (ImageView) itemView .findViewById(R.id.fragment_music_singer_item_image_iv_eight); titleTV8 = (TextView) itemView .findViewById(R.id.fragment_music_singer_item_name_tv_eight); bgIV9 = (ImageView) itemView .findViewById(R.id.fragment_music_singer_item_image_iv_nine); titleTV9 = (TextView) itemView .findViewById(R.id.fragment_music_singer_item_name_tv_nine); bgIV10 = (ImageView) itemView .findViewById(R.id.fragment_music_singer_item_image_iv_ten); titleTV10 = (TextView) itemView .findViewById(R.id.fragment_music_singer_item_name_tv_ten); itemRL1 = (RelativeLayout) itemView .findViewById(R.id.fragment_music_singer_item_one); itemRL2 = (RelativeLayout) itemView .findViewById(R.id.fragment_music_singer_item_two); itemRL3 = (RelativeLayout) itemView .findViewById(R.id.fragment_music_singer_item_three); itemRL4 = (RelativeLayout) itemView .findViewById(R.id.fragment_music_singer_item_four); itemRL5 = (RelativeLayout) itemView .findViewById(R.id.fragment_music_singer_item_five); itemRL6 = (RelativeLayout) itemView .findViewById(R.id.fragment_music_singer_item_six); itemRL7 = (RelativeLayout) itemView .findViewById(R.id.fragment_music_singer_item_seven); itemRL8 = (RelativeLayout) itemView .findViewById(R.id.fragment_music_singer_item_eight); itemRL9 = (RelativeLayout) itemView .findViewById(R.id.fragment_music_singer_item_nine); itemRL10 = (RelativeLayout) itemView .findViewById(R.id.fragment_music_singer_item_ten); } } }
2:ViewPager使用:
/** * @author Homgwu */ public class MainActivity extends Activity { private ViewPager mViewPager; private MainViewPagerAdapter mViewPagerAdapter; private List<ItemEntity> mItemEntityList=new ArrayList<ItemEntity>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); } private void initView(){ mViewPager= (ViewPager) findViewById(R.id.main_vp); initData(); mViewPagerAdapter=new MainViewPagerAdapter(mItemEntityList,this); //设置翻页动画 mViewPager.setPageTransformer(true,new DepthPageTransformer()); mViewPager.setAdapter(mViewPagerAdapter); } /** * 初始化数据 */ private void initData(){ for (int i=0;i<104;i++){ ItemEntity itemEntity=new ItemEntity(); itemEntity.name="Android"+i; mItemEntityList.add(itemEntity); } } }
3:动画代码:
public class DepthPageTransformer implements PageTransformer { private static float MIN_SCALE = 0.5f; /** * position参数指明给定页面相对于屏幕中心的位置。它是一个动态属性,会随着页面的滚动而改变。当一个页面填充整个屏幕是,它的值是0, * 当一个页面刚刚离开屏幕的右边时 * ,它的值是1。当两个也页面分别滚动到一半时,其中一个页面的位置是-0.5,另一个页面的位置是0.5。基于屏幕上页面的位置 * ,通过使用诸如setAlpha()、setTranslationX()、或setScaleY()方法来设置页面的属性,来创建自定义的滑动动画。 */ @Override public void transformPage(View view, float position) { int pageWidth = view.getWidth(); if (position < -1) { // [-Infinity,-1) // This page is way off-screen to the left. view.setAlpha(0); view.setTranslationX(0); } else if (position <= 0) { // [-1,0] // Use the default slide transition when // moving to the left page view.setAlpha(1); view.setTranslationX(0); view.setScaleX(1); view.setScaleY(1); } else if (position <= 1) { // (0,1] // Fade the page out. view.setAlpha(1 - position); // Counteract the default slide transition view.setTranslationX(pageWidth * -position); // Scale the page down (between MIN_SCALE and 1) float scaleFactor = MIN_SCALE + (1 - MIN_SCALE) * (1 - Math.abs(position)); view.setScaleX(scaleFactor); view.setScaleY(scaleFactor); } else { // (1,+Infinity] // This page is way off-screen to the right. view.setAlpha(0); view.setScaleX(1); view.setScaleY(1); } } }
完整Sample可以到如下地址下载:
1:http://download.csdn.net/detail/homg92/8584445