Dynamic ListView issue on Android

时间:2015-09-29 00:52:49

标签: android listview dynamic

Currently I am working on an Android app and use parse as backend where I have created a ListView of nearby places dynamically. But I face the following design issue: When the user clicks on a place, a view must appear under the clicked item.

And I have faced a problem with grouping the place, as you can see in figure 1, there are many branches for HSBC bank. In which case they are under HSBC.

I have tried expandable ListView before, but it does not give much customization for child view , just simple one.

my BaseAdapter:

import java.util.ArrayList;
import java.util.List;

import com.parse.ParseGeoPoint;

import android.content.Context;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.ViewManager;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

public class ListViewAdapter extends BaseAdapter {

    // Declare Variables
    Context context;
    LayoutInflater inflater;
    //ImageLoader imageLoader;
    private List<AnywallPost> AnywallPostlist = null;
    private ArrayList<AnywallPost> arraylist;

    public ListViewAdapter(Context context,
            List<AnywallPost> AnywallPostlist) {
        this.context = context;
        this.AnywallPostlist = AnywallPostlist;
        inflater = LayoutInflater.from(context);
        this.arraylist = new ArrayList<AnywallPost>();
        this.arraylist.addAll(AnywallPostlist);

    }

    public class ViewHolder {
        TextView distance;
        TextView name;

    }

    @Override
    public int getCount() {
        return AnywallPostlist.size();
    }

    @Override
    public Object getItem(int position) {
        return AnywallPostlist.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    public View getView(final int position, View view, ViewGroup parent) {
        final ViewHolder holder;
        final View row=view;

        if (view == null) {
            holder = new ViewHolder();
            view = inflater.inflate(R.layout.user_custom, null);
            // Locate the TextViews in listview_item.xml
            holder.distance = (TextView) view.findViewById(R.id.disView);
            holder.name = (TextView) view.findViewById(R.id.nameView);


            view.setTag(holder);
        } else {
            holder = (ViewHolder) view.getTag();
        }
        // Set the results into TextViews

        holder.name.setText(AnywallPostlist.get(position).getText());
        holder.distance.setText(AnywallPostlist.get(position).getDis());


        //Listen for ListView Item Click
        view.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View arg0) {

                Toast.makeText(context,AnywallPostlist.get(position).getText(), Toast.LENGTH_LONG).show();


            }
        });
        return view;
    }

}

.

import com.parse.ParseClassName;
import com.parse.ParseGeoPoint;
import com.parse.ParseObject;
import com.parse.ParseQuery;
import com.parse.ParseUser;

/**
 * Data model for a post.
 */
@ParseClassName("places")
public class AnywallPost extends ParseObject {

  public String getText() {
    return getString("text");
  }

  public void setText(String value) {
    put("text", value);
  }

public String getBank() {
    return getString("bank");
  }

  public void setBank(String value) {
    put("bank", value);
  }

  public ParseUser getUser() {
    return getParseUser("user");
  }

  public void setUser(ParseUser value) {
    put("user", value);
  }


  public String getType()
  {
    return getString("type");  
  }

  public void setType(String value)
  {
    put("type",value);
  }

  public ParseGeoPoint getLocation() {
    return getParseGeoPoint("location");
  }

  public void setLocation(ParseGeoPoint value) {
    put("location", value);
  }


  public String getDis()
  {
    return getString("dis");  
  }

  public void setdis(String value)
  {
    put("dis",value);
  }

  public static ParseQuery<AnywallPost> getQuery() {
    return ParseQuery.getQuery(AnywallPost.class);
  }
}

.

switch (getItemViewType(position)) {
            case 0:
                Bank bank = (Bank) getItem(position);
                holder.name.setText(bank.name);
                String str = String.valueOf(bank.numBranches);
                holder.cn.setText(str);
                imageLoader.DisplayImage(bank.image,
                        holder.logo);
                Toast.makeText(getActivity(), "img"+bank.image,Toast.LENGTH_LONG).show();
                // ... set the image here
                // ... set the number of branches here
                break;
            case 1:
                branch = (AnywallPost) getItem(position);
                holder.name.setText(branch.getText());
                holder.distance.setText(branch.getDis());
                holder.b.setText(branch.getbranch());
                imageLoader.DisplayImage(branch.getimg(),
                        holder.logo);
                break;
            case 2:
                branch = (AnywallPost) getItem(position);
                holder.name.setText(branch.getText());
                holder.distance.setText(branch.getDis());
                holder.b.setText(branch.getbranch());
                imageLoader.DisplayImage(branch.getimg(),
                        holder.logo);
                // ... set values for all the expanded view widgets too
                break;
        }

I have used this code to get image from parse and I add it to AnywallPost

ParseFile image = (ParseFile) country.get("image");

AnywallPost map = new AnywallPost();

map.setimg(image.getUrl());

then, I used this code to load the image and it worked fine

imageLoader.DisplayImage(AnywallPostlist.get(position).getimg(),
                holder.logo);

2 个答案:

答案 0 :(得分:0)

这是我的想法:

你将有两个布局,一个简短的布局,名称为&amp;距离,以及名称为&amp;的扩展名距离加上所有细节。

