Android仿京东手机端类别页

京东手机端的类别标签页, 是一个左侧滑动可选择类别, 右侧一个类别明细的列表联动页面. 当用户选择左侧选项, 可在右侧显示更多选项来选择. 实现方式也不少. 最常见的当然是左侧和右侧各一个Fragment, 左侧Fragment放置ListView, 右侧放显示类别明细的Fragment. 如果觉得页面包含的Fragment太多, 左侧直接给一个ListView就可以了.不影响效果.

效果图:

例子中值得注意的三点:

  • 左侧列表点击某个Item可以自动上下滑动,使所点击的item自动移至列表中间
  • 点击item后保留背景色不变
  • 右侧布局

针对上面三个点,这里采取如下的解决方法:

  • 计算可见列表的可见首项或末项position值,使用smoothScrollToPosition()方法实现滑动
  • 自定义列表selector按下和松开的背景色,在adapter去更新并控制item的背景色
  • 右侧布局,采用Fragment是最好的. 里面使用ScrollView装载所有数据,可以动态的addView(),removeView(), 网格布局使用GridView. 由于Fragment, 所以更新数据和更新View都非常方便, 所以例子中直接用静态页面模拟数据了.

重在通过简单的例子解释这种实现思路, 当然实现不是唯一的.

然后,我们先来模拟右侧的Fragment数据,一看就懂的代码:

public class JDFragment extends Fragment{
  String TAG = "JDFragment";
  private View rootView = null;
  private LinearLayout llayout_main = null;
  private TextView tv = null;

  private LinearLayout.LayoutParams lp_gd = null;
  private LinearLayout.LayoutParams lp_tv = null;
  private ArrayList<Category> itemList = null;
  private GDAdapter adapter = null;

  @Override
  public void onAttach(Activity activity)
  {
    Log.e(TAG, "onAttach...");
    super.onAttach(activity);
  }

  @Override
  public void onCreate(Bundle savedInstanceState)
  {
    Log.e(TAG, "onCreate...");
    super.onCreate(savedInstanceState);
  }

  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container,
      Bundle savedInstanceState)
  {
    Log.e(TAG, "onCreateView...");
    rootView = inflater.inflate(R.layout.jd_frg_main, null);
    llayout_main = (LinearLayout) rootView.findViewById(R.id.llayout_jd_frg_main);
    tv = (TextView) rootView.findViewById(R.id.tv_jd_frg_main);

    updateTitle();

    //模拟数据
    for(int i=0; i<2; i++)
    {
      setData();
    }

    return rootView;
  }

  protected void updateTitle()
  {
    if(getArguments() != null)
    {
      updateTitle(getArguments().getString("name"));
    }
  }

  protected void updateTitle(String title)
  {
    if(tv != null)
    {
      tv.setText(title);
    }
  }

  private void setData()
  {
    if(itemList == null)
    {
      itemList = new ArrayList<Category>();
      for(int i=1; i<11; i++)
      {
        itemList.add(new Category("选项 " + i, ""+i));
      }
    }

    //高度60dp+行距8dp = 68dp
    int heightUnit = (int)TypedValue
        .applyDimension(TypedValue.COMPLEX_UNIT_DIP, 68, getResources().getDisplayMetrics());
    int height;

    //计算Gridview总高度
    if(itemList.size() % 3 == 0)
    {
      height = (itemList.size()/3 + 2)*heightUnit;
    }
    else{
      height = (itemList.size()/3 + 1)*heightUnit;
    }

    if(lp_gd == null)
      lp_gd = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, height);

    if(lp_tv == null)
      lp_tv = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT
          , (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP
              , 30, getResources().getDisplayMetrics()));

    TextView tv_title = new TextView(getActivity());
    tv_title.setLayoutParams(lp_tv);
    tv_title.setText("组一");
    llayout_main.addView(tv_title);

    GridView gridView = new GridView(getActivity());
    gridView.setNumColumns(3);
    gridView.setVerticalSpacing(8);
    gridView.setLayoutParams(lp_gd);

    adapter = new GDAdapter(getActivity(), itemList,R.drawable.cate);
    gridView.setAdapter(adapter);
    llayout_main.addView(gridView);
  }

  @Override
  public void onActivityCreated(Bundle savedInstanceState)
  {
    Log.e(TAG, "onActivityCreated...");
    super.onActivityCreated(savedInstanceState);
  }

  @Override
  public void onStart()
  {
    Log.e(TAG, "onStart...");
    super.onStart();
  }

  @Override
  public void onResume()
  {
    Log.e(TAG, "onResume...");
    super.onResume();
  }

  @Override
  public void onPause()
  {
    Log.e(TAG, "onPause...");
    super.onPause();
  }

  @Override
  public void onStop()
  {
    Log.e(TAG, "onStop...");
    super.onStop();
  }

  @Override
  public void onDestroyView()
  {
    Log.e(TAG, "onDestroyView...");
    super.onDestroyView();
  }

  @Override
  public void onDestroy()
  {
    Log.e(TAG, "onDestroy...");
    super.onDestroy();
  }

  @Override
  public void onDetach()
  {
    Log.e(TAG, "onDetach...");
    super.onDetach();
  }

  static class GDAdapter extends BaseAdapter
  {
    Context context;
    List<Category> results;
    int imageId;
    ViewHolder holder = null;

    public GDAdapter(Context context, List<Category> results,int imageId) {
      this.context = context;
      this.results = results;
      this.imageId = imageId;
    }

    @Override
    public int getCount() {
      // TODO Auto-generated method stub
      return results.size();
    }

    @Override
    public Object getItem(int position) {
      // TODO Auto-generated method stub
      return results.get(position);
    }

    @Override
    public long getItemId(int position) {
      // TODO Auto-generated method stub
      return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
      Category c = (Category)getItem(position);

      if(convertView == null)
      {
        holder = new ViewHolder();
        convertView = LayoutInflater.from(context).inflate(R.layout.jd_item, null);
        holder.tv = (TextView) convertView.findViewById(R.id.tv_jd_item);
        holder.imv = (ImageView) convertView.findViewById(R.id.imv_jd_item);
      }
      else
      {
        holder = (ViewHolder) convertView.getTag();
      }
      convertView.setTag(holder);

      holder.tv.setText(c.getName());
      holder.imv.setImageResource(imageId);

      return convertView;
    }

    class ViewHolder
    {
      TextView tv;
      ImageView imv;
    }
  }

}

