首页 > 系统 > Android > 正文

Android仿京东手机端类别页

2019-10-22 18:15:12
字体:
来源:转载
供稿:网友

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

效果图:

Android,京东,手机端,类别页

例子中值得注意的三点:

  • 左侧列表点击某个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, 到此效果就出来了. 好简单吧!

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


注:相关教程知识阅读请移步到Android开发频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表