仿蘑菇街界面应用

简介:

蘑菇街作为中国最大女性购物社区,其APP的设计水平也毋庸置疑的,最近博客将连续来仿造一个蘑菇街的APP的界面设计。

(1)准备工作

  在阅读郭霖大神的博客时有人问里面使用的美工素材怎么得到的,其实很简单,下载一个APP,把APK格式修改成rar后解压,你会在目录下看到所有的素材。

        随后,看看APP的界面:

      

第一个是启动界面,第二个是主界面,先来看第一个界面。

(1)启动界面(Splash)。

启动界面也叫Splash界面,是APP启动时的第一画面,主要用于介绍应用、宣传或者加载数据,或者兼而有之。这里之所以要单独拿出来是因为这个应用有个独特的,它的LOGO是透明渐变出现的,也就是淡入效果,我们知道ANDROID主要有四种动画:透明动画、缩放、位移、旋转,分别使用的AlphaAnimation、ScaleAnimation、TranslateAnimation、RotateAnimation,这里我们使用AlphaAnimation。

界面布局很简单,如activity_loading.xml:

[html]  view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:orientation="vertical"   
  6.     android:gravity="center"  
  7.     android:background="@drawable/init_bg">  
  8.     <ImageView   
  9.         android:id="@+id/logo"  
  10.         android:layout_width="wrap_content"  
  11.         android:layout_height="wrap_content"  
  12.         android:src="@drawable/init_logo"/>  
  13. </LinearLayout>  

新建一个LoadingActivity类:如下代码:

[java]  view plain copy
  1. public class LoadingActivity extends Activity{  
  2.       
  3.     @Override  
  4.     protected void onCreate(Bundle savedInstanceState) {  
  5.          super.onCreate(savedInstanceState);  
  6.          //设置全屏  
  7.          this.requestWindowFeature(Window.FEATURE_NO_TITLE);  
  8.          this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);  
  9.          setContentView(R.layout.activity_loading);  
  10.          ImageView view =(ImageView) findViewById(R.id.logo);  
  11.          AlphaAnimation aa = new AlphaAnimation(0.01f,1.0f);//透明度变化  
  12.          aa.setDuration(1500);//设置渐变时间  
  13.          view.startAnimation(aa);//设置渐变的view  
  14.          aa.setAnimationListener(new AnimationListener(){  
  15.              //动画结束后自动执行  
  16.             @Override  
  17.             public void onAnimationEnd(Animation arg0) {  
  18.                 redirectTo();  
  19.             }  
  20.             @Override  
  21.             public void onAnimationRepeat(Animation animation) {  
  22.                   
  23.             }  
  24.             @Override  
  25.             public void onAnimationStart(Animation animation) {  
  26.                   
  27.             }  
  28.                                                                             
  29.          });  
  30.     }  
  31.       
  32.     /** 
  33.      * 跳转到登陆界面 
  34.      */  
  35.     private void redirectTo(){         
  36.         Intent intent = new Intent(this, MainActivity.class);  
  37.         startActivity(intent);  
  38.         finish();  
  39.     }  
  40.   
  41.       
  42. }  

注意2个地方:a. AlphaAnimation aa = new AlphaAnimation(0.01f,1.0f); 构造方法:AlphaAnimation(float fromAlpha, float toAlpha),表示从透明度0.01到1.0的渐变,我们知道0.0表示全透明,1.0表示完全不透明.

  b. onAnimationEnd方法,顾名思义,表示:在动画结束后自动执行这个方法,这里当然是跳转到主界面了。运行后其效果如下:


是不是很简单,以后做启动画面都可以采用类似的方法。

总结要点:AlphaAnimation类

(1)主界面。

看看原图,如下:


中间的内容先不管,我们看ActionBar和底部菜单,上面是一个自定义的ActionBar,下面是一个切换菜单,而且下面菜单在改变的时候上面的ActionBar也在变。我们这里采用的设计方法是fragment+activity混合使用,底部菜单使用RadioButton,中间留出一个活动的fragment

先来看ActionBar,观察发现ActionBar分为2类,第一个是图片标题,另外一个是文字标题。

所以自定义的actionBar需要2个xml布局文件,分别命名为:actionbar_index.xml和actionbar_usu.xml

其XML布局分别为:actionbar_index.xml

