Making A Middle Element To Get Stuck In The Header (scrollview/listview)
Solution 1:
I have used(or rather, tried to use) the StickyListHeaders
library in the past. After having some issues with it, I came up with the following. It is not much different from what other posters have suggested.
The main layout file activity_layout.xml
consists of a ListView
and a LinearLayout
which is invisible by default. Using the OnScrollListener's onScroll() method, the LinearLayout's
visibility is toggled. You don't need to inflate another layout or add views dynamically to your layout's parent. This is what the onScroll
method looks like:
publicvoidonScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount){
if (firstVisibleItem > 3) { // 5th row will stick
llHeader.setVisibility(View.VISIBLE);
} else {
llHeader.setVisibility(View.GONE);
}
}
Simply, toggle the visibility to get the desired effect. You can take a look at the following code. Its a working example of what you can expect. The activity contains a ListView
with a strictly barebone extension of BaseAdapter
. The ListView
is populated with numbered Buttons(one on each row, starting at 0, and going up to 19).
publicclassStickyHeaderextendsActivity {
LinearLayout llHeader;
ListView lv;
SHAdapter shAdapter;
@OverrideprotectedvoidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_layout);
lv = (ListView) findViewById(R.id.listView1);
llHeader = (LinearLayout) findViewById(R.id.llHeader);
shAdapter = newSHAdapter();
lv.setAdapter(shAdapter);
lv.setOnScrollListener(newOnScrollListener() {
@OverridepublicvoidonScrollStateChanged(AbsListView view, int scrollState) {}
@OverridepublicvoidonScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if (firstVisibleItem > 3) {
llHeader.setVisibility(View.VISIBLE);
} else {
llHeader.setVisibility(View.GONE);
}
}
});
}
publicclassSHAdapterextendsBaseAdapter {
Button btCurrent;
int[] arr = newint[] {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
@OverridepublicintgetCount() {
return20;
}
@Overridepublic Object getItem(int arg0) {
return arr[arg0];
}
@OverridepubliclonggetItemId(int position) {
return0;
}
@Overridepublic View getView(int position, View convertView, ViewGroup parent) {
convertView = getLayoutInflater().inflate(R.layout.list_item_layout, null);
btCurrent = (Button) convertView.findViewById(R.id.button1);
if ((Integer)getItem(position) == 4) {
btCurrent.setText("Number " + getItem(position) + " is sticky");
} else {
btCurrent.setText("" + getItem(position));
}
return convertView;
}
}
}
activity_layout.xml
<RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="fill_parent"android:layout_height="fill_parent" ><ListViewandroid:id="@+id/listView1"android:layout_width="match_parent"android:layout_height="wrap_content" ></ListView><!-- This LinearLayout's visibility is toggled --><!-- Improvement suggested by user 'ar34z'
(see comment section below) --><includelayout="@layout/list_item_layout" /></RelativeLayout>
list_item_layout
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/llHeader"android:layout_width="match_parent"android:layout_height="50dp"android:background="@color/white"android:orientation="vertical" ><Buttonandroid:id="@+id/button1"android:layout_gravity="center"android:layout_width="match_parent"android:layout_height="wrap_content" /></LinearLayout>
Solution 2:
This is the simplest code to illustrate the main idea:
listView.setOnScrollListener(newOnScrollListener() {
ViewGroupmainView= (ViewGroup) findViewById(R.id.main);
ViewpinnedView=null;
@OverridepublicvoidonScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if (firstVisibleItem < PINNED_ITEM) {
mainView.removeView(pinnedView);
pinnedView = null;
} elseif (pinnedView == null) {
pinnedView = adapter.getView(PINNED_ITEM, null, view);
pinnedView.setBackgroundColor(0xFF000000);
mainView.addView(pinnedView);
}
}
@OverridepublicvoidonScrollStateChanged(AbsListView view, int scrollState) {}
});
I have a FrameLayout
which contains nothing but my ListView
:
<FrameLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:id="@+id/main"
><ListViewandroid:layout_width="match_parent"android:layout_height="match_parent"
/></FrameLayout>
PINNED_ITEM
is the position of your item (for example, PINNED_ITEM = 2
). This layout acts as an overlay for the list. The ScrollListener
tracks the current visible items and if it detects that an item should be pinned, it adds it to the layout and removes it otherwise.
The line pinnedView.setBackgroundColor(0xFF000000);
is needed to set an opaque background for the item. The item will be transparent if you don't do this. You can tweak the background according to your needs (for example, you can use a background from your current theme attribute).
Solution 3:
In order to accomplish this, i'll put the listView in a relativeLayout and add a listener on the scroll. Then in it, when the firstVisibleItem change, i'll duplicate the itemView you need and display it over your listView.
Here is a short sample of what I think. The only things is that the duplicate view has to be opaque.
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.RelativeLayout;
publicclassMainActivityextendsActivity {
@OverrideprotectedvoidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/*Create listView inside a relativelayout*/finalRelativeLayoutrl=newRelativeLayout(this);
finalListViewlv=newListView(this);
rl.addView(lv);
/* Set it as a content view*/
setContentView(rl);
/*populate it*/
String[] items = { "Cupcake",
"Donut",
"Eclair",
"Froyo",
"Gingerbread",
"Honeycomb",
"Ice Cream Sandwich",
"Jelly Bean"};
intsize=10;
String[] arrayItems = newString[items.length*size];
for(inti=0; i < arrayItems.length; i++)
arrayItems[i] = items[i%items.length] + " " + i;
/* Need to use a non transparent view*/final ArrayAdapter<String> adapter = newArrayAdapter<String>(this,
R.layout.simple_list_item_1_opaque, arrayItems);
lv.setAdapter(adapter);
/* Choose the item to stick*/finalintitemToStick=3;
/* Create things needed for duplication */final RelativeLayout.LayoutParamsparams=newRelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.ALIGN_PARENT_TOP, 1);
final RelativeLayout.LayoutParamsselectorParams=newRelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, lv.getDividerHeight());
lv.setOnScrollListener(newOnScrollListener() {
@OverridepublicvoidonScrollStateChanged(AbsListView view, int scrollState) {
// TODO Auto-generated method stub
}
@OverridepublicvoidonScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
if(itemToStick <= firstVisibleItem && rl.getChildCount() == 1)
{
/* Put view in a linearlayout in order to be able to add the sepline */LinearLayoutll=newLinearLayout(view.getContext());
ll.setOrientation(LinearLayout.VERTICAL);
ll.addView(adapter.getView(itemToStick, null, null),params);
/* Create Divider */Viewselector=newLinearLayout(view.getContext());
selector.setBackground(lv.getDivider());
/* add views*/
ll.addView(selector,selectorParams);
rl.addView(ll,params);
}
/* Remove view when scrolling up to it */elseif(itemToStick > firstVisibleItem)
{
if(rl.getChildCount() > 1)
rl.removeViewAt(1);
}
}
});
}
}
And simple_list_item_1_opaque:
<?xml version="1.0" encoding="utf-8"?><TextViewxmlns:android="http://schemas.android.com/apk/res/android"android:id="@android:id/text1"android:layout_width="match_parent"android:layout_height="wrap_content"android:textAppearance="?android:attr/textAppearanceListItemSmall"android:gravity="center_vertical"android:paddingStart="?android:attr/listPreferredItemPaddingStart"android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"android:minHeight="?android:attr/listPreferredItemHeightSmall"android:background="#FFFFFF"
/>
Post a Comment for "Making A Middle Element To Get Stuck In The Header (scrollview/listview)"