当前位置: 代码迷 >> Android >> [Android]仿京东手机端品种页
  详细解决方案

[Android]仿京东手机端品种页

热度:29   发布时间:2016-04-27 23:18:41.0
[Android]仿京东手机端类别页

[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, 到此效果就出来了. 好简单吧!

版权声明:本文为博主原创文章,未经博主允许不得转载。

  相关解决方案