仿蘑菇街界面(2)

上一篇博客,博客地址http://blog.csdn.net/itbailei/article/details/38561297把基本的主界面框架已经搭建完毕,我们采用的基本框架为fragment进行页面之间的切换,底部菜单采用的是RadioButton。今天我们来重点来仿照一下第一个底部菜单“爱逛”,首先我们来分解一下功能区域:


1.功能区域分解

  (1) PageTabs左右切换菜单:这里我们使用第三方开源插件,不过需要自己进行修改,采用的是ViewPage进行页面的切换,左右滑动。

(2) 图片轮播:ViewGroup+Viewpage每一个ViewGroup存储一个按压效果的dot和一张图片,随着手指的滑动进行图片之间的切换,当然我们这里只使用五张图片。

(3)更新时间:这个不说了,就是设置时间,这里找不到图片我自己设定固定值,当然也可以通过代码设置。

(4)第一个列表,第二个列表,我们观察布局可知,下面2个布局的大小是分别占用了屏幕的一般,我们可以通过设置权值属性来设置大小,也就是

<span style="white-space:pre">		</span>android:layout_width="match_parent"android:layout_height="match_parent"android:layout_weight="2"


第一个布局是线性布局的,线性布局里面包括一个更新时间的一些TextView控件和一个GridView控件,第二个布局是一个单独的GridView控件

2.实现方式

(1) PageTabs:

第一个难点毋庸置疑就是PageTabs菜单,所幸这方面的开源组件挺多,我们可以使用郭霖大神推荐的PagerSlidingTabStrip,当然也要进行修改,修改包括横条的颜色。每一个PageTabs就是一个Fragment,因为放置这个PageTabs的本身就是一个Fragment,所以我们需要注意,在使用FragmentManager()的地方,必须要使用当前Fragment的子FragmentManager,否则会报错。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical" android:background="#EEEEEE"><com.blog.mogujie.tool.PagerSlidingTabStripandroid:id="@+id/tabs"android:layout_width="match_parent"android:layout_height="40dp" /><android.support.v4.view.ViewPagerandroid:id="@+id/pager"android:layout_width="match_parent"android:layout_height="wrap_content" /></LinearLayout>

PagerSlidingTabStrip为自定义控件,也就是第三方插件,ViewPager用来显示每一个页面的大小,但是注意到修改滚动条的长度,修改代码如下:

@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);if (isInEditMode() || tabCount == 0) {return;}final int height = getHeight();// draw underlinerectPaint.setColor(underlineColor);canvas.drawRect(0, height - underlineHeight, tabsContainer.getWidth(), height, rectPaint);// draw indicator linerectPaint.setColor(indicatorColor);// default: line below current tabView currentTab = tabsContainer.getChildAt(currentPosition);float lineLeft = currentTab.getLeft();float lineRight = currentTab.getRight();// if there is an offset, start interpolating left and right coordinates between current and next tabif (currentPositionOffset > 0f && currentPosition < tabCount - 1) {View nextTab = tabsContainer.getChildAt(currentPosition + 1);final float nextTabLeft = nextTab.getLeft();final float nextTabRight = nextTab.getRight();lineLeft = (currentPositionOffset * nextTabLeft + (1f - currentPositionOffset) * lineLeft);lineRight = (currentPositionOffset * nextTabRight + (1f - currentPositionOffset) * lineRight);}canvas.drawRect(lineLeft+100, height - indicatorHeight, lineRight-100, height, rectPaint);// draw dividerdividerPaint.setColor(dividerColor);for (int i = 0; i < tabCount - 1; i++) {View tab = tabsContainer.getChildAt(i);canvas.drawLine(tab.getRight(), dividerPadding, tab.getRight(), height - dividerPadding, dividerPaint);}}


主要看第这一行

canvas.drawRect(lineLeft+100, height - indicatorHeight, lineRight-100, height, rectPaint);

这行lineLeft+100,lineRight-100设置左右两边同时减小100的长度。

设置IndexFragment代码,该代码就是“精选”菜单区域Fragment,代码如下:

public class IndexFragment extends Fragment {private PagerSlidingTabStrip tabs;private DisplayMetrics dm;private String[] titles = { "精选", "搭配", "团购" };private ViewPager pager;private Fragment fragment;@Overridepublic void onActivityCreated(Bundle savedInstanceState) {super.onActivityCreated(savedInstanceState);dm = getResources().getDisplayMetrics();pager = (ViewPager) getView().findViewById(R.id.pager);tabs = (PagerSlidingTabStrip) getView().findViewById(R.id.tabs);//因为这里是嵌套使用fragment,所以这里不能直接传getActivity().getSupportFragmentManager(),他返回的是父fragment//应当使用当前fragment的FragmentManager(),返回当前fragmentpager.setAdapter(new PagerAdapter(this.getChildFragmentManager()));tabs.setViewPager(pager);InitTabsConfig();}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {return inflater.inflate(R.layout.fragment_index, container, false);}private void InitTabsConfig() {// 设置Tab是自动填充满屏幕的tabs.setShouldExpand(true);// 设置Tab的分割线是透明的tabs.setDividerColor(Color.TRANSPARENT);// 设置Tab底部线的高度tabs.setUnderlineHeight((int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, dm));// 设置Tab Indicator的高度tabs.setIndicatorHeight((int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 2, dm));// 设置Tab标题文字的大小tabs.setTextSize((int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 16, dm));// 设置Tab Indicator的颜色tabs.setIndicatorColor(getResources().getColor(R.color.red));// 设置选中Tab文字的颜色tabs.setSelectedTextColor(getResources().getColor(R.color.red));// 取消点击Tab时的背景色tabs.setTabBackground(0);}/*** 此处应当继承FragmentStatePagerAdapter* 在处理数据量较大的页面应当使用FragmentStatePagerAdapter,而不是FragmentPagerAdapter*/public class PagerAdapter extends FragmentStatePagerAdapter {public PagerAdapter(FragmentManager fm) {super(fm);}@Overridepublic CharSequence getPageTitle(int position) {return titles[position];}@Overridepublic int getCount() {return titles.length;}@Override  public Fragment getItem(int position) {switch (position) {case 0:fragment = new GoodsFargment();break;case 1:fragment = new ShopingsFragment();break;case 2:fragment = new MatchFragment();break;default:break;}return fragment;}}}

注意到代码,这里使用this.getChildFragmentManager()来表示当前的Fragment为子Fragment,不能使用getActivity().getSupportFragmentManager(),否则在切换时候会出错,第二个地方为第X行,这里继承的是 FragmentStatePagerAdapte,而非FragmentPagerAdapter。

 (2)图片轮播