[html]  view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="fill_parent"  
  5.     android:id="@+id/index_action_layout"  
  6.     android:background="@drawable/title_bg">  
  7.       
  8.   <ImageButton  
  9.     android:id="@+id/btn_slideMenu"  
  10.     android:layout_width="wrap_content"  
  11.     android:layout_height="match_parent"  
  12.     android:layout_gravity="center"  
  13.     android:background="@android:color/transparent"  
  14.     android:clickable="true"  
  15.     android:paddingLeft="8dip"  
  16.     android:src="@drawable/index_logo" />  
  17.                  
  18.    <ImageButton android:id="@+id/btn_main_qrcode"  
  19.            android:layout_width="wrap_content"  
  20.            android:layout_height="match_parent"  
  21.            android:background="@android:color/transparent"  
  22.            android:src="@drawable/icon_qc"  
  23.            android:paddingRight="8dip"  
  24.            android:clickable="true"  
  25.            android:layout_gravity="right|center_vertical"/>    
  26. </FrameLayout>  
actionbar_usu.xml

[html]  view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="fill_parent"  
  5.     android:id="@+id/index_action_layout"  
  6.     android:background="@drawable/title_bg">  
  7.     <TextView   
  8.         android:id="@+id/tv_title"  
  9.         android:layout_width="wrap_content"  
  10.         android:layout_height="match_parent"  
  11.         android:layout_gravity="center"  
  12.         android:gravity="center"  
  13.         android:textColor="@color/white1"  
  14.         android:textSize="@dimen/actionbar_title"  
  15.         android:background="@android:color/transparent"  
  16.         android:clickable="true"  
  17.         android:paddingLeft="8dip"  
  18.        />  
  19.     
  20. </FrameLayout>  
这个不多讲,唯一值得注意的是需要使用FrameLayout来布局,其中一些strings 、colors以及dimens是自己定义的最后我会将代码传上去。
新建一个ActionBarTool工具类,主要用来设置每个界面的ActionBar,代码如下:

[java]  view plain copy
  1. public class ActionBarTool {  
  2.     Activity activity;  
  3.     public ActionBarTool(Activity activity){  
  4.         this.activity=activity;  
  5.     }  
  6.     /** 
  7.      * 设置主界面的Index 
  8.      */  
  9.     public void setIndexActionBar(){  
  10.         ActionBar actionBar=activity.getActionBar();         
  11.         ActionBar.LayoutParams params=new ActionBar.LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT,Gravity.CENTER );  
  12.         View view=LayoutInflater.from(activity).inflate(R.layout.actionbar_index, null);  
  13.         actionBar.setCustomView(view,params);  
  14.         actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);  
  15.         actionBar.setDisplayShowCustomEnabled(true);  
  16.     }  
  17.       
  18.     /** 
  19.      * 设置其他界面的ActionBar 
  20.      * @param title 标题 
  21.      */  
  22.     public void setUsuActionBar(String title){  
  23.         ActionBar actionBar=activity.getActionBar();         
  24.         ActionBar.LayoutParams params=new ActionBar.LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT,Gravity.CENTER );  
  25.         View view=LayoutInflater.from(activity).inflate(R.layout.actionbar_usu, null);  
  26.         actionBar.setCustomView(view,params);  
  27.         actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);  
  28.         actionBar.setDisplayShowCustomEnabled(true);  
  29.         TextView tv_title=(TextView)activity.findViewById(R.id.tv_title);  
  30.         tv_title.setText(title);  
  31.     }  
  32. }  
这是自定义目录的一般做法,但是安卓的设计文档里面是不推荐这么使用的,因为这样会破坏ActionBar的一些灵活性,而且到后期很难管理,这里之所以使用是因为文字居中需要自己定义视图,其实可以直接用背景来代替,这样也能实现文字居中,而且不会破坏actonbar的灵活性。

再来看看底部菜单:main.XML文件如下