JDFragment的布局文件, jd_frg_main.xml:

<?xml version="1.0" encoding="utf-8" ?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:background="#FFFFFF"
  >
  <TextView
    android:id="@+id/tv_jd_frg_main"
    android:layout_width="match_parent"
    android:layout_height="25dp"
    android:text="Fragment"
    android:textSize="16sp"
    android:background="#EEEEEE"
    />
  <ScrollView
    android:id="@+id/scrlayout_jd_frg_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_below="@+id/tv_jd_frg_main"
    android:overScrollMode="never"
    >
    <LinearLayout
      android:id="@+id/llayout_jd_frg_main"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:orientation="vertical"
      />
  </ScrollView>

</RelativeLayout>

将所有数据放在ScrollView的线性布局中,使用Fragment作为容器, 可以根据需要ADD, Remove和Update数据和View. 到这里右侧页面的简单模拟实现就结束了,都是一目了然的代码.

然后就是实现左侧列表了,先是列表中简单的自定义Adapter, MyAdapter:

public class MyAdapter extends BaseAdapter
{
  private Context context;
  private List<Category> results;
  private int imageId;
  private ViewHolder holder = null;
  private int selectedId;

  public MyAdapter(Context context, List<Category> results,int imageId) {
    this.context = context;
    this.results = results;
    this.imageId = imageId;
  }

  @Override
  public int getCount() {
    // TODO Auto-generated method stub
    return results.size();
  }

  @Override
  public Object getItem(int position) {
    // TODO Auto-generated method stub
    return results.get(position);
  }

  @Override
  public long getItemId(int position) {
    // TODO Auto-generated method stub
    return position;
  }

  public void setSelected(int position)
  {
    this.selectedId = position;
  }

  @Override
  public View getView(int position, View convertView, ViewGroup parent) {
    Category c = (Category)getItem(position);

    if(convertView == null)
    {
      holder = new ViewHolder();
      convertView = LayoutInflater.from(context).inflate(R.layout.jd_item, null);
      holder.tv = (TextView) convertView.findViewById(R.id.tv_jd_item);
      holder.imv = (ImageView) convertView.findViewById(R.id.imv_jd_item);
    }
    else
    {
      holder = (ViewHolder) convertView.getTag();
    }

    if(position == selectedId)
    {
      convertView.setBackgroundResource(R.drawable.sele_true);
    }
    else
    {
      convertView.setBackgroundResource(R.drawable.sele_false);
    }

    holder.tv.setText(c.getName());
    holder.imv.setImageResource(imageId);
    convertView.setTag(holder);

    return convertView;
  }