  我们知道OnTouch事件的响应机制是逐级响应的,他会自动响应最底层的View,因此考虑到图片轮播需要左右滑动,而PageTabs也会左右滑动,并且PageTabs在图片轮转View的下一层,如果使用原生控件,系统会优先响应PageTabs而不会响应ViewPage的图片滑动;因此需要考虑,重写ViewPager控件,让该控件只会响应自己的左右滑动事件,其父视图的View左右滑动事件不响应。

public class ChildViewPager extends ViewPager {public ChildViewPager(Context context, AttributeSet attrs) {super(context, attrs);// TODO Auto-generated constructor stub}public ChildViewPager(Context context) {super(context);// TODO Auto-generated constructor stub}@Overridepublic boolean onInterceptTouchEvent(MotionEvent arg0) {// 当拦截触摸事件到达此位置的时候,返回true,// 说明将onTouch拦截在此控件,进而执行此控件的onTouchEventreturn true;}@Overridepublic boolean onTouchEvent(MotionEvent arg0) {getParent().requestDisallowInterceptTouchEvent(true);return super.onTouchEvent(arg0);}
}
 代码很少,主要是这一句getParent().requestDisallowInterceptTouchEvent( true);

设置父控件不响应OnTouch事件,而是交给当前控件的onTouchEvent事件,从而阻止PageTabS的滑动,响应当前控件的滑动事件

最后这是ViewPage的数据适配器,添加图片和点,进行左右的移动,定义ImgaePagerAdapter适配器类,其代码如下:

public class ImgaePagerAdapter extends PagerAdapter {ImageView[] mImageViews;public ImgaePagerAdapter(ImageView[] mImageViews) {this.mImageViews = mImageViews;}//获取要滑动的控件的数量@Overridepublic int getCount() {return Integer.MAX_VALUE;}//来判断显示的是否是同一张图片,这里我们将两个参数相比较返回即可  @Overridepublic boolean isViewFromObject(View arg0, Object arg1) {return arg0 == arg1;}//PagerAdapter如果滑动的图片超出了缓存的范围,就会调用这个方法,将图片销毁  @Overridepublic void destroyItem(View container, int position, Object object) {((ViewPager) container).removeView(mImageViews[position% mImageViews.length]);}/***循环读取图片,取余数*/@Overridepublic Object instantiateItem(View container, int position) {((ViewPager) container).addView(mImageViews[position% mImageViews.length], 0);return mImageViews[position % mImageViews.length];}}
循环图片的代码主要放在了instantiateItem中,该事件负责将图片添加到容器中,并返回该图片视图,并且每次返回的图片为当前的位置和图片的总长度取余数,通过取余数从而判断是否进行循环。

在Fragment中调用如下的代码对数据适配器的绑定

viewPager.setAdapter(new ImgaePagerAdapter(mImageViews));

viewPager.setOnPageChangeListener(this);

(3)控件

这里的列表控件用来显示精选衣服基本信息,使用图片加文字的组合方式,我们第一反应想到的是GridView控件,这个想法是对的;可是我们注意到“精选”菜单的整个布局是使用ScrollView控件来控制上下一起移动的,如果单纯使用GridView控件的话,GridView控件在ScrollView中会显示不正常,所以我们应当自定义GirdView让它不能滑动,并且适配ScrollView控件的大小。定义MyGridView控件:

public class ImgaePagerAdapter extends PagerAdapter {ImageView[] mImageViews;public ImgaePagerAdapter(ImageView[] mImageViews) {this.mImageViews = mImageViews;}//获取要滑动的控件的数量@Overridepublic int getCount() {return Integer.MAX_VALUE;}//来判断显示的是否是同一张图片,这里我们将两个参数相比较返回即可  @Overridepublic boolean isViewFromObject(View arg0, Object arg1) {return arg0 == arg1;}//PagerAdapter如果滑动的图片超出了缓存的范围,就会调用这个方法,将图片销毁  @Overridepublic void destroyItem(View container, int position, Object object) {((ViewPager) container).removeView(mImageViews[position% mImageViews.length]);}/***循环读取图片,取余数*/@Overridepublic Object instantiateItem(View container, int position) {((ViewPager) container).addView(mImageViews[position% mImageViews.length], 0);return mImageViews[position % mImageViews.length];}}
在绘制GridView控件大小的时候,通过设置MeasureSpec.AT_MOST参数来指定到想要控件高度,通过onMeasure事件来绘制GridView。在XML布局中引用<com.blog.mogujie.tool.MyGridView ../>,布局文件代码太长就不贴出来了,待会在后面提供代码下载链接。

然后再定义该GridView文件的适配器,代码如下,注意GridView的优化设置:

public class GrdoneAdapter extends BaseAdapter{private Context mContext;private List<GrdOneInfo> mGrdOneInfoList;public GrdoneAdapter(Context mContext,List<GrdOneInfo> mGrdOneInfoList){this.mContext=mContext;this.mGrdOneInfoList=mGrdOneInfoList;}@Overridepublic int getCount() {// TODO Auto-generated method stubreturn mGrdOneInfoList.size();}@Overridepublic Object getItem(int position) {// TODO Auto-generated method stubreturn position;}@Overridepublic long getItemId(int position) {// TODO Auto-generated method stubreturn position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {View view = convertView;final ViewHolder holder;if (convertView == null) {view = ((Activity) mContext).getLayoutInflater().inflate(R.layout.item_grd1, parent, false);holder = new ViewHolder();holder.image = (ImageView) view.findViewById(R.id.grdimage);holder.brife= (TextView) view.findViewById(R.id.brife1);holder.price= (TextView) view.findViewById(R.id.price);holder.marks= (TextView) view.findViewById(R.id.marks);view.setTag(holder);} else {holder = (ViewHolder) view.getTag();}holder.image.setImageResource(mGrdOneInfoList.get(position).imagePath);if(mGrdOneInfoList.get(position).brife.length()>50){holder.brife.setText(mGrdOneInfoList.get(position).brife.subSequence(0, 30)+"...");}else{holder.brife.setText(mGrdOneInfoList.get(position).brife);}holder.price.setText(mGrdOneInfoList.get(position).price);holder.marks.setText(mGrdOneInfoList.get(position).marksNum);return view;}static class ViewHolder{ImageView image;TextView brife;TextView price;TextView marks;}
}
最终效果如下:

 


资源地址为点击打开链接,今天到这里。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/352227.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

仿蘑菇街界面应用(1)

看到郭霖大神仿微信主界面的博客&#xff0c;在佩服大神文笔犀利、讲解详尽、代码风骚之余&#xff0c;也想在上班无所事事时&#xff0c;找点有意思的东西玩玩&#xff0c;蘑菇街作为中国最大女性购物社区&#xff0c;其APP的设计水平也毋庸置疑的&#xff0c;最近博客将连续来…

实现蘑菇街首页效果

打算出一个系列&#xff0c;专治现在市面上各种app的各种滑动不服系列&#xff0c;解决各种滑动冲突问题&#xff0c;现在已经发现了9种样式&#xff0c;打算一个一个一一破解&#xff0c;这是第一篇。 今天给大家带来的是高仿蘑菇街的首页&#xff0c;现在这种页面的格式很流…

设备指纹系列--基础篇

基础概念 618还没开始&#xff0c;但是又好像已经结束了…在这种电商大促的大节日前&#xff0c;电商行业客户一般会提前找到合适的设备指纹产品&#xff0c;去防止被“薅秃”。因为&#xff0c;黑灰产拥有专业的设备牧场&#xff0c;通过使用模拟器、刷机改机等手段&#xff…

仿蘑菇街个人主页

效果图&#xff1a; 看到效果图&#xff0c;第一想到的大致布局是一个scrollview嵌套一个viewpage&#xff0c;viewpage里面有一两个fragment或者写成一个fragment。但是fragment肯定包含两个布局&#xff0c;一个是含有图片(gridview)的listview&#xff0c;另一个布局是只含有…

App竞品分析报告:美丽说VS蘑菇街

1.产品概况 iOS App Store中国区iPhone免费-生活类排名&#xff08;最近3个月&#xff09; 数据来源&#xff1a;ann9.com 蘑菇街排名基本稳定在Top 10至20之间&#xff0c;美丽说在8月下旬后基本游离在Top 30外。 2015年6月活跃用户数比对-iOS端 数据说明&#xff1a;MAU为月…

社会化购物:Pinterest,Fancy还是美丽说,蘑菇街?

转自&#xff1a;网站分析在中国 原文地址&#xff1a;http://www.chinawebanalytics.cn/social-shopping-pinterest-or-fancy/ 【每期一句】越强烈的网络效应&#xff0c;越接近成功。 【前言】这篇文章是应 的邀请所做。很高兴能有机会与几年前一样&#xff0c;分析一个细分行…

仿蘑菇街项目

引言 仿蘑菇街的Vue.js项目是我学习vue.js做的第一个项目&#xff0c;今天来重温一下项目实现的功能&#xff0c;记录一下&#xff0c;方便以后查看。首先需要创建项目&#xff0c;本项目采用cli-3脚手架创建项目&#xff0c;采用默认安装模式&#xff0c;没有安装vue-router和…

高仿蘑菇街欢迎页

####蘑菇街欢迎页 ####高仿效果 这里这里…Demo下载地址 #####前言 本文将介绍如何对蘑菇街欢迎页效果进行分析&#xff0c;拆分&#xff0c;并一步步实现1个高仿版本&#xff0c;最重要的设计思路包括以下2点&#xff1a; 1.ViewPager切换时&#xff0c;通过offset偏移量动…

美丽说蘑菇街首页效果(UITableView和UIScrollerView联动)

作为一名菜鸟iOS开发程序员&#xff0c;第一次写文章&#xff0c;有点小激动&#xff01;进入正题&#xff0c;最近项目中有个需求&#xff0c;类似美丽说蘑菇街首页效果&#xff0c;在网上找了一些资料后自己研究了下终于搞定了&#xff01; 先看效果&#xff1a; 接下来详细…

【Linux】Nginx 优化与防盗链

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 Nginx 优化与防盗链 一、隐藏版本号方法一&#xff1a;修改配置文件方式方法二&#xff1a;修改源码文件&#xff0c;重新编译安装 二、修改用户与组三、缓存时间四、日志切割…

操作系统的最强入门科普(Unix/Linux篇)

今天这篇文章&#xff0c;我们来聊聊操作系统&#xff08;Operating System&#xff09;。 说到操作系统&#xff0c;大家都不会陌生。我们天天都在接触操作系统——用台式机或笔记本电脑&#xff0c;使用的是windows和macOS系统&#xff1b;用手机、平板电脑&#xff0c;则是a…

PDF文件无法编辑怎么办

PDF文件无法编辑是因为设置了编辑限制&#xff0c;只要在设置密码的地方输入密码把密码取消就可以自由编辑文件了。如果不知道密码或者忘记了密码&#xff0c;只能使用第三方的解密软件把密码解除掉&#xff0c;现在有很多PDF的辅助软件&#xff0c;可以在网上搜到很多&#xf…

SpringBoot实现服务器PDF文件的下载和预览功能

&#x1f345;程序员小王的博客&#xff1a;程序员小王的博客 &#x1f345; 欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; &#x1f345; 如有编辑错误联系作者&#xff0c;如果有比较好的文章欢迎分享给我&#xff0c;我会取其精华去其糟粕 &#x1f345;java自学的学习…

PDF文件不能编辑,有什么办法能够解决?

PDF文件打开之后发现不能编辑&#xff0c;很有可能是因为PDF文件设置了限制编辑。一般来说&#xff0c;想要解决问题&#xff0c;我们只需要将PDF编辑限制解除就可以了 但是大家有时候可能是不知道PDF密码的&#xff0c;那么在不知道PDF密码的情况下&#xff0c;如何解决不能编…

java利用itext编辑pdf

最近项目需要,在调研如何在pdf中增加标识字样,用来区分版本.最后确定用itext来实现 . itext的官网是:http://www.itextpdf.com/ 代码如下: Java代码 /** * authory kingviker * time : 2012-12-12 */ import java.io.FileOutputStream; import java.io.IOExcepti…

java设置pdf不可编辑_禁止编辑,但允许在Java iText / PDF中进行页面提取

我正在使用iText生成PDF文件 . 我想禁止编辑PDF&#xff0c;但允许读者提取页面 . 这是我设置加密的代码&#xff1a; writer.setEncryption(null, null, 0xffffffff, PdfWriter.STANDARD_ENCRYPTION_128); 第三个参数指定权限 . 我正在使用0xffffffff而不是单独的iText标志ALL…

HTML5 PDF 编辑,pdf.js的使用与改造

一、前期准备 1.1 需求描述 1.想让各个浏览器能显示服务器存放的PDF文件(主要是手机的浏览器) 2.想让项目结构如下:lib目录存放pdf.js等依赖文件,src存放要显示的pdf文件 想要的项目结构 3.这样我就可以将这个项目放到我网站的任何目录下,比如放到PDF或者别的文件夹下 PDF目…

如何免费编辑PDF文档?

我们都知道PDF文档不像Word文档一样可以直接编辑修改&#xff0c;想要编辑PDF文档&#xff0c;我们就需要借助专业的PDF编辑器。今天小编就给大家推荐一款可以免费编辑PDF文档的工具“金闪PDF编辑器”。 金闪PDF编辑器是一款功能齐全的强大的PDF工具&#xff0c;目前有移动端安…

PDF文件编辑并去除水印

我相信很多博友肯定被这个问题烦恼过&#xff0c;并且当初我自己也因为这个事情熬的掉了好几根头发&#xff0c;这件事就是PDF文件编辑过后会留下很严重的水印&#xff0c;并且无法除去&#xff0c;想去除就得花钱购买会员&#xff0c;想白嫖都没有办法&#xff0c;接下来我就为…

怎么编辑PDF文件?分享三种好用的编辑方法

怎么编辑PDF文件中的内容呢&#xff1f;大家在日常使用PDF文件的过程中肯定遇到过需要编辑文件的需求&#xff0c;因为我们不能保证每个文件中的内容都不会出错&#xff0c;问题是PDF文件不容易改动&#xff0c;我们怎么做才能够编辑PDF文件呢&#xff1f;不用着急&#xff0c;…