[html]  view plain copy
  1. <?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:background="#fff"  
  6.     android:orientation="vertical" >  
  7.     <FrameLayout   
  8.         android:id="@+id/content"  
  9.         android:layout_width="match_parent"  
  10.         android:layout_height="match_parent"  
  11.         android:layout_weight="1"  
  12.         android:background="#fff"/>  
  13.    <RadioGroup   
  14.         android:layout_width="match_parent"  
  15.         android:layout_height="match_parent"  
  16.         android:background="@color/gray"  
  17.         android:layout_marginTop="2dp"  
  18.         android:layout_weight="10"  
  19.         android:gravity="center"  
  20.         android:orientation="horizontal" >  
  21.     <RadioButton  
  22.         android:id="@+id/fragment_index"  
  23.         android:layout_width="match_parent"  
  24.         android:layout_height="wrap_content"  
  25.         android:layout_weight="1"  
  26.         android:button="@null"  
  27.         android:drawableTop="@drawable/index_indicator"  
  28.         android:gravity="center"  
  29.         android:text="@string/index"  
  30.         android:textColor="@color/white"  
  31.         android:textSize="12sp" />  
  32.      
  33.     <RadioButton  
  34.         android:id="@+id/fragment_category"  
  35.         android:layout_width="match_parent"  
  36.          android:layout_height="wrap_content"  
  37.         android:layout_weight="1"  
  38.         android:button="@null"  
  39.         android:drawableTop="@drawable/category_indicator"  
  40.         android:gravity="center"  
  41.         android:text="@string/category"  
  42.         android:textColor="@color/white"  
  43.         android:textSize="12sp" />  
  44.     <RadioButton  
  45.         android:id="@+id/fragment_discovery"  
  46.         android:layout_width="match_parent"  
  47.         android:layout_height="wrap_content"  
  48.         android:layout_weight="1"  
  49.         android:button="@null"  
  50.         android:drawableTop="@drawable/discovery"  
  51.         android:gravity="center"  
  52.         android:text="@string/discovery"  
  53.         android:textColor="@color/white"  
  54.         android:textSize="12sp" />  
  55.   
  56.     <RadioButton  
  57.         android:id="@+id/fragment_cart"  
  58.         android:layout_width="match_parent"  
  59.          android:layout_height="wrap_content"  
  60.         android:layout_weight="1"  
  61.         android:button="@null"  
  62.         android:drawablePadding="3dip"  
  63.         android:drawableTop="@drawable/cart_tab_icon_dark"  
  64.         android:gravity="center"  
  65.         android:text="@string/cart"  
  66.         android:textColor="@color/white"  
  67.         android:textSize="12sp" />  
  68.       
  69.     <RadioButton  
  70.         android:id="@+id/fragment_my"  
  71.         android:layout_width="match_parent"  
  72.           android:layout_height="wrap_content"  
  73.         android:layout_weight="1"  
  74.         android:button="@null"  
  75.         android:drawablePadding="3dip"  
  76.         android:drawableTop="@drawable/my_indicator"  
  77.         android:gravity="center"  
  78.         android:text="@string/my"  
  79.         android:textColor="@color/white"  
  80.         android:textSize="12sp" />  
  81. </RadioGroup>  
  82. </LinearLayout>  
RadioGroup +活动的FrameLayout 构成了整个页面的布局。

接下来是mian 页面的切换代码,MainActivity.java