简短布局的视图类型为0,展开的布局视图类型为1.

单击该项目时,在列表模型中设置一个标志,表示视图已从简短视图切换到长视图。所以你应该看到视图开关。如果单击展开的视图,它将恢复为简短视图。

我没有办法测试这个,但这是我认为代码的样子:

public class ListViewAdapter extends BaseAdapter {

    // Declare Variables
    Context context;
    LayoutInflater inflater;
    //ImageLoader imageLoader;
    private List<AnywallPost> AnywallPostlist = null;
    private ArrayList<AnywallPost> arraylist;

    /** this array holds a flag for each item to show if it is in brief view more or expanded view mode*/
    private boolean[] expandedView;

    public ListViewAdapter(Context context,
            List<AnywallPost> AnywallPostlist) {
        this.context = context;
        this.AnywallPostlist = AnywallPostlist;
        inflater = LayoutInflater.from(context);
        this.arraylist = new ArrayList<AnywallPost>();
        this.arraylist.addAll(AnywallPostlist);

        this.expandedView = new boolean[AnywallPostlist.size()];
    }

    public class ViewHolder {
        TextView distance;
        TextView name;
        // ... add all your expanded view fields here too
    }

    @Override
    public int getCount() {
        return AnywallPostlist.size();
    }

    @Override
    public int getViewTypeCount() {
        return 2; // brief & expanded
    }

    @Override
    public int getItemViewType(int position) {
        return expandedView[position] ? 1 : 0;
    }

    @Override
    public Object getItem(int position) {
        return AnywallPostlist.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    public View getView(final int position, View view, ViewGroup parent) {
        final ViewHolder holder;
        final View row=view;

        if (view == null) {
            holder = new ViewHolder();
            int layout =  expandedView[position] ? R.layout.user_custom_expanded : R.layout.user_custom;
            view = inflater.inflate(layout, parent, false);
            // Locate the TextViews in listview_item.xml
            holder.distance = (TextView) view.findViewById(R.id.disView);
            holder.name = (TextView) view.findViewById(R.id.nameView);

            if (expandedView[position]) {
                // ... locate all the expanded view widgets too
            }

            view.setTag(holder);
        } else {
            // because the view type is determined by expandedView[position], the correct layout will be recycled here
            holder = (ViewHolder) view.getTag();
        }
        // Set the results into TextViews

        holder.name.setText(AnywallPostlist.get(position).getText());
        holder.distance.setText(AnywallPostlist.get(position).getDis());

        if (expandedView[position]) {
            // ... set all the values for your expanded view too
        }

        //Listen for ListView Item Click
        view.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View arg0) {

                if (expandedView[position]) {
                    // this is expanded view so toggle it back to brief view
                    expandedView[position] = false;
                } else {
                    // clear any expanded views elsewhere
                    expandedView = new boolean[AnywallPostlist.size()];
                    // toggle brief view to expanded
                    expandedView[position] = true;
                }

                // forces the ListView to refresh and convert the brief view into an expanded view and vice versa.
                ListViewAdapter.this.notifyDataSetChanged();
                // Toast.makeText(context,AnywallPostlist.get(position).getText(), Toast.LENGTH_LONG).show();
            }
        });

        if (expandedView[position]) {
            // ... add all your event listeners for the expanded view widgets
        }

        return view;
    }

}

您还可以向视图添加带有展开/折叠指示符的切换按钮,以控制展开/折叠,这样您就不会单击视图上的任何位置进行更改。

如果您愿意,可以使用ExpandableListView执行此操作,只需更改为ExpandableListAdapter并稍微改变布局。

答案 1 :(得分:0)

以下是制作异构列表的一些代码:

仔细看看构造函数,看看我是如何通过银行将它们分成一个大的列表来分割它们的。

该列表只是一个Object数组,因此您可以找出该项目的内容:

如果它是Bank,那么它就是银行。

如果它是AnywallPostexpandedView[position] == false那么它就是一个分支,简短的视图

如果它是AnywallPostexpandedView[position] == true那么它就是一个分支,展开的视图

public class Bank {
    private String name;
    private String image;   //  maybe this needs to be URL?
    private int numBranches;
}

public class ListViewAdapter extends BaseAdapter {

    // Declare Variables
    Context context;
    LayoutInflater inflater;
    ImageLoader imageLoader;
    private Object[] masterList;

    /** this array holds a flag for each item to show if it is in brief view more or expanded view mode*/
    private boolean[] expandedView;

