Implementing horizontalList inside a vertical list in android

前端 未结 2 474
再見小時候
再見小時候 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> 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 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 {
    
            private List> mDataList;
    
            public VerticalAdapter() {
            }
    
            public void setData(List> 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 {
    
            private List 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 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

    
    
        
    
    
    

    horizontal_list_item.xml

    
    
    
        
    
    
    

    vertical_list_item.xml

    
    
    
        
    
        
    
    

    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> mMapData = new TreeMap>();
    
    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 getItem(int position) {
        if (!isEmpty() && isAvaliablePostion(position)) {
            Iterator>> entries = mMapData
                    .entrySet().iterator();
            int i = 0;
            Entry> 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 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> 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 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 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 :

    
    
    
    
    
    
    

    item_recommend_app_inner.xml:

    
    
    
    
    
    
    

    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;
    

    }

提交回复
热议问题