[java]  view plain copy
  1. public class MainActivity extends FragmentActivity {  
  2.   
  3.     RadioButton btn_index, btn_category, btn_discovery, btn_cart, btn_my;  
  4.     private Fragment fragment;  
  5.     FragmentManager fragmentManager;  
  6.     ActionBarTool actionbarTool;  
  7.     @Override  
  8.     protected void onCreate(Bundle savedInstanceState) {  
  9.         super.onCreate(savedInstanceState);  
  10.         setContentView(R.layout.main);  
  11.         InitUI();  
  12.     }  
  13.       
  14.     /** 
  15.      * 初始化UI界面 
  16.      */  
  17.     private void InitUI() {  
  18.         actionbarTool=new ActionBarTool(this);  
  19.         btn_index = (RadioButton) findViewById(R.id.fragment_index);  
  20.         btn_category = (RadioButton) findViewById(R.id.fragment_category);  
  21.         btn_discovery = (RadioButton) findViewById(R.id.fragment_discovery);  
  22.         btn_cart = (RadioButton) findViewById(R.id.fragment_cart);  
  23.         btn_my = (RadioButton) findViewById(R.id.fragment_my);  
  24.         btn_my.setOnClickListener(new switchFragment());  
  25.         btn_cart.setOnClickListener(new switchFragment());  
  26.         btn_discovery.setOnClickListener(new switchFragment());  
  27.         btn_category.setOnClickListener(new switchFragment());  
  28.         btn_index.setOnClickListener(new switchFragment());  
  29.         fragment = new IndexFragment();  
  30.         actionbarTool.setIndexActionBar();  
  31.         btn_index.setTextColor(getResources().getColor(R.color.red));  
  32.         btn_index.setCompoundDrawablesWithIntrinsicBounds(null,   
  33.                 getResources().getDrawable(R.drawable.index_indicator_s), nullnull);  
  34.         fragmentManager =getSupportFragmentManager();  
  35.         if (fragment != null) {  
  36.             fragmentManager.beginTransaction()  
  37.                     .replace(R.id.content, fragment).commit();  
  38.         } else {  
  39.             Log.e("MainActivity""Error in creating fragment");  
  40.         }  
  41.     }  
  42.   
  43.     /** 
  44.      * 切换fragment 
  45.      * @author zw.yan 
  46.      *  
  47.      */  
  48.     class switchFragment implements View.OnClickListener {  
  49.         @Override  
  50.         public void onClick(View arg0) {  
  51.             InitBg();//每一次都初始化按钮样式  
  52.             switch (arg0.getId()) {  
  53.             case R.id.fragment_index:  
  54.                 fragment = new IndexFragment();  
  55.                 actionbarTool.setIndexActionBar();  
  56.                 btn_index.setTextColor(getResources().getColor(R.color.red));  
  57.                 btn_index.setCompoundDrawablesWithIntrinsicBounds(null,   
  58.                         getResources().getDrawable(R.drawable.index_indicator_s), nullnull);  
  59.                 break;  
  60.             case R.id.fragment_category:  
  61.                 fragment = new CategoryFragment();  
  62.                 actionbarTool.setUsuActionBar("分类");  
  63.                 btn_category.setTextColor(getResources().getColor(R.color.red));  
  64.                 btn_category.setCompoundDrawablesWithIntrinsicBounds(null,   
  65.                         getResources().getDrawable(R.drawable.category_indicator_s), nullnull);  
  66.                 break;  
  67.             case R.id.fragment_discovery:  
  68.                 fragment = new DiscoveryFragment();  
  69.                 actionbarTool.setUsuActionBar("发现");  
  70.                 btn_discovery.setTextColor(getResources().getColor(R.color.red));  
  71.                 btn_discovery.setCompoundDrawablesWithIntrinsicBounds(null,   
  72.                         getResources().getDrawable(R.drawable.discovery_s), nullnull);  
  73.                 break;  
  74.             case R.id.fragment_cart:  
  75.                 fragment = new CartFragment();  
  76.                 actionbarTool.setUsuActionBar("我的购物车");  
  77.                 btn_cart.setTextColor(getResources().getColor(R.color.red));  
  78.                 btn_cart.setCompoundDrawablesWithIntrinsicBounds(null,   
  79.                         getResources().getDrawable(R.drawable.cart_tab_icon_red), nullnull);  
  80.                 break;  
  81.             case R.id.fragment_my:  
  82.                 fragment = new MyFragment();  
  83.                 //actionbarTool.setUsuActionBar("我的");  
  84.                 btn_my.setTextColor(getResources().getColor(R.color.red));  
  85.                 btn_my.setCompoundDrawablesWithIntrinsicBounds(null,   
  86.                         getResources().getDrawable(R.drawable.my_indicator_s), nullnull);  
  87.                 break;  
  88.             }  
  89.             if (fragment != null) {  
  90.                 fragmentManager.beginTransaction()  
  91.                         .replace(R.id.content, fragment).commit();  
  92.             } else {  
  93.                 Log.e("MainActivity""Error in creating fragment");  
  94.             }  
  95.   
  96.         }  
  97.   
  98.     }  
  99.       
  100.     /** 
  101.      * 初始化按钮样式 
  102.      *  
  103.      */  
  104.     private void InitBg(){  
  105.         btn_index.setTextColor(getResources().getColor(R.color.white));  
  106.         btn_index.setCompoundDrawablesWithIntrinsicBounds(null,   
  107.                 getResources().getDrawable(R.drawable.index_indicator), nullnull);  
  108.         btn_category.setTextColor(getResources().getColor(R.color.white));  
  109.         btn_category.setCompoundDrawablesWithIntrinsicBounds(null,   
  110.                 getResources().getDrawable(R.drawable.category_indicator), nullnull);  
  111.         btn_cart.setTextColor(getResources().getColor(R.color.white));  
  112.         btn_cart.setCompoundDrawablesWithIntrinsicBounds(null,   
  113.                 getResources().getDrawable(R.drawable.cart_tab_icon_dark), nullnull);  
  114.         btn_discovery.setTextColor(getResources().getColor(R.color.white));  
  115.         btn_discovery.setCompoundDrawablesWithIntrinsicBounds(null,   
  116.                 getResources().getDrawable(R.drawable.discovery), nullnull);  
  117.         btn_my.setTextColor(getResources().getColor(R.color.white));  
  118.         btn_my.setCompoundDrawablesWithIntrinsicBounds(null,   
  119.                 getResources().getDrawable(R.drawable.my_indicator), nullnull);  
  120.     }  
  121.       
  122.     @Override  
  123.     public boolean onCreateOptionsMenu(Menu menu) {  
  124.         return true;  
  125.     }  
  126.   
  127. }  