    public ListViewAdapter(Context context,
                           List<AnywallPost> AnywallPostlist) {
        this.context = context;
        inflater = LayoutInflater.from(context);

        /*
         * Phase I -- get list of banks and organize the branches by bank
         */
        int count = 0;
        List<String bankNames = new ArrayList<String>();
        List<Bank> banks = new ArrayList<Bank>();
        Map<String, Bank> bankMap = new HashMap<String, Bank>();
        Map<String, List<AnywallPost>> mappedBranches = new HashMap<String, List<AnywallPost>>();

        Bank bank = null;
        List<AnywallPost> branches = null;

        for (AnywallPost branch : AnywallPostlist) {

            // have we started a branch list for this bank?
            if  (! bankNames.contains(branch.getBank())) {  // no we haven't

                // remember the bank name
                bankNames.add(branch.getBank());

                // init a new Bank
                bank = new Bank();
                bank.name = branch.getBank();
                bank.image = branch.getImg();  // if this is URL make image in Bank a URL
                banks.add(bank);
                bankMap.put(bank.name, bank);
                count++;

                // create a list for this bank's branches and index it by bank
                branches = new ArrayList<AnywallPost>();
                mappedBranches.put(branch.getBank(), branches);

            } else {   // yes we have

                // get the bank for this name
                // this fixes the problem with the branch counts
                bank = bankMap.get(branch.getBank());

                // get the branch list we already created for this bank
                branches = mappedBranches.get(branch.getBank());
            }

            // remember the branch for this bank
            branches.add(branch);
            count++;

            // increment the number of branches for this bank
            bank.numBranches++;
        }

        /*
         * Phase II -- sort the banks and branches
         */

        // ... here you can order the banks by name, branches by distance, etc.

        /*
         * Phase III -- create the mixed list
         */
        int index = 0;
        masterList = new Object[count];

        for (Bank bank : banks) {

            // append a bank to the list
            masterList[index] = bank;
            index++;

            for (AnywallPost branch : mappedBranches.get(bank.name)) {

                // append a branch to the list
                masterList[index] = branch;
                index++;
            }
        }

        this.expandedView = new boolean[count];
    }

    public class ViewHolder {
        TextView distance;
        TextView name;
        ImageView logo;
        // ... add all your expanded view fields here too
    }

    @Override
    public int getCount() {
        return masterList.length;
    }

    @Override
    public int getViewTypeCount() {
        return 4; // bank brief, bank expanded, branch brief & branch expanded
    }

    @Override
    public Object getItem(int position) {
        return masterList[position];
    }

    @Override
    public int getItemViewType(int position) {
        if (getItem(position) instanceof Bank) {
            return expandedView[position] ? 1 : 0;
        }
        return expandedView[position] ? 3 : 2;
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(final int position, View view, ViewGroup parent) {
        final ViewHolder holder;
        final View row=view;

        if (view == null) {
            holder = new ViewHolder();
            int layout =  0;
            switch (getItemViewType(position)) {
                case 0:
                    layout = R.layout.bank_brief;
                    break;
                case 1:
                    layout = R.layout.bank_expanded;
                    break;
                case 2:
                    layout = R.layout.branch_brief;
                    break;
                case 3:
                    layout = R.layout.branch_expanded;
                    break;
            }
            view = inflater.inflate(layout, parent, false);

            switch (getItemViewType(position)) {
                case 0:
                    holder.name = (TextView) view.findViewById(R.id.nameView);
                    break;
                case 1:
                    holder.name = (TextView) view.findViewById(R.id.nameView);
                    // ... locate all the bank expanded view widgets too
                    break;
                case 2:
                    holder.name = (TextView) view.findViewById(R.id.nameView);
                    holder.distance = (TextView) view.findViewById(R.id.disView);
                    break;
                case 3:
                    holder.name = (TextView) view.findViewById(R.id.nameView);
                    holder.distance = (TextView) view.findViewById(R.id.disView);
                    // ... locate all the expanded view widgets too
                    break;
            }

            view.setTag(holder);

        } else {
            // because the view type is determined by expandedView[position], the correct layout will be recycled here
            holder = (ViewHolder) view.getTag();
        }

        AnywallPost branch = null;
        switch (getItemViewType(position)) {
            case 0:
                Bank bank = (Bank) getItem(position);
                holder.name.setText(bank.name);
                imageLoader.DisplayImage(bank.image, holder.logo);
                // ... set the number of branches here
                break;
            case 1:
                holder.name.setText(bank.name);
                imageLoader.DisplayImage(bank.image, holder.logo);
                // ... set the number of branches here
                break;
            case 1:
                branch = (AnywallPost) getItem(position);
                holder.name.setText(branch.getText());
                holder.distance.setText(branch.getDis());
                break;
            case 2:
                branch = (AnywallPost) getItem(position);
                holder.name.setText(branch.getText());
                holder.distance.setText(branch.getDis());
                // ... set values for all the expanded view widgets too
                break;
        }

        //Listen for ListView Item Click
        view.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View arg0) {

                if (expandedView[position]) {
                    // this is expanded view so toggle it back to brief view
                    expandedView[position] = false;
                } else {
                    // clear any expanded views elsewhere
                    expandedView = new boolean[expandedView.length];
                    // toggle brief view to expanded
                    expandedView[position] = true;
                }

                if (getItem(position) instanceof AnywallPost) { // only for branches
                    // AnywallPost branch = (AnywallPost) getItem(position);
                    // Toast.makeText(context, branch.getText(), Toast.LENGTH_LONG).show();
                }

                // forces the ListView to refresh and convert the brief view into an expanded view and vice versa.
                notifyDataSetChanged();
            }
        });

        if (expandedView[position]) {
            // ... add all your event listeners for the expanded view widgets
        }

        return view;
    }
}