編輯:關於Android編程
京東手機端的類別標簽頁, 是一個左側滑動可選擇類別, 右側一個類別明細的列表聯動頁面. 當用戶選擇左側選項, 可在右側顯示更多選項來選擇. 實現方式也不少. 最常見的當然是左側和右側各一個Fragment, 左側Fragment放置ListView, 右側放顯示類別明細的Fragment. 如果覺得頁面包含的Fragment太多, 左側直接給一個ListView就可以了.不影響效果.
效果圖:
例子中值得注意的三點:
左側列表點擊某個Item可以自動上下滑動,使所點擊的item自動移至列表中間 點擊item後保留背景色不變 右側布局針對上面三個點,這裡采取如下的解決方法:
計算可見列表的可見首項或末項position值,使用smoothScrollToPosition()方法實現滑動 自定義列表selectZ喎?/kf/ware/vc/" target="_blank" class="keylink">vcrC0z8K6zcvJv6q1xLGzvrDJqyzU2mFkYXB0ZXLIpbj80MKyor/Y1sZpdGVttcSxs76wyasg09Ky4LK8vtYsssnTw0ZyYWdtZW50ysfX7rrDtcQuIMDvw+bKudPDU2Nyb2xsVmlld9ew1NjL+dPQyv2+3Sy/ydLUtq/MrLXEYWRkVmlldygpLHJlbW92ZVZpZXcoKSwgzfi48bK8vtbKudPDR3JpZFZpZXcuINPJ09pGcmFnbWVudCwgy/nS1Lj80MLK/b7dus24/NDCVmlld7a8t8ezo7e9seMsIMv50tTA/dfT1tDWsb3T08O+ssys0rPD5sSjxOLK/b7dwcsuDQo8cD7W2NTazai5/bzytaW1xMD919O94srN1eLW1sq1z9bLvMK3LCC1sci7yrXP1rK7ysfOqNK7tcQuPC9wPg0KPHA+yLu68yzO0sPHz8jAtMSjxOLT0rLgtcRGcmFnbWVudMr9vt0s0ru/tL7Ntq61xLT6wus6PC9wPg0KPHByZSBjbGFzcz0="brush:java;">
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 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();
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 results;
int imageId;
ViewHolder holder = null;
public GDAdapter(Context context, List 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:
將所有數據放在ScrollView的線性布局中,使用Fragment作為容器, 可以根據需要ADD, Remove和Update數據和View. 到這裡右側頁面的簡單模擬實現就結束了,都是一目了然的代碼.
然後就是實現左側列表了,先是列表中簡單的自定義Adapter, MyAdapter:
public class MyAdapter extends BaseAdapter
{
private Context context;
private List results;
private int imageId;
private ViewHolder holder = null;
private int selectedId;
public MyAdapter(Context context, List 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 itemList = new ArrayList();
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, 到此效果就出來了. 好簡單吧!
只有簡單的三步,官網寫的非常簡明全面,非常佩服 【准備】 1. Eclipse(Indigo) 2. ADT: 這個不說了,無非就是eclipse添加個an
?? 上一篇Android研究之屬性動畫(Property Animation)完全解析詳解上已經基本展示了屬性動畫的核心用法: ObjectAnimator實現動畫,V
開發環境:android4.1.實驗功能:在第一個界面中的2個乘數輸入處分別輸入2個數字,按下結果button,會自動跳到第二個界面並顯示輸入2個數字相乘的結果。如果在第
應用開發中經常會有從數據庫中讀取數據顯示,然後選中多條、全部記錄並且刪除的需求。在做定制系統聯系人的時候也遇到這樣的需求,下面寫個簡單的通過ListView和CheckB