其他页面的fragment.类似,布局文件是空布局:

[java]  view plain copy
  1. public class IndexFragment extends Fragment{  
  2.   
  3.     @Override  
  4.     public void onActivityCreated(Bundle savedInstanceState) {  
  5.         // TODO Auto-generated method stub  
  6.         super.onActivityCreated(savedInstanceState);  
  7.     }  
  8.   
  9.     @Override  
  10.     public View onCreateView(LayoutInflater inflater, ViewGroup container,  
  11.             Bundle savedInstanceState) {  
  12.         return inflater.inflate(R.layout.fragment_index, container, false);  
  13.     }  
  14.   
  15.       
  16.       
  17. }  
上面的主要代码是:switchFragment类,是切换fragment的,通过fragmentManager.beginTransaction().replace(R.id.content, fragment).commit();来替换当前的fragment,在替换的时候需要先使用 InitBg()初始化按钮的颜色,在来改变按钮的字体颜色和图标。效果如下:


今天我们来重点来仿照一下第一个底部菜单“爱逛”,首先我们来分解一下功能区域:


1.功能区域分解

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

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

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

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

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. <span style="white-space:pre">        </span>android:layout_width="match_parent"  
  2.         android:layout_height="match_parent"  
  3.         android:layout_weight="2"  


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

2.实现方式

(1) PageTabs:

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

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:orientation="vertical"   
  6.     android:background="#EEEEEE">  
  7.       
  8.  <com.blog.mogujie.tool.PagerSlidingTabStrip  
  9.         android:id="@+id/tabs"  
  10.         android:layout_width="match_parent"  
  11.         android:layout_height="40dp" />  
  12.   
  13.  <android.support.v4.view.ViewPager  
  14.         android:id="@+id/pager"  
  15.         android:layout_width="match_parent"  
  16.         android:layout_height="wrap_content" />  
  17.    
  18. </LinearLayout>  

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

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. @Override  
  2.     protected void onDraw(Canvas canvas) {  
  3.         super.onDraw(canvas);  
  4.   
  5.         if (isInEditMode() || tabCount == 0) {  
  6.             return;  
  7.         }  
  8.   
  9.         final int height = getHeight();  
  10.           
  11.         // draw underline  
  12.         rectPaint.setColor(underlineColor);  
  13.         canvas.drawRect(0, height - underlineHeight, tabsContainer.getWidth(), height, rectPaint);  
  14.   
  15.         // draw indicator line  
  16.         rectPaint.setColor(indicatorColor);  
  17.   
  18.         // default: line below current tab  
  19.         View currentTab = tabsContainer.getChildAt(currentPosition);  
  20.         float lineLeft = currentTab.getLeft();  
  21.         float lineRight = currentTab.getRight();  
  22.   
  23.         // if there is an offset, start interpolating left and right coordinates between current and next tab  
  24.         if (currentPositionOffset > 0f && currentPosition < tabCount - 1) {  
  25.   
  26.             View nextTab = tabsContainer.getChildAt(currentPosition + 1);  
  27.             final float nextTabLeft = nextTab.getLeft();  
  28.             final float nextTabRight = nextTab.getRight();  
  29.   
  30.             lineLeft = (currentPositionOffset * nextTabLeft + (1f - currentPositionOffset) * lineLeft);  
  31.             lineRight = (currentPositionOffset * nextTabRight + (1f - currentPositionOffset) * lineRight);  
  32.         }  
  33.   
  34.         canvas.drawRect(lineLeft+100, height - indicatorHeight, lineRight-100, height, rectPaint);  
  35.   
  36.         // draw divider  
  37.   
  38.         dividerPaint.setColor(dividerColor);  
  39.         for (int i = 0; i < tabCount - 1; i++) {  
  40.             View tab = tabsContainer.getChildAt(i);  
  41.             canvas.drawLine(tab.getRight(), dividerPadding, tab.getRight(), height - dividerPadding, dividerPaint);  
  42.         }  
  43.     }  


