Implementing horizontalList inside a vertical list in android

前端 未结 2 475
再見小時候
再見小時候 2021-01-16 03:30

I have made a custom Horizontal List view which works fine. I then implemented the same horizontal list inside a ListView control. But when I run the same, all I get is a bl

相关标签:
2条回答
  • 2021-01-16 03:59

    After Android L Developer Preview published, Google supply a new View called RecyclerView which can replace ListView and GridView, it makes it easier to make a horizontal list, so I update my answer here.

    We don't need to use any library anymore at this time, RecyclerView is just enough. Here is the code which I make a horizontal list by RecyclerView (I am not trying to explain detailed usage of RecyclerView):

    MainActivity.java

    public class MainActivity extends AppCompatActivity {
    
        List<List<String>> mDataList;
    
        private RecyclerView mVerticalList;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            prepareData();
            initListView();
        }
    
        private void prepareData() {
            mDataList = new ArrayList<>();
            int vItemCount = 25;
            int hItemCount = 20;
            for (int i = 0; i < vItemCount; i++) {
                List<String> hList = new ArrayList<>();
                for (int j = 0; j < hItemCount; j++) {
                    hList.add("Item." + j);
                }
                mDataList.add(hList);
            }
        }
    
        private void initListView() {
            mVerticalList = (RecyclerView) findViewById(R.id.vertical_list);
            mVerticalList.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
            VerticalAdapter verticalAdapter = new VerticalAdapter();
            verticalAdapter.setData(mDataList);
            mVerticalList.setAdapter(verticalAdapter);
        }
    
        private static class VerticalAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    
            private List<List<String>> mDataList;
    
            public VerticalAdapter() {
            }
    
            public void setData(List<List<String>> data) {
                mDataList = data;
                notifyDataSetChanged();
            }
    
            private class HorizontalListViewHolder extends RecyclerView.ViewHolder {
    
                private TextView title;
                private RecyclerView horizontalList;
                private HorizontalAdapter horizontalAdapter;
    
                public HorizontalListViewHolder(View itemView) {
                    super(itemView);
                    Context context = itemView.getContext();
                    title = (TextView) itemView.findViewById(R.id.item_title);
                    horizontalList = (RecyclerView) itemView.findViewById(R.id.item_horizontal_list);
                    horizontalList.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false));
                    horizontalAdapter = new HorizontalAdapter();
                    horizontalList.setAdapter(horizontalAdapter);
                }
            }
    
            @Override
            public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
                Context context = parent.getContext();
                View itemView = LayoutInflater.from(context).inflate(R.layout.vertical_list_item, parent, false);
                HorizontalListViewHolder holder = new HorizontalListViewHolder(itemView);
                return holder;
            }
    
            @Override
            public void onBindViewHolder(RecyclerView.ViewHolder rawHolder, int position) {
                HorizontalListViewHolder holder = (HorizontalListViewHolder) rawHolder;
                holder.title.setText("Horizontal List No." + position);
                holder.horizontalAdapter.setData(mDataList.get(position));
                holder.horizontalAdapter.setRowIndex(position);
            }
    
            @Override
            public int getItemCount() {
                return mDataList.size();
            }
        }
    
        private static class HorizontalAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    
            private List<String> mDataList;
            private int mRowIndex = -1;
            private int[] mColors = new int[]{Color.RED, Color.BLUE, Color.GREEN, Color.MAGENTA, Color.DKGRAY};
    
            public HorizontalAdapter() {
            }
    
            public void setData(List<String> data) {
                if (mDataList != data) {
                    mDataList = data;
                    notifyDataSetChanged();
                }
            }
    
            public void setRowIndex(int index) {
                mRowIndex = index;
            }
    
            private class ItemViewHolder extends RecyclerView.ViewHolder {
    
                private TextView text;
    
                public ItemViewHolder(View itemView) {
                    super(itemView);
                    text = (TextView) itemView.findViewById(R.id.item_text);
                    itemView.setOnClickListener(mItemClickListener);
                }
            }
    
            @Override
            public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
                Context context = parent.getContext();
                View itemView = LayoutInflater.from(context).inflate(R.layout.horizontal_list_item, parent, false);
                ItemViewHolder holder = new ItemViewHolder(itemView);
                return holder;
            }
    
            @Override
            public void onBindViewHolder(RecyclerView.ViewHolder rawHolder, int position) {
                ItemViewHolder holder = (ItemViewHolder) rawHolder;
                holder.text.setText(mDataList.get(position));
                holder.itemView.setBackgroundColor(mColors[position % mColors.length]);
                holder.itemView.setTag(position);
            }
    
            @Override
            public int getItemCount() {
                return mDataList.size();
            }
    
            private View.OnClickListener mItemClickListener = new View.OnClickListener() {
    
                @Override
                public void onClick(View v) {
                    int columnIndex = (int) v.getTag();
                    int rowIndex = mRowIndex;
    
                    String text = String.format("rowIndex:%d ,columnIndex:%d", rowIndex, columnIndex);
                    showToast(v.getContext(), text);
                    Log.d("test", text);
                }
            };
        }
    
        private static Toast sToast;
    
        public static void showToast(Context context, String text) {
            if (sToast != null) {
                sToast.cancel();
            }
            sToast = Toast.makeText(context, text, Toast.LENGTH_LONG);
            sToast.show();
        }
    }
    

    activity_main.xml

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent">
    
        <android.support.v7.widget.RecyclerView
            android:id="@+id/vertical_list"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
    
    </RelativeLayout>
    

    horizontal_list_item.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="wrap_content"
        android:paddingLeft="10dp"
        android:paddingRight="10dp"
        android:orientation="vertical">
    
        <TextView
            android:id="@+id/item_text"
            android:textColor="@android:color/white"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:gravity="center_vertical"/>
    
    </LinearLayout>
    

    vertical_list_item.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="wrap_content"
        android:orientation="vertical">
    
        <TextView
            android:id="@+id/item_title"
            android:background="@android:color/darker_gray"
            android:layout_width="match_parent"
            android:layout_height="48dp"
            android:gravity="center_vertical"/>
    
        <android.support.v7.widget.RecyclerView
            android:id="@+id/item_horizontal_list"
            android:layout_width="match_parent"
            android:layout_height="50dp"/>
    </LinearLayout>
    

    update at 2015-05-20

    Old Answer:

    I have used TwoWayView to show horizontal lists in a vertical listview just like you. Here is my vertical and horizontal listview adapter code .It works fine for me, all views are reusable, all the rows scroll individually. I hope this may help you.

    public class RecommendAppAdapter extends BaseAdapter implements
        OnItemClickListener {
    public static final String TAG = "RecommendAppAdapter";
    
    //Vertical list data
    private Map<String, List<RecommendApp>> mMapData = new TreeMap<String, List<RecommendApp>>();
    
    private OnItemClickListener mOnItemClickListener = null;
    
    //Vertical list adapter
    public RecommendAppAdapter(Context context) {
    }
    
    @Override
    public boolean isEmpty() {
        return mMapData == null || mMapData.isEmpty();
    }
    
    @Override
    public int getCount() {
        if (!isEmpty()) {
            return mMapData.size();
        } else {
            return 0;
        }
    }
    
    //Get horizental list data
    @Override
    public List<RecommendApp> getItem(int position) {
        if (!isEmpty() && isAvaliablePostion(position)) {
            Iterator<Entry<String, List<RecommendApp>>> entries = mMapData
                    .entrySet().iterator();
            int i = 0;
            Entry<String, List<RecommendApp>> entry = null;
            while (entries.hasNext()) {
                entry = entries.next();
                if (i == position) {
                    return entry.getValue();
                }
                i++;
            }
        }
        return null;
    }
    
    @Override
    public long getItemId(int position) {
        return position;
    }
    
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder = null;
        ItemAdapter innerListAdapter = null;
        if (convertView == null) {
            holder = new ViewHolder();
            convertView = LayoutInflater.from(parent.getContext()).inflate(
                    R.layout.item_recommend_app, null);
            //Some views in vertical list
            holder.type = (TextView) convertView
                    .findViewById(R.id.item_rec_app_type_name);
            //Get horizental list view
            holder.hListView = (TwoWayView) convertView
                    .findViewById(R.id.item_rec_app_list);
            //Bind adapter on horizental list
            innerListAdapter = new ItemAdapter();
            holder.hListView.setAdapter(innerListAdapter);
            //Bind item click listener on horizental list
            holder.hListView.setOnItemClickListener(this);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
            innerListAdapter = (ItemAdapter) holder.hListView.getAdapter();
        }
        //Get horizental list data
        List<RecommendApp> itemList = getItem(position);
    
        holder.type.setText(itemList.get(0).getTypeName());
    
        //Deliver horizental list adapter data
        innerListAdapter.setData(itemList);
    
        return convertView;
    }
    
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position,
            long id) {
        switch (parent.getId()) {
        case R.id.item_rec_app_list:
            if (mOnItemClickListener != null) {
                mOnItemClickListener.onItemClick(parent, view, position, id);
            }
            break;
        }
    }
    
    public void setOnItemClickListener(OnItemClickListener listener) {
        mOnItemClickListener = listener;
    }
    
    public void setData(Map<String, List<RecommendApp>> data) {
        mMapData.clear();
        if (data != null && !data.isEmpty()) {
            mMapData.putAll(data);
        }
        notifyDataSetChanged();
    }
    
    private boolean isAvaliablePostion(int position) {
        if (position >= 0 && position < getCount()) {
            return true;
        } else {
            return false;
        }
    }
    
    
    private class ViewHolder {
        public TextView type;
        public TwoWayView hListView;
    }
    
    //Horizontal list adapter
    //All work are just like the normal use of ListView 
    private class ItemAdapter extends BaseAdapter {
    
        //Horizontal list data
        private List<RecommendApp> mInnerData = null;
    
        private FinalBitmap mFinalBitmap = FinalBitmap.create(MyApp
                .getInstance());
    
        @Override
        public boolean isEmpty() {
            return mInnerData == null || mInnerData.isEmpty();
        }
    
        @Override
        public int getCount() {
            if (!isEmpty()) {
                return mInnerData.size();
            }
            return 0;
        }
    
    
        @Override
        public RecommendApp getItem(int position) {
            if (position >= 0 && position < getCount()) {
                return mInnerData.get(position);
            }
            return null;
        }
    
        @Override
        public long getItemId(int position) {
            return position;
        }
    
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolderInner holder = null;
            if (convertView == null) {
                holder = new ViewHolderInner();
                Context context = parent.getContext();
                convertView = LayoutInflater.from(context).inflate(
                        R.layout.item_recommend_app_inner, null);
                holder.name = (TextView) convertView
                        .findViewById(R.id.item_rec_app_inner_name);
                holder.icon = (ImageView) convertView
                        .findViewById(R.id.item_rec_app_inner_icon);
                convertView.setTag(holder);
            } else {
                holder = (ViewHolderInner) convertView.getTag();
            }
            RecommendApp item = ItemAdapter.this.getItem(position);
            holder.name.setText(item.getAppName());
            mFinalBitmap.display(holder.icon, item.getIcon());
            return convertView;
        }
    
        public void setData(List<RecommendApp> data) {
            mInnerData = data;
            notifyDataSetChanged();
        }
    
        private class ViewHolderInner {
            public TextView name;
            public ImageView icon;
        }
    }
    

    }

    Edit 1

    RecommendApp is a POJO which contain data of an item that shows in the horizontal list.

    item_recommend_app.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" >
    
    <TextView
        android:id="@+id/item_rec_app_type_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/item_rec_app_type_name_bg"
        android:gravity="left|center_vertical"
        android:paddingBottom="@dimen/item_rec_app_type_name_paddingBottom"
        android:paddingLeft="@dimen/item_rec_app_type_name_paddingLeft"
        android:paddingTop="@dimen/item_rec_app_type_name_paddingTop"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:textIsSelectable="false" />
    
    <com.phonetools.appmanager.widget.TwoWayView
        android:id="@+id/item_rec_app_list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" />
    

    item_recommend_app_inner.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="@dimen/item_rec_app_inner_padding" >
    
    <ImageView
        android:id="@+id/item_rec_app_inner_icon"
        android:layout_width="@dimen/item_rec_app_inner_icon_width"
        android:layout_height="@dimen/item_rec_app_inner_icon_height"
        android:layout_gravity="center"
        android:contentDescription="@string/image_desc"
        android:scaleType="fitCenter" />
    
    <TextView
        android:id="@+id/item_rec_app_inner_name"
        android:layout_width="@dimen/item_rec_app_inner_icon_width"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:ellipsize="end"
        android:gravity="center"
        android:singleLine="true"
        android:textAppearance="?android:attr/textAppearanceSmall"
        android:textIsSelectable="false" />
    

    RecommendApp.java:

    public class RecommendApp {
    public RecommendApp() {
    }
    
    
    private String packageName;
    
    
    private String appName;
    
    
    private String versionName;
    
    
    private float size;
    
    
    private String icon;
    
    
    private int typeId;
    
    
    private String typeName;
    
    
    private String installLink;
    
    
    private String description;
    
    
    private float ratingScore;
    
    
    private long installedSum;
    

    }

    0 讨论(0)
  • 2021-01-16 04:03

    Instead of list view to show horizontal and vertical scrolling list. You can use table layout. Below is my code in which both side scrolling is performing well.

    Also you can customize it according your needs.

    Create MainActivity.java

    import android.app.Activity;
    import android.graphics.Color;
    import android.os.Bundle;
    import android.view.Gravity;
    import android.widget.TableLayout;
    import android.widget.TableRow;
    import android.widget.TableRow.LayoutParams;
    import android.widget.TextView;
    
    public class MainActivity extends Activity {
    
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
            TableRow.LayoutParams wrapWrapTableRowParams = new     TableRow.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        int[] fixedColumnWidths = new int[]{20, 20, 20, 20, 20, 20};
        int[] scrollableColumnWidths = new int[]{20, 20, 20, 30, 30, 30};
        int fixedRowHeight = 50;
        int fixedHeaderHeight = 60;
    
        TableRow row = new TableRow(this);
        //header (fixed vertically)
        TableLayout header = (TableLayout) findViewById(R.id.table_header);
        row.setLayoutParams(wrapWrapTableRowParams);
        row.setGravity(Gravity.CENTER);
    
        row.addView(makeTableRowWithText("col 1", fixedColumnWidths[0], fixedHeaderHeight));
        row.addView(makeTableRowWithText("col 2", fixedColumnWidths[1], fixedHeaderHeight));
        row.addView(makeTableRowWithText("col 3", fixedColumnWidths[2], fixedHeaderHeight));
        row.addView(makeTableRowWithText("col 4", fixedColumnWidths[3], fixedHeaderHeight));
        row.addView(makeTableRowWithText("col 5", fixedColumnWidths[4], fixedHeaderHeight));
        row.addView(makeTableRowWithText("col 6", fixedColumnWidths[5], fixedHeaderHeight));
        header.addView(row);
    
        //header (fixed horizontally)
    
        TableLayout fixedColumn = (TableLayout) findViewById(R.id.fixed_column);
    
        //rest of the table (within a scroll view)
    
        TableLayout scrollablePart = (TableLayout) findViewById(R.id.scrollable_part);
    
        for(int i = 0; i < 50; i++)
        {
           TextView fixedView = makeTableRowWithText("row number " + i,   scrollableColumnWidths[0], fixedRowHeight);
    
            fixedColumn.addView(fixedView);
            row = new TableRow(this);
            row.setLayoutParams(wrapWrapTableRowParams);
            row.setGravity(Gravity.CENTER); 
            row.setBackgroundColor(Color.WHITE);
            row.addView(makeTableRowWithText("value 2", scrollableColumnWidths[1], fixedRowHeight));
            row.addView(makeTableRowWithText("value 3", scrollableColumnWidths[2], fixedRowHeight));
            row.addView(makeTableRowWithText("value 4", scrollableColumnWidths[3], fixedRowHeight));
            row.addView(makeTableRowWithText("value 5", scrollableColumnWidths[4], fixedRowHeight));
            row.addView(makeTableRowWithText("value 6", scrollableColumnWidths[5], fixedRowHeight));
            scrollablePart.addView(row);
       }
    }
    
    //util method
    private TextView recyclableTextView;
     public TextView makeTableRowWithText(String text, int widthInPercentOfScreenWidth, int   fixedHeightInPixels) {
    int screenWidth = getResources().getDisplayMetrics().widthPixels;
    recyclableTextView = new TextView(this);
    recyclableTextView.setText(text);
    recyclableTextView.setTextColor(Color.BLACK);
    recyclableTextView.setTextSize(20);
    recyclableTextView.setWidth(widthInPercentOfScreenWidth * screenWidth / 100);
    recyclableTextView.setHeight(fixedHeightInPixels);
    return recyclableTextView;
      }
    }
    

    Create activity_main.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:gravity="center_horizontal"
    android:id="@+id/fillable_area">
    <TableLayout
        android:id="@+id/table_header"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"/>
    <ScrollView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content">
        <LinearLayout android:orientation="horizontal"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:gravity="center_horizontal"
            android:id="@+id/fillable_area">
            <TableLayout
                android:id="@+id/fixed_column"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"/>
            <HorizontalScrollView
                android:layout_width="fill_parent"
                android:layout_height="wrap_content">
                <TableLayout
                    android:id="@+id/scrollable_part"
                    android:layout_width="fill_parent"
                    android:layout_height="fill_parent"/>
            </HorizontalScrollView>
        </LinearLayout>
    </ScrollView>
    </LinearLayout>
    

    Try this i'll solve your needs.

    Thanks

    0 讨论(0)
提交回复
热议问题