  class ViewHolder
  {
    TextView tv;
    ImageView imv;
  }
}

然后是主Activity了, 在里面对可见ListView的item位置进行计算, 并进行滑动处理. 当用户点击偏上的item, 列表就往下滑动, 加载顶部更多的item; 当用户点击偏下的item, 列表就往上滑动, 加载底部更多的item.

同时我们自定义按下和松开时的背景文件放在drawable, 随便一个shape就可以了. 然后点击某个item的position时, 在adapter中判断是否目标item, 是就设置按下背景色 - 白色, 否则就是正常的背景色 - 灰色.

/**
 * 仿京东类别页
 * @author AlexTam
 */
public class JDActivity extends FragmentActivity{
  private ListView lv_main = null;
  private EditText et_search = null;

  private ArrayList<Category> itemList = new ArrayList<Category>();
  private MyAdapter adapter = null;
  //可见列表项的数量
  private int visibleCount = 0;
  //上次点击的位置
  private int lastPosition = 0;
  private int ce = 0;
  //实际列表是否超出屏幕
  private boolean isOut = true;
  private JDFragment fragment = null;

  @Override
  public void onCreate(Bundle savedInstanceState)
  {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.jd_main);

    init();
  }

  private void init()
  {
    lv_main = (ListView) findViewById(R.id.lv_main);
    et_search = (EditText) findViewById(R.id.et_search);

    for(int i=1; i<21; i++)
    {
      itemList.add(new Category("选项 " + i, ""+i));
    }

    adapter = new MyAdapter(this, itemList,R.drawable.ic_launcher);
    lv_main.setAdapter(adapter);
    lv_main.setOnItemClickListener(new MyOnItemOnClick());
    lv_main.setSelector(R.color.pink);

    //模拟右侧标签页
    fragment = new JDFragment();
    Bundle bundle = new Bundle();
    bundle.putString("name", "c1");
    fragment.setArguments(bundle);
    FragmentManager fm = getSupportFragmentManager();
    FragmentTransaction ft = fm.beginTransaction();
    ft.replace(R.id.flayout_main, fragment, "c0").commit();

    adapter.setSelected(0);
    adapter.notifyDataSetChanged();
  }

  private class MyOnItemOnClick implements OnItemClickListener
  {
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position,
        long id)
    {
      //计算滑动
      if(visibleCount == 0)
      {
        visibleCount = lv_main.getChildCount();
        if(visibleCount == itemList.size())
          isOut = false;
        else
        {
          ce = visibleCount/2;
        }
      }

      if(position <= (parent.getFirstVisiblePosition() + ce))
      {  //上移
        lv_main.smoothScrollToPosition(position - ce);
      }
      else
      {  //下移
        if((parent.getLastVisiblePosition() + ce + 1) <= parent.getCount())
        {
          lv_main.smoothScrollToPosition(position + ce);
        }
        else
        {
          lv_main.smoothScrollToPosition(parent.getCount()-1);
        }

      }

      lastPosition = position;

      adapter.setSelected(position);
      adapter.notifyDataSetChanged();

      //更新右侧标签页的标题
      fragment.updateTitle("c" + (position+1));
    }

  }

  /**
   * 选项对象
   */
  static class Category
  {
    private String name;
    private String id;

    Category(String name,String id)
    {
      this.name = name;
      this.id = id;
    }

    public String getName()
    {
      return this.name;
    }
  }

}

OK, 到此效果就出来了. 好简单吧!

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

您可能感兴趣的文章:

  • Android实现腾讯新闻的新闻类别导航效果
  • Android仿京东分类模块左侧分类条目效果
  • Android使用Scroll+Fragment仿京东分类效果
  • Android 仿京东、拼多多商品分类页的示例代码
  • Android实现网易Tab分类排序控件实现
  • Android使用分类型RecyclerView仿各大商城首页
  • Android编程实现仿美团或淘宝的多级分类菜单效果示例【附demo源码下载】
  • android使用 ScrollerView 实现 可上下滚动的分类栏实例
  • Android 仿网易新闻客户端分类排序功能
  • Android学习教程之分类侧滑菜单(5)
(0)