主要看第这一行

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

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

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

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public class IndexFragment extends Fragment {  
  2.     private PagerSlidingTabStrip tabs;  
  3.     private DisplayMetrics dm;  
  4.     private String[] titles = { "精选""搭配""团购" };  
  5.     private ViewPager pager;  
  6.     private Fragment fragment;  
  7.     @Override  
  8.     public void onActivityCreated(Bundle savedInstanceState) {  
  9.         super.onActivityCreated(savedInstanceState);  
  10.         dm = getResources().getDisplayMetrics();  
  11.         pager = (ViewPager) getView().findViewById(R.id.pager);  
  12.         tabs = (PagerSlidingTabStrip) getView().findViewById(R.id.tabs);  
  13.         //因为这里是嵌套使用fragment,所以这里不能直接传getActivity().getSupportFragmentManager(),他返回的是父fragment  
  14.         //应当使用当前fragment的FragmentManager(),返回当前fragment  
  15.         pager.setAdapter(new PagerAdapter(this.getChildFragmentManager()));  
  16.         tabs.setViewPager(pager);  
  17.         InitTabsConfig();  
  18.     }  
  19.   
  20.     @Override  
  21.     public View onCreateView(LayoutInflater inflater, ViewGroup container,  
  22.             Bundle savedInstanceState) {  
  23.         return inflater.inflate(R.layout.fragment_index, container, false);  
  24.     }  
  25.       
  26.     private void InitTabsConfig() {  
  27.         // 设置Tab是自动填充满屏幕的  
  28.         tabs.setShouldExpand(true);  
  29.         // 设置Tab的分割线是透明的  
  30.         tabs.setDividerColor(Color.TRANSPARENT);  
  31.         // 设置Tab底部线的高度  
  32.         tabs.setUnderlineHeight((int) TypedValue.applyDimension(  
  33.                 TypedValue.COMPLEX_UNIT_DIP, 1, dm));  
  34.         // 设置Tab Indicator的高度  
  35.         tabs.setIndicatorHeight((int) TypedValue.applyDimension(  
  36.                 TypedValue.COMPLEX_UNIT_DIP, 2, dm));  
  37.         // 设置Tab标题文字的大小  
  38.         tabs.setTextSize((int) TypedValue.applyDimension(  
  39.                 TypedValue.COMPLEX_UNIT_SP, 16, dm));  
  40.         // 设置Tab Indicator的颜色  
  41.         tabs.setIndicatorColor(getResources().getColor(R.color.red));  
  42.         // 设置选中Tab文字的颜色  
  43.         tabs.setSelectedTextColor(getResources().getColor(R.color.red));  
  44.         // 取消点击Tab时的背景色  
  45.         tabs.setTabBackground(0);  
  46.     }  
  47.   
  48.     /** 
  49.      * 此处应当继承FragmentStatePagerAdapter 
  50.      * 在处理数据量较大的页面应当使用FragmentStatePagerAdapter,而不是FragmentPagerAdapter 
  51.      */  
  52.     public class PagerAdapter extends FragmentStatePagerAdapter {  
  53.         public PagerAdapter(FragmentManager fm) {  
  54.             super(fm);  
  55.         }  
  56.   
  57.         @Override  
  58.         public CharSequence getPageTitle(int position) {  
  59.             return titles[position];  
  60.         }  
  61.   
  62.         @Override  
  63.         public int getCount() {  
  64.             return titles.length;  
  65.         }  
  66.           
  67.         @Override    
  68.         public Fragment getItem(int position) {  
  69.             switch (position) {  
  70.                 case 0:  
  71.                     fragment = new GoodsFargment();  
  72.                     break;  
  73.                 case 1:  
  74.                     fragment = new ShopingsFragment();  
  75.                     break;  
  76.                 case 2:  
  77.                     fragment = new MatchFragment();  
  78.                     break;  
  79.                 default:  
  80.                     break;  
  81.             }  
  82.             return fragment;  
  83.         }  
  84.   
  85.     }  
  86.   
  87. }  

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

 (2)图片轮播

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

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public class ChildViewPager extends ViewPager {  
  2.     public ChildViewPager(Context context, AttributeSet attrs) {  
  3.         super(context, attrs);  
  4.         // TODO Auto-generated constructor stub  
  5.     }  
  6.   
  7.     public ChildViewPager(Context context) {  
  8.         super(context);  
  9.         // TODO Auto-generated constructor stub  
  10.     }  
  11.   
  12.     @Override  
  13.     public boolean onInterceptTouchEvent(MotionEvent arg0) {  
  14.         // 当拦截触摸事件到达此位置的时候,返回true,  
  15.         // 说明将onTouch拦截在此控件,进而执行此控件的onTouchEvent  
  16.         return true;  
  17.     }  
  18.   
  19.   
  20.     @Override  
  21.     public boolean onTouchEvent(MotionEvent arg0) {  
  22.         getParent().requestDisallowInterceptTouchEvent(true);  
  23.         return super.onTouchEvent(arg0);  
  24.     }  
  25. }  
 代码很少,主要是这一句getParent().requestDisallowInterceptTouchEvent( true );

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

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

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public class ImgaePagerAdapter extends PagerAdapter {  
  2.   
  3.     ImageView[] mImageViews;  
  4.   
  5.     public ImgaePagerAdapter(ImageView[] mImageViews) {  
  6.         this.mImageViews = mImageViews;  
  7.     }  
  8.     //获取要滑动的控件的数量  
  9.     @Override  
  10.     public int getCount() {  
  11.         return Integer.MAX_VALUE;  
  12.     }  
  13.     //来判断显示的是否是同一张图片,这里我们将两个参数相比较返回即可    
  14.     @Override  
  15.     public boolean isViewFromObject(View arg0, Object arg1) {  
  16.         return arg0 == arg1;  
  17.     }  
  18.     //PagerAdapter如果滑动的图片超出了缓存的范围,就会调用这个方法,将图片销毁    
  19.     @Override  
  20.     public void destroyItem(View container, int position, Object object) {  
  21.           
  22.         ((ViewPager) container).removeView(mImageViews[position  
  23.                 % mImageViews.length]);  
  24.   
  25.     }  
  26.   
  27.     /** 
  28.      *循环读取图片,取余数 
  29.      */  
  30.     @Override  
  31.     public Object instantiateItem(View container, int position) {  
  32.         ((ViewPager) container).addView(mImageViews[position  
  33.                 % mImageViews.length], 0);  
  34.         return mImageViews[position % mImageViews.length];  
  35.     }  
  36.   
  37. }  
