SimplyProgrammer
SimplyProgrammer

Reputation: 1819

How to implement Scroll View with views getting aligned at the top?

I came across this UI and am trying to use it. enter image description here

  1. In the image what I guess is, the root layout is a Scroll view.
  2. The top view inside the ScrollView is Relative layout and below it is ListView which gets loaded depending on the dates selected. (not sure)
  3. When the view is scrolled up the button present on the top View aligns itself to the top of the parent layout.
  4. And then the rest is scrolled like a listview.
  5. When scrolled down again the top view is visible.

NB: I have tried to apply what I feel like has been used for such effect. But I am not able to align the button of the top view to the parent layout. If needed I can post the code.

Please help me to find what exactly is the logic behind this effect. Thanks.

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context="com.mypackage.Appointments_Main_ActivityFragment">
<RelativeLayout

    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <LinearLayout
        android:layout_width="match_parent"
        android:orientation="vertical"
        android:id="@+id/linear"
        android:layout_height="wrap_content">
        <TextView
            android:text="From Date"
            android:id="@+id/frm"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="14dip"
            android:textStyle="bold"
            android:layout_marginRight="5dip" />
        <TextView
            android:text="To Date"
            android:id="@+id/to"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="14dip"
            android:textStyle="bold"
            android:layout_marginRight="5dip" />
    </LinearLayout>
    <Button
        android:id="@+id/alertbtn"
        android:layout_below="@id/linear"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:background="@color/DarkGray"
        android:padding="16dp"
        android:text="Alerts"
        android:textColor="@color/accentforGray" />

    <ListView
        android:layout_below="@id/alertbtn"
        android:id="@+id/listView1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dip"
        android:background="#B29090" >
    </ListView>
</RelativeLayout>

Upvotes: 0

Views: 1397

Answers (2)

SimplyProgrammer
SimplyProgrammer

Reputation: 1819

I solved the problem myself.

For getting the same look and feel as mentioned in the image.

I did the following:

1) Defined 3 layouts used in ListView.

list_top_one -> for top view having from date and to date text view

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical" android:layout_width="match_parent"
        android:layout_height="match_parent">
        <TextView
            android:id="@+id/frmdate"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="16dp"
            android:text="from date"/>
        <TextView
            android:id="@+id/todate"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="16dp"
            android:text="to date"/>

    </LinearLayout>

b) list_item_in_middle -> for having button like feel

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical" android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="16dp"
        android:id="@+id/llHeader">
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/btn_background"
        android:text="OK"
        android:padding="16dp"/>
    </LinearLayout>

c) list_items -> for holding the dynamically loaded value.

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#FFBB00"
        android:orientation="vertical" >

        <TextView
            android:textColor="#000"
            android:layout_margin="30dp"
            android:id="@+id/button1"
            android:layout_gravity="center"
            android:text="OK"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

    </LinearLayout>

2) Main activity layout.

a) Contains a listview

b) And includes a layout that is to be shown as button.

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

        <ListView
            android:id="@+id/listview"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

        </ListView>

        <!-- This LinearLayout's visibility is toggled -->
        <include layout="@layout/list_item_in_middle" />

    </RelativeLayout>

Reference: Making a middle element to get stuck in the header (ScrollView/ListView)

3) ListAdapter class

    public class ListAdapter extends BaseAdapter {
        public Context mContext;
        TextView btCurrent;
        ArrayList<Integer> newarrays = new ArrayList<>();

        ListAdapter(Context context,Integer[] arrval) {
            mContext = context;
            newarrays.addAll(Arrays.asList(arrval));
        }

        public void InitializeValues(Integer[] arrval){
            newarrays.addAll(Arrays.asList(arrval));
        }

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

        @Override
        public Object getItem(int arg0) {
            return newarrays.get(arg0);
        }

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

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            if(position == 0){
                convertView = inflater.inflate(R.layout.list_item_in_middle, null);//Adding btn layout
            }else {
                convertView = inflater.inflate(R.layout.list_items, null);// Adding other elements
                btCurrent = (TextView) convertView.findViewById(R.id.button1);

                if ((Integer) getItem(position) == 3) {
                    btCurrent.setText("Number " + getItem(position) + " is sticky");
                } else {
                    btCurrent.setText("" + getItem(position));
                }
            }
            return convertView;
        }
    }

4) MainActivity

a) OnScrollListener for attaching the btn like list item on top.

    llHeader = (LinearLayout) findViewById(R.id.llHeader);//from the list_item_in_middle layout
    listView.setOnScrollListener(new AbsListView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {

        }

        @Override
        public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
            if (firstVisibleItem > 0) {        // 1st row will stick
                llHeader.setVisibility(View.VISIBLE);
            } else {
                llHeader.setVisibility(View.GONE);
            }
        }
    });

b) OnItemClickListener of listview

    listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            int a = 0;
            if(position == 0){//for clicking from date and to date.
                TextView frm = (TextView) view.findViewById(R.id.frmdate);
                frm.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        Toast.makeText(MainActivity.this,"From date clicked",Toast.LENGTH_SHORT).show();
                    }
                });
                TextView to = (TextView) view.findViewById(R.id.todate);
                to.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        Toast.makeText(MainActivity.this,"to date clicked",Toast.LENGTH_SHORT).show();
                    }
                });
            }else {
                if(position == 1) {//for clicking the btn like list element.

                    swap();
                    Toast.makeText(MainActivity.this,"Header clicked",Toast.LENGTH_SHORT).show();
                }else {
                    Toast.makeText(MainActivity.this, parent.getItemAtPosition(position).toString(), Toast.LENGTH_SHORT).show();
                }
            }
        }
    });

c) Linearlayout click function for element that gets stuck to the top

    llHeader.setOnClickListener(new View.OnClickListener() { //for clicking the elements that gets stuck to the top
        @Override
        public void onClick(View v) {
            swap();
            Toast.makeText(MainActivity.this,"Header clicked",Toast.LENGTH_SHORT).show();
        }
    });

d) swap function called from linearlayout and the list element at position 1

    public void swap(){
        ltAdapter.notifyDataSetChanged();
        new1 = new Integer[]{20, 21, 22, 23, 24, 25, 26, 27, 28};
        ltAdapter.InitializeValues(new1);
    }

NB:If any focusable view is taken in the listview, the OnItemclickListener doesnot work, read in stackoverflow itself

Finally the output:

before the second element click

after clicking

after scrolling

Upvotes: 1

Amirhossein Naghshzan
Amirhossein Naghshzan

Reputation: 1180

I think it happens in this way: when you scroll the page, linear layout gets invisible successfully but when you reache the button by doing scroll, the focus goes to listview and so it makes listview to scrolls instead of the whole page.

Do a fast scroll or scroll the page by swiping the button, not the listview and check if botton gets invisible.

Upvotes: 0

Related Questions