Search code examples
androidperformanceandroid-listviewandroid-viewhorizontalscrollview

Rearranging other views in HorizontalScrollView when size of one view changes


I am drawing a rectangles views and arranging it in HorizontalScrollView. I want a functionality such that when a rectangle(view) is clicked, it will grow in size but other rectangles(views) size should remain as it is.

I have a class LockHorizontalScrollview which draws the initial view by calling getView() method of CustomListAdapter class. Also, I am attaching onClicklistener in getView() method.

So when any view is clicked, I am redrawing all the views of HorizontalScrollView. But I am facing one problem, how do I tell the LockHorizontalScrollview(this class will draw all my views) class to redraw all the views again.

The problem I am facing is when I click any view, the application crashes

LockHorizontalScrollview class is called by main activity.This class call the getView() method of custom Adapter to draw all views. This class draw all views.

public class LockHorizontalScrollview extends HorizontalScrollView {
    Context context;
    int prevIndex = 0;
    int data[] = new int[] {200,200,200,200,200,200,200,200,200,200,200,200};

    CustomListAdapter kk;
    void  changedata(int position)
    {
        data[position]+=50;
        abc(kk);

    }




    public void setAdapter(Context context, CustomListAdapter mAdapter) {

        try {
            this.kk=mAdapter;
            fillViewWithAdapter(mAdapter);
        } catch (ZeroChildException e) {

            e.printStackTrace();
        }
    }

    private void fillViewWithAdapter(CustomListAdapter mAdapter)
            throws ZeroChildException {
        if (getChildCount() == 0) {
            throw new ZeroChildException(
                    "CenterLockHorizontalScrollView must have one child");
        }
        if (getChildCount() == 0 || mAdapter == null)
        {       Log.e("Ronak","Came at zero");
            return;
        }

        ViewGroup parent = (ViewGroup) getChildAt(0);

        //parent.removeAllViews();

        for (int i = 0; i < mAdapter.getCount(); i++) {
            parent.addView(mAdapter.getView(i, null, parent));
        }
    }

    void abc(CustomListAdapter mAdapter)
    {
        Log.e("Ronak","Came at");
        ViewGroup parent = (ViewGroup) getChildAt(0);

        //parent.removeAllViews();

        for (int i = 0; i < mAdapter.getCount(); i++) {
            parent.addView(mAdapter.getViewType(i, null, parent,data[i]));
        }
    }


}

My custom adapter is

    public class CustomListAdapter extends BaseAdapter  {

     static class ViewHolder {
            public DrawView drawview;
            public TextView textview;
            public LinearLayout ll;
        }

    private ArrayList<String> mData = new ArrayList<String>();
    private LayoutInflater mInflater;
    Context c;

    HorizontalScrollViewActivity abc=new HorizontalScrollViewActivity();
    //CenterLockHorizontalScrollview abc=new CenterLockHorizontalScrollview(c, null);
    private TreeSet<Integer> mSeparatorsSet = new TreeSet<Integer>();


    public CustomListAdapter(Context c, ArrayList<String> data) {
        mInflater = (LayoutInflater)c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        mData=data;
        this.c=c;
    }

    public void addItem(final String item) {
        mData.add(item);
        notifyDataSetChanged();
    }



    @Override
    public int getItemViewType(int position) {
        return 0;
    }

    @Override
    public int getViewTypeCount() {
        return 1;
    }

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

    @Override
    public String getItem(int position) {
        return mData.get(position);
    }

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

    private int getWidth(String aa)
    {
        int k=aa.length();
        if(k>0 && k<=3)
            return 200;
        if(k>3 && k<=6)
            return 250;
        if(k>6 && k<=9)
            return 300;
        if(k>9 && k<=12)
            return 350;
        if(k>12 && k<=15)
            return 400;
        if(k>15 && k<=18)
            return 450;
        if(k>18 && k<=21)
            return 500;
        if(k>21 && k<=24)
            return 550;
        if(k>24 && k<=27)
            return 600;

        return 700;

    }

    private int getHeight(String aa)
    {

        return 350;
    }


    @Override
    public View getView(final int position,  View convertView, final ViewGroup parent) {
        Log.e("Ronak","Came at getview");

        ViewHolder holder = null;
        if (convertView == null) {
                        holder = new ViewHolder();
                        convertView = mInflater.inflate(R.layout.news_list_item,null);
                        final LinearLayout layout = (LinearLayout)convertView.findViewById(R.id.mainLayout);
                        //final LinearLayout.LayoutParams parms = new LinearLayout.LayoutParams(300,400);
                        //layout.setLayoutParams(parms);
                           TextView t= (TextView)convertView.findViewById(R.id.textView1);

                        //t.setWidth(width);
                        //t.setBackgroundColor(0x7F2626);
                        holder.textview = t;
                        holder.ll=layout;
                        DrawView abc = (DrawView)convertView.findViewById(R.id.drawview);
                        holder.drawview=abc;
                        Log.e("Ronak","reached here3");            
                        convertView.setTag(holder);
        } else {
            holder = (ViewHolder)convertView.getTag();
        }
        holder.textview.setText(mData.get(position));
        convertView.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
             Toast.makeText(c, "Clicked on="+position, 2).show();
            // Log.e
             abc.get().changedata(position);

                }
        });

        return convertView;
        }

    public View getViewType(final int position,  View convertView, final ViewGroup parent, int width) {
                        convertView = mInflater.inflate(R.layout.news_list_item,null);
                        final LinearLayout layout = (LinearLayout)convertView.findViewById(R.id.mainLayout);
                        final LinearLayout.LayoutParams parms = new LinearLayout.LayoutParams(width,150);
                        layout.setLayoutParams(parms);

        return convertView;
        }

There is also DrawView.java class which draw a rectangle

and my xml news_list_item.xml which is layout of each view of Horizontal Scroll View

Also my main Activity is

    public class HorizontalScrollViewActivity extends Activity {
    CenterLockHorizontalScrollview centerLockHorizontalScrollview;
    CustomListAdapter customListAdapter;
    Button btnPrev, btnNext, btnActivity;
    int currIndex = 0;
    private TextView text;

    int data[] = new int[] {200,200,200,200,200,200,200,200,200,200,200,200};

    ArrayList<String> list = new ArrayList<String>() {

        {
            add("Jan");
            add("Feb");
            add("Mar");
        }
    };

    @Override
    public void onCreate(Bundle savedInstanceState) {

        Log.e("Ronak","Came at main");


        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_horizontal_scroll_view);
        centerLockHorizontalScrollview = (CenterLockHorizontalScrollview) findViewById(R.id.scrollView);
        customListAdapter = new CustomListAdapter(this, list);
        centerLockHorizontalScrollview.setAdapter(this, customListAdapter);

    }

Solution

  • The method you're looking for is requestLayout(). Calling it will make the callee re-measure and re-layout all it's children.

    On a side note, is there any particular reason you're using an Adapter with a HorizontalScrollView (which is not an AdapterView)?

    The whole idea behind using Adapter/AdapterView is view recycling -- ScrollViews don't do that. Since you don't use a ListView (or other AdapterView), using an adapter is overkill.

    Also, I don't think putting the content filling logic into a ScrollView is a good idea either. You should probably do it in it's child (the one called parent in your code). ScrollViews are meant to provide easy means of adding scrolling capabilities to any other view -- by simply wrapping it in layout file; extending them with content-aware logic is against their purspose :)