0

I have this code to create a parallax scrolling effect,i could not found any errors in this code but when i run the app it crashes and it is shown that a Run time exception in the code,i did not understand what the problem is.Can anybody help??

Here is my MainActivity

public class MainActivity extends Activity {
private int lastTop = 0;
ImageView image;
ListView listView;

ArrayAdapter adapter;
ArrayList<String> items = new ArrayList<>();

public void parallax(final View v) {
    final Rect r = new Rect();
    v.getLocalVisibleRect(r);

    if (lastTop != r.top) {
        lastTop = r.top;
        v.post(new Runnable() {
            @Override
            public void run() {
                v.setY((float) (r.top / 2.0));
            }
        });
    }
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    listView = (ListView) findViewById(R.id.listView);

    items.add("List Item 1");
    items.add("List Item 2");
    items.add("List Item 3");
    items.add("List Item 4");
    items.add("List Item 5");
    items.add("List Item 6");
    items.add("List Item 7");
    items.add("List Item 8");
    items.add("List Item 9");
    items.add("List Item 10");
    items.add("List Item 11");
    items.add("List Item 12");
    items.add("List Item 13");
    items.add("List Item 14");
    items.add("List Item 15");
    items.add("List Item 16");
    items.add("List Item 17");
    items.add("List Item 18");
    items.add("List Item 19");
    items.add("List Item 20");

    adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, items);
    listView.setAdapter(adapter);
    adapter.notifyDataSetChanged();
    View view = getLayoutInflater().inflate(R.layout.header, null, false);
    image = (ImageView) view.findViewById(R.id.image);
    listView.addHeaderView(view);
    listView.setOnScrollListener(new AbsListView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {
            parallax(image);
        }

        @Override
        public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
            parallax(image);
        }
    });
}
}

Here is my logcat

java.lang.RuntimeException: Unable to start activity ComponentInfo{in.zoid.parallaxtutorial/in.zoid.parallaxtutorial.MainActivity}: java.lang.IllegalStateException: Cannot add header view to list -- setAdapter has already been called.
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2110)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2135)
        at android.app.ActivityThread.access$700(ActivityThread.java:140)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1237)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:137)
        at android.app.ActivityThread.main(ActivityThread.java:4921)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:511)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1027)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:794)
        at dalvik.system.NativeStart.main(Native Method)
 Caused by: java.lang.IllegalStateException: Cannot add header view to list -- setAdapter has already been called.
        at android.widget.ListView.addHeaderView(ListView.java:261)
        at android.widget.ListView.addHeaderView(ListView.java:290)
        at in.zoid.parallaxtutorial.MainActivity.onCreate(MainActivity.java:70)
        at android.app.Activity.performCreate(Activity.java:5206)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1094)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2074)

           

Gopal Singh Sirvi
  • 4,539
  • 5
  • 33
  • 55
jibinz
  • 23
  • 1
  • 9

3 Answers3

1

you have getting illegalstate because you first assign adapter and then assign header. just reverse this things first assign header and then assign adapter your problem was solved.

public class MainActivity extends Activity {
private int lastTop = 0;
ImageView image;
ListView listView;

ArrayAdapter adapter;
ArrayList<String> items = new ArrayList<>();

public void parallax(final View v) {
    final Rect r = new Rect();
    v.getLocalVisibleRect(r);

    if (lastTop != r.top) {
        lastTop = r.top;
        v.post(new Runnable() {
            @Override
            public void run() {
                v.setY((float) (r.top / 2.0));
            }
        });
    }
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    listView = (ListView) findViewById(R.id.listView);

    items.add("List Item 1");
    items.add("List Item 2");
    items.add("List Item 3");
    items.add("List Item 4");
    items.add("List Item 5");
    items.add("List Item 6");
    items.add("List Item 7");
    items.add("List Item 8");
    items.add("List Item 9");
    items.add("List Item 10");
    items.add("List Item 11");
    items.add("List Item 12");
    items.add("List Item 13");
    items.add("List Item 14");
    items.add("List Item 15");
    items.add("List Item 16");
    items.add("List Item 17");
    items.add("List Item 18");
    items.add("List Item 19");
    items.add("List Item 20");

    View view = getLayoutInflater().inflate(R.layout.header, null, false);
    image = (ImageView) view.findViewById(R.id.image);
    listView.addHeaderView(view);

    adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, items);
    listView.setAdapter(adapter);
    adapter.notifyDataSetChanged();
    listView.setOnScrollListener(new AbsListView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {
            parallax(image);
        }

        @Override
        public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
            parallax(image);
        }
    });
}

}

Hiren Vaghela
  • 61
  • 1
  • 1
  • 6
0

apply this change your problem solve ::

public class MainActivity extends Activity {
    private int lastTop = 0;
    ImageView image;
    ListView listView;

    ArrayAdapter adapter;
    ArrayList<String> items = new ArrayList<>();

    public void parallax(final View v) {
        final Rect r = new Rect();
        v.getLocalVisibleRect(r);

        if (lastTop != r.top) {
            lastTop = r.top;
            v.post(new Runnable() {
                @Override
                public void run() {
                    v.setY((float) (r.top / 2.0));
                }
            });
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        listView = (ListView) findViewById(R.id.listView);

        items.add("List Item 1");
        items.add("List Item 2");
        items.add("List Item 3");
        items.add("List Item 4");
        items.add("List Item 5");
        items.add("List Item 6");
        items.add("List Item 7");
        items.add("List Item 8");
        items.add("List Item 9");
        items.add("List Item 10");
        items.add("List Item 11");
        items.add("List Item 12");
        items.add("List Item 13");
        items.add("List Item 14");
        items.add("List Item 15");
        items.add("List Item 16");
        items.add("List Item 17");
        items.add("List Item 18");
        items.add("List Item 19");
        items.add("List Item 20");

        View view = getLayoutInflater().inflate(R.layout.header, null, false);
        image = (ImageView) view.findViewById(R.id.image);
        listView.addHeaderView(view);

        adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, items);
        listView.setAdapter(adapter);
        adapter.notifyDataSetChanged();
        listView.setOnScrollListener(new AbsListView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {
                parallax(image);
            }

            @Override
            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
                parallax(image);
            }
        });
    }
}
Hiren Vaghela
  • 916
  • 1
  • 9
  • 22
0

I have no reputation so I can only write my words in the answer.. I think you should define a listview class to extends listview, and init the headview in it. like the code below .

public FriendCircleList(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    // TODO Auto-generated constructor stub
    initHeadView(context);
}

private void initHeadView(Context context) {
    headView = LayoutInflater.from(context).inflate(R.layout.header, null);
    addHeaderView(headView);
    circle = (ImageView) headView.findViewById(R.id.circleprogress);
    headView.getViewTreeObserver().addOnPreDrawListener(
            new OnPreDrawListener() {
                @Override
                public boolean onPreDraw() {
                    if (headView.getMeasuredHeight() > 0) {
                        headViewHeight = headView.getMeasuredHeight();
                        headView.getViewTreeObserver()
                                .removeOnPreDrawListener(this);
                    }
                    return true;
                }
            });
    setOnScrollListener(this);
    currentScrollState = OnScrollListener.SCROLL_STATE_IDLE;
    currentState = LoadState.LOADSTATE_IDLE;
    firstVisibleItem = 0;
    CircleMarginTop = 76;
    setSelector(new ColorDrawable(Color.TRANSPARENT));
    setItemsCanFocus(true);
}

Alse,I think write addheadview() before setadpter() maybe work. Hope it can help you.