相关推荐

  • Android使用分类型RecyclerView仿各大商城首页

    **正所谓,一入商城深似海~ 商城类的App,确实是有许多东西值得学习,但是只要略微斟酌一下,你又会发现,它们之间存在着许多不谋而合的相似,也就是所谓的雷同~既然如此,让我们也来接下地气,先从一个简单的首页做起吧~** 实现的效果如下图: 1.大布局就是一个简单的RecyclerView: 也可以通过添加多个header实现 4.这里我仅以四种类型为例 /** * 4种类型 */ /** * 类型1:黑色星期五--使用banner实现 */ public static final int BLA

  • Android学习教程之分类侧滑菜单(5)

    本文实例为大家分享了Android分类侧滑菜单的制作方法,供大家参考,具体内容如下 classificmenuActivity.java代码: package com.siso.crazyworld; import android.animation.Animator; import android.content.res.Configuration; import android.graphics.Color; import android.graphics.drawable.BitmapDr

  • Android编程实现仿美团或淘宝的多级分类菜单效果示例【附demo源码下载】

    本文实例讲述了Android编程实现仿美团或淘宝的多级分类菜单效果.分享给大家供大家参考,具体如下: 这里要实现的是诸如美团/淘宝/百度糯米 多级分类菜单效果.当分类数量非常多时可以考虑采用两级分类,而诸如美团这种表现方式是一个不错的选择. 首先上效果图:   主要代码: 1. PopupWindow初始化过程: popupWindow = new PopupWindow(this); View view = LayoutInflater.from(this).inflate(R.layout.

  • android使用 ScrollerView 实现 可上下滚动的分类栏实例

    如果不考虑更深层的性能问题,我个人认为ScrollerView还是很好用的.而且单用ScrollerView就可以实现分类型的RecyclerView或ListView所能实现的效果. 下面我单单从效果展示方面考虑,使用ScrollerView实现如下图所示的可滚动的多条目分类,只是为了跟大家一起分享一下新思路.(平时:若从复用性等方面考虑,这显然是存在瑕疵的~) 特点描述: 1.可上下滚动 2.有类似于网格布局的样式 3.子条目具有点击事件 刚看到这个效果时,首先想到的是使用分类型的Recyc

  • Android仿京东分类模块左侧分类条目效果

    本文实例为大家分享了Android仿京东左侧分类条目效果的具体代码,供大家参考,具体内容如下 import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.LinearLayout; import android.widget.ScrollView; import android.widget.TextView; import com.frame.R;

  • Android 仿网易新闻客户端分类排序功能

    先来看看网易新闻客户端以及自己实现的效果图,效果当然还是网易的好 gridviewsort.gif 如何实现拖拽一个Item 用WindowManager添加一个ImageView,并且将这个ImageView的显示图片设置成被拖拽item的截图,截图可以通过View的getDrawingCache获得.拖拽的时候,隐藏原始的item.处理触摸事件的ActionMove,调整ImageView的位置,跟随手指移动.在ActionUp的时候removeView GridView @Override

  • Android实现网易Tab分类排序控件实现

    先看看效果图: 1.XML布局引入 <com.net168.lib.SortTabLayout android:id="@+id/layout" android:layout_width="match_parent" android:layout_height="wrap_content" /> 2.设置数据源数据,也就是每个item的对应文本数据 //构造数据源,暂时仅支持String List<String> data

  • Android实现腾讯新闻的新闻类别导航效果

    效果图如下所示:  1.在Adapter中加入如下代码 <pre style="background-color:#2b2b2b;color:#a9b7c6;font-family:'OCR A Std';font-size:10.2pt;"><span style="color:#cc7832;">private int </span><span style="color:#9876aa;">cl

  • Android使用Scroll+Fragment仿京东分类效果

    本文实例为大家分享了Android九宫格图片展示的具体代码,供大家参考,具体内容如下 实现思路:首先说下布局,整个是一个横向的线性布局,左边是一个ScrollView,右边是一个FrameLayout,在代码中动态向ScrollView中添加TextView,然后根据TextView的点击事件使用Fragment替换FrameLayout 首先看下布局: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/andr

  • Android 仿京东、拼多多商品分类页的示例代码

    最近接了一个项目,要仿照京东写一个商品分类页,但需要滑动右边子分类,左边的主分类也跟着变换,写了个demo,需要的同学可以自取. 先放一个写完之后的样子: 写这个需求的思路也很清晰,首先左边肯定是一个listView,右边也是一个listView,这两个listView要达到一个联动的效果.右边的listView再嵌套一个GridView即可.如下图所示. 所以,我们需要的数据结构也就确定了,应该是数组套数组,也就说护肤大分类下又有子分类商品,类似于这个样子: ok,数据和UI结构确定了,就可以

随机推荐