循环图片的代码主要放在了instantiateItem中,该事件负责将图片添加到容器中,并返回该图片视图,并且每次返回的图片为当前的位置和图片的总长度取余数,通过取余数从而判断是否进行循环。

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

viewPager.setAdapter(new ImgaePagerAdapter(mImageViews));

viewPager.setOnPageChangeListener(this);

(3)控件

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

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public class ImgaePagerAdapter extends PagerAdapter {  
  2.   
  3.     ImageView[] mImageViews;  
  4.   
  5.     public ImgaePagerAdapter(ImageView[] mImageViews) {  
  6.         this.mImageViews = mImageViews;  
  7.     }  
  8.     //获取要滑动的控件的数量  
  9.     @Override  
  10.     public int getCount() {  
  11.         return Integer.MAX_VALUE;  
  12.     }  
  13.     //来判断显示的是否是同一张图片,这里我们将两个参数相比较返回即可    
  14.     @Override  
  15.     public boolean isViewFromObject(View arg0, Object arg1) {  
  16.         return arg0 == arg1;  
  17.     }  
  18.     //PagerAdapter如果滑动的图片超出了缓存的范围,就会调用这个方法,将图片销毁    
  19.     @Override  
  20.     public void destroyItem(View container, int position, Object object) {  
  21.           
  22.         ((ViewPager) container).removeView(mImageViews[position  
  23.                 % mImageViews.length]);  
  24.   
  25.     }  
  26.   
  27.     /** 
  28.      *循环读取图片,取余数 
  29.      */  
  30.     @Override  
  31.     public Object instantiateItem(View container, int position) {  
  32.         ((ViewPager) container).addView(mImageViews[position  
  33.                 % mImageViews.length], 0);  
  34.         return mImageViews[position % mImageViews.length];  
  35.     }  
  36.   
  37. }  
