在項目的進行中要用到左右滑動又能上下滑動的列表布局,開始想的是使用一個ViewPager嵌套一個ListView來進行分頁處理,在滑動ViewPager的時候翻頁,效果是達到了,但是拓展性不好,所以我又另想法子,現在使用一個HorizontalScrollView嵌套一個ListView可以很好的解決拓展的問題,效果如下,原諒我GIF做的如此的簡陋,這里提供一個思路,希望能幫到有需要的朋友,源代碼附在文后 。
。
簡單講下實現的思路:思路應該從需求開始講,項目中用到的這個類似電影院選座位或考場編座位,界面上有xx排xx列個位置,需要按照票面的座位號對號入座,如果一個屏幕能裝下還好解決,使用GridView就應該可以應付了,但是如果橫向超出一個屏幕,好像GridView就有點無能為力了,所以我這里思考使用HorizontalScorllView嵌套一層布局去實現,里面的布局我使用的是ListView,實現豎向滑動,不要問為什么,我喜歡,就是這么任性
,當然如果你喜歡使用GridView,請隨意
,因為他們倆都是AbsListVIew的直接子類,用法的話自己去琢磨
。
二話不說先上代碼了,這次從布局看起
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.cjt.horizontalscrollviewdemo.MainActivity"> <HorizontalScrollView android:id="@+id/mHorizontalScrollView" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_alignParentTop="true"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <LinearLayout android:id="@+id/titleLayout" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="40dp"/> <ListView android:id="@+id/mListView" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout> </HorizontalScrollView></RelativeLayout>這就是我的主頁面布局文件,在HorizontalScrollView中嵌套ListView布局,使用ScrollView或者HorizontalScrollView的時候一定要注意,因為他們比較特別,只承認一個兒子,也就是嵌套的子布局只能是一個,所以我這里使用的是LinearLayout包裹ListView控件,可能細心的你會問,還有一個LinearLayout是干嘛的,其實他不只是打醬油的,他就是上面GIF中的第幾列的標題,ListView上下滑動的時候,他是保持不動的,可以理解為Excel中的表頭,分析完畢。接著上代碼??聪翸ainActivity長什么樣public class MainActivity extends AppCompatActivity { // 界面上的控件 PRivate ListView mListView; private MyListAdapter mAdapter; private LinearLayout mTitleLayout ; // 相關的數據 private List<ItemBean> dataList = new ArrayList<>(); // 測試實體類的集合 private ItemBean bean; // 測試實體類,模擬一個座位,有頭像和姓名,以及座位號 private List<String> idList = new ArrayList<>(); // 為了大家便于理解,存放票面號 private static final int COLUMN_NUM = 10; // 列數 private static final int ROW_NUM = 10; // 行數 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mListView = (ListView) findViewById(R.id.mListView); mTitleLayout = (LinearLayout) findViewById(R.id.titleLayout); // 首先填充頭部的標題布局 for (int i = 0; i < COLUMN_NUM; i++) { View titleView = LayoutInflater.from(this).inflate(R.layout.item_text,null); TextView title = (TextView) titleView.findViewById(R.id.itemTitleTv); title.setText("標題"+i); // 直接往LinearLayout中填充子元素,設置該子元素的寬高和寬所占的比重 mTitleLayout.addView(titleView,new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT, 1.0f)); } // 準備數據,這里僅僅準備票面的座位號,相當于準備票 for (int i = 1; i <= COLUMN_NUM; i++) { for (int j = 1; j <= ROW_NUM; j++){ idList.add(i+"-"+j); } } // 下面把剛剛準備好的一批票發放到每個人的手中 for (int i = 0; i < idList.size(); i++) { bean = new ItemBean(); bean.setId(idList.get(i)); // 給這位同學發了一張票了 bean.setPictureName("同學" + i); bean.setPictureResId(R.mipmap.ic_launcher); // 這位同學的長相 dataList.add(bean); // 添加到數據集合 } // 設置適配器 mAdapter = new MyListAdapter(this, dataList, COLUMN_NUM ); mListView.setAdapter(mAdapter); }}代碼注釋也很清楚了,我就不再啰嗦了,有什么不明白的地方大家可以跟我留言,反正我也不會解答。這里補充一下代碼中幾個xml布局的寫法。
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="5dp"> <TextView android:id="@+id/itemTitleTv" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:textSize="18sp" android:text="--標題--" /></LinearLayout>這個就是標題的長相,也就是上圖中標紅的部分R.layout.item_text的寫法。下面看下適配器Adapter是怎么寫的,
public class MyListAdapter extends BaseAdapter { private Context mContext ; private List<ItemBean> mDataLists ; private int mColumnNum = 0 ; public MyListAdapter() { } /** * 構造函數 * @param mContext * @param mDataLists */ public MyListAdapter(Context mContext, List<ItemBean> mDataLists , int columnNum ) { this.mContext = mContext; this.mDataLists = mDataLists; this.mColumnNum = columnNum ; } @Override public int getCount() { return mDataLists.size(); } @Override public ItemBean getItem(int i) { return mDataLists.get(i); } @Override public long getItemId(int i) { return i; } @Override public View getView(int position, View view, ViewGroup parent) { view = LayoutInflater.from(mContext).inflate(R.layout.list_row_layout,null); LinearLayout row = (LinearLayout) view.findViewById(R.id.listViewRow); // 行布局 if(row != null) row.removeAllViews(); // 清空行 for (int i = 0; i < mColumnNum ; i++) { View itemView = LayoutInflater.from(mContext).inflate(R.layout.item,null); TextView itemNameTv = (TextView) itemView.findViewById(R.id.itemNameTv); TextView itemLocationTv = (TextView) itemView.findViewById(R.id.itemLocationTv); ItemBean itemBean = getLocationBean(position+1 , i+1); // 獲取對應的實體類 if(itemBean != null){ itemNameTv.setText(itemBean.getPictureName()); itemLocationTv.setText(itemBean.getId()); // 將每個元素添加到行布局中去 row.addView(itemView, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT, 1.0f)); } } return view; // 返回加載好了內容的行布局 } /*** * 根據座位號獲取對應的元素 * @param row * @param column * @return */ private ItemBean getLocationBean(int row , int column){ String index = column+"-"+row; // 生成索引,對比索引找到對應的學生 for (int i = 0; i < this.getCount(); i++) { if(this.getItem(i).getId().equals(index)) return this.getItem(i) ; } return null ; }}下面摘出來的一段代碼就是定位用的,在電影院里,就是憑借著票面上的xx排xx列找到自己的座位的,這里也是一樣的原理
private ItemBean getLocationBean(int row , int column){ String index = column+"-"+row; // 生成索引,對比索引找到對應的學生 for (int i = 0; i < this.getCount(); i++) { if(this.getItem(i).getId().equals(index)) return this.getItem(i) ; } return null ; }這個Adapter中也有兩個布局XML文件,主要是不想手寫,其實純粹可以手寫,我習慣用LayoutInflater加載XML布局來實現的,這兩個布局XML也貼出來給大家。
R.layout.list_row_layout: 這個是每行的布局,作為父容器來使用
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/listViewRow" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent"/>R.layout.item: 就是每個位子上的布局
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:gravity="center" android:padding="16dp" android:layout_height="match_parent"> <ImageView android:layout_width="60dp" android:layout_height="60dp" app:srcCompat="@mipmap/ic_launcher" android:layout_centerInParent="true" android:id="@+id/itemImageView" /> <TextView android:text="名稱" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/itemImageView" android:layout_centerHorizontal="true" android:layout_marginTop="10dp" android:id="@+id/itemNameTv" /> <TextView android:text="坐標" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/itemNameTv" android:layout_alignLeft="@+id/itemNameTv" android:layout_alignStart="@+id/itemNameTv" android:layout_centerHorizontal="true" android:layout_marginTop="6dp" android:id="@+id/itemLocationTv" /></RelativeLayout>文末的福利放送:你也想制作文中的GIF圖嗎,推薦你一款軟件LICEcap,這是地址:http://www.cockos.com/licecap/
源代碼地址(下載不要分,拿走不謝):
Git倉庫:https://github.com/1989Jiangtao/HorizontalScrollviewDemo
CSDN:http://download.csdn.net/detail/u010898329/9751237
| 
 
 | 
新聞熱點
疑難解答