在绘制GridView控件大小的时候,通过设置MeasureSpec.AT_MOST参数来指定到想要控件高度,通过onMeasure事件来绘制GridView。在XML布局中引用<com.blog.mogujie.tool.MyGridView ../>,布局文件代码太长就不贴出来了,待会在后面提供代码下载链接。

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

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public class GrdoneAdapter extends BaseAdapter{  
  2.   
  3.     private Context mContext;  
  4.     private List<GrdOneInfo> mGrdOneInfoList;  
  5.     public GrdoneAdapter(Context mContext,List<GrdOneInfo> mGrdOneInfoList){  
  6.         this.mContext=mContext;  
  7.         this.mGrdOneInfoList=mGrdOneInfoList;  
  8.     }  
  9.     @Override  
  10.     public int getCount() {  
  11.         // TODO Auto-generated method stub  
  12.         return mGrdOneInfoList.size();  
  13.     }  
  14.   
  15.     @Override  
  16.     public Object getItem(int position) {  
  17.         // TODO Auto-generated method stub  
  18.         return position;  
  19.     }  
  20.   
  21.     @Override  
  22.     public long getItemId(int position) {  
  23.         // TODO Auto-generated method stub  
  24.         return position;  
  25.     }  
  26.   
  27.     @Override  
  28.     public View getView(int position, View convertView, ViewGroup parent) {  
  29.         View view = convertView;  
  30.         final ViewHolder holder;  
  31.         if (convertView == null) {  
  32.             view = ((Activity) mContext).getLayoutInflater().inflate(  
  33.                     R.layout.item_grd1, parent, false);  
  34.             holder = new ViewHolder();  
  35.             holder.image = (ImageView) view.findViewById(R.id.grdimage);  
  36.             holder.brife= (TextView) view.findViewById(R.id.brife1);  
  37.             holder.price= (TextView) view.findViewById(R.id.price);  
  38.             holder.marks= (TextView) view.findViewById(R.id.marks);  
  39.             view.setTag(holder);  
  40.         } else {  
  41.             holder = (ViewHolder) view.getTag();  
  42.         }  
  43.         holder.image.setImageResource(mGrdOneInfoList.get(position).imagePath);  
  44.         if(mGrdOneInfoList.get(position).brife.length()>50){  
  45.             holder.brife.setText(mGrdOneInfoList.get(position).brife.subSequence(030)+"...");  
  46.         }else{  
  47.             holder.brife.setText(mGrdOneInfoList.get(position).brife);  
  48.         }  
  49.         holder.price.setText(mGrdOneInfoList.get(position).price);  
  50.         holder.marks.setText(mGrdOneInfoList.get(position).marksNum);  
  51.         return view;  
  52.     }  
  53.   
  54.     static class ViewHolder{  
  55.         ImageView image;  
  56.         TextView brife;  
  57.         TextView price;  
  58.         TextView marks;  
  59.     }  
  60. }  
最终效果如下:

 


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


相关文章
|
1月前
|
存储 JavaScript 前端开发
订水商城实战教程10-宫格导航
订水商城实战教程10-宫格导航
|
JavaScript 前端开发
uniapp仿微信聊天室|仿微信界面
基于uniapp+vue仿微信聊天室uniapp-chatroom项目,vue语法及类似小程序api开发原生APP应用,实现了发送图文消息、表情(gif动图),图片预览、地图位置、红包、仿微信朋友圈等功能。
2900 0
|
4月前
|
前端开发
移动端开发——京东首页制作(流式布局)
移动端开发——京东首页制作(流式布局)
|
存储 容器
仿百度福袋红包界面
仿百度福袋红包界面
70 0
仿百度福袋红包界面
|
JavaScript 前端开发
仿网易云项目笔记
仿网易云项目笔记
127 0
|
API 开发工具 开发者
微信小游戏分享功能
微信小游戏分享功能
微信小游戏分享功能
|
前端开发
移动端支付界面制作(小兔鲜项目)
移动端支付界面制作(小兔鲜项目)
177 0
移动端支付界面制作(小兔鲜项目)
Qt-网易云音乐界面实现-9 照片墙功能
最近车也买了,不过倒是没有想象的那么开心,车真的是想消耗品啊。
176 0
Qt-网易云音乐界面实现-9 照片墙功能
Qt-网易云音乐界面实现-6 迷你个人中心实现
这个界面除了麻烦耗时,没有啥技术含量。暂时我也就把它称为迷你个人中心,因为后面还有一个个人中心了。 先看下完成品
108 0
Qt-网易云音乐界面实现-6 迷你个人中心实现
|
C++
Qt-网易云音乐界面实现-3 音乐名片模块的实现
Qt-网易云音乐界面实现-3 音乐名片模块的实现
124 0
Qt-网易云音乐界面实现-3 音乐名片模块的实现