Android ListView handle scroll event to expand it fullscreen - android

I have a layout made of a MapView and a Listview 50-50 (image link below)
http://imgur.com/uRIS9AN
I want to handle the scroll event of the ListView, to expand it to fullscreen before it scrolls through the elements of the list.
Layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<com.google.android.gms.maps.MapView
android:id="#+id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/fortress_listview">
</ListView>
</LinearLayout>
</LinearLayout>

take a look on my code which i am using here, Use this as in xml class :
<NestedListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/fortress_listview">
Add this NestedListView Class in your app package :
public class NestedListView extends ListView implements View.OnTouchListener, AbsListView.OnScrollListener {
private int listViewTouchAction;
private static final int MAXIMUM_LIST_ITEMS_VIEWABLE = 99;
public NestedListView(Context context, AttributeSet attrs) {
super(context, attrs);
listViewTouchAction = -1;
setOnScrollListener(this);
setOnTouchListener(this);
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
if (getAdapter() != null && getAdapter().getCount() > MAXIMUM_LIST_ITEMS_VIEWABLE) {
if (listViewTouchAction == MotionEvent.ACTION_MOVE) {
scrollBy(0, -1);
}
}
}
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int newHeight = 0;
final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
if (heightMode != MeasureSpec.EXACTLY) {
ListAdapter listAdapter = getAdapter();
if (listAdapter != null && !listAdapter.isEmpty()) {
int listPosition = 0;
for (listPosition = 0; listPosition < listAdapter.getCount()
&& listPosition < MAXIMUM_LIST_ITEMS_VIEWABLE; listPosition++) {
View listItem = listAdapter.getView(listPosition, null, this);
//now it will not throw a NPE if listItem is a ViewGroup instance
if (listItem instanceof ViewGroup) {
listItem.setLayoutParams(new LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
}
listItem.measure(widthMeasureSpec, heightMeasureSpec);
newHeight += listItem.getMeasuredHeight();
}
newHeight += getDividerHeight() * listPosition;
}
if ((heightMode == MeasureSpec.AT_MOST) && (newHeight > heightSize)) {
if (newHeight > heightSize) {
newHeight = heightSize;
}
}
} else {
newHeight = getMeasuredHeight();
}
setMeasuredDimension(getMeasuredWidth(), newHeight);
}
#Override
public boolean onTouch(View v, MotionEvent event) {
if (getAdapter() != null && getAdapter().getCount() > MAXIMUM_LIST_ITEMS_VIEWABLE) {
if (listViewTouchAction == MotionEvent.ACTION_MOVE) {
scrollBy(0, 1);
}
}
return false;
}
}

Related

Dynamically add view in raw item of listview with in scrollview not working android

i have one scrollview that is compulsory need it . within scroll view i have one Listview . listview's row item have one framlayout . i am adding nativeexpreesview to fram layout when ad is ready .
now problem is if list have 10 items when ad is not loaded its works okay but when ad is loaded then it occupy some height because i am adding it to frame layout then scroll view scrolls only height of list that is before ad loaded.
but i want scroll with entire item as well ads
My acivity'slayout is below
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/svStrategy"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/app_bg"
android:scrollbars="none">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:descendantFocusability="blocksDescendants"
android:orientation="vertical">
<LinearLayout
android:id="#+id/lytBanner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/list_selector"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="5dp"
android:layout_gravity="center"
android:text="#string/str_use_spells_best"
android:textAppearance="#android:style/TextAppearance.DeviceDefault.Large"
android:textColor="#android:color/white" />
<ImageView
android:id="#+id/ivBanner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:adjustViewBounds="true" />
</LinearLayout>
<com.example.SummonersWar.classes.NestedListView
android:id="#+id/lvStrategy"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:cacheColorHint="#00000000"
android:divider="#android:color/transparent"
android:dividerHeight="10dp"
android:fadingEdge="none"
android:focusable="false"
android:scrollbars="none" />
</LinearLayout>
</ScrollView>
Row_layout of Nestedlistview
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="#+id/lytStrategyRow"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/list_selector"
android:orientation="horizontal"
android:weightSum="2">
<ImageView
android:id="#+id/ivStrategyIcon"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1.4"
android:scaleType="fitXY" />
<TextView
android:id="#+id/tvStrategyTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_margin="5dp"
android:layout_weight="0.6"
android:ellipsize="end"
android:maxLines="4"
android:minLines="4"
android:textAppearance="#android:style/TextAppearance.DeviceDefault.Medium"
android:textColor="#android:color/white" />
</LinearLayout>
<LinearLayout
android:id="#+id/rlads"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/lytStrategyRow"
android:orientation="vertical"
android:visibility="gone">
<View
android:layout_width="match_parent"
android:layout_height="10dp"
android:background="#android:color/transparent" />
<FrameLayout
android:id="#+id/fr_adview"
android:layout_width="match_parent"
android:layout_height="wrap_content"></FrameLayout>
</LinearLayout>
</RelativeLayout>
I am programmatically adding Nativeexpressview to framlayout when ads is loaded.
My nestedlistview below
public class NestedListView extends ListView implements OnScrollListener // OnTouchListener
{
private int listViewTouchAction;
private static final int MAXIMUM_LIST_ITEMS_VIEWABLE = 100;
public NestedListView(Context context, AttributeSet attrs) {
super(context, attrs);
listViewTouchAction = -1;
setOnScrollListener(this);
// setOnTouchListener(this);
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
if (getAdapter() != null
&& getAdapter().getCount() > MAXIMUM_LIST_ITEMS_VIEWABLE) {
if (listViewTouchAction == MotionEvent.ACTION_MOVE) {
scrollBy(0, -1);
}
}
}
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int newHeight = 0;
final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
if (heightMode != MeasureSpec.EXACTLY) {
ListAdapter listAdapter = getAdapter();
if (listAdapter != null && !listAdapter.isEmpty()) {
int listPosition = 0;
for (listPosition = 0; listPosition < listAdapter.getCount()
&& listPosition < MAXIMUM_LIST_ITEMS_VIEWABLE; listPosition++) {
View listItem = listAdapter.getView(listPosition, null,
this);
// now it will not throw a NPE if listItem is a ViewGroup
// instance
if (listItem instanceof ViewGroup) {
listItem.setLayoutParams(new LayoutParams(
LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT));
}
listItem.measure(widthMeasureSpec, heightMeasureSpec);
newHeight += listItem.getMeasuredHeight();
}
newHeight += getDividerHeight() * listPosition;
newHeight += getPaddingBottom() + getPaddingTop();
}
if ((heightMode == MeasureSpec.AT_MOST) && (newHeight > heightSize)) {
if (newHeight > heightSize) {
newHeight = heightSize;
}
}
} else {
newHeight = getMeasuredHeight();
}
setMeasuredDimension(getMeasuredWidth(), newHeight);
}}
so my problem is scrollview scrolls only height of list when ads are loaded .so please help me what should i do now for scrolling entire list with ads?
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.ViewParent;
import android.widget.ScrollView;
public class VerticalScrollview extends ScrollView {
public VerticalScrollview(Context context) {
super(context);
}
public VerticalScrollview(Context context, AttributeSet attrs) {
super(context, attrs);
}
public VerticalScrollview(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
final int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
super.onTouchEvent(ev);
break;
case MotionEvent.ACTION_MOVE:
return false; // redirect MotionEvents to ourself
case MotionEvent.ACTION_CANCEL:
super.onTouchEvent(ev);
break;
case MotionEvent.ACTION_UP:
return false;
default:
break;
}
return false;
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
super.onTouchEvent(ev);
return true;
}
}

how to set Listview height dynamically having multiline textview inside item in android

I am using code given at many places-
public void setListHeight(ListView list, CustomListPairingAdapter adapter, int screenRatio)
{
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int _hieght = size.y;
if (adapter != null) {
int totalHeight = 0;
for (int i = 0; i < adapter.getCount(); i++) {
View listItem = adapter.getView(i, null, list);
listItem.measure(0, 0);
totalHeight += listItem.getMeasuredHeight();
}
ViewGroup.LayoutParams params = list.getLayoutParams();
totalHeight=totalHeight + (list.getDividerHeight() * (adapter.getCount()));
int desiredHeight=_hieght*screenRatio/100;
if(desiredHeight<=totalHeight)
params.height = desiredHeight;
else
params.height = totalHeight;
list.setLayoutParams(params);
list.requestLayout();
}
}
But it does not work when list item has multiline textview. How to resolve this problem. any ideas ?
Thanks already
int myHeight=20;
LayoutParams par=new RelativeLayout.LayoutParams
(LayoutParams.MATCH_PARENT, myHeight);
//Replace RelativeLayout with the parent layout of list view
ListView t=(ListView)findViewById(R.id.mylist);
t.setLayoutParams(par);
You can try with this custom listview to avoid listhieght having multiline textview problem
<namespace.epicurio.NestedListView
android:id="#+id/listComments"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
android:divider="#000000"
android:dividerHeight="1.0sp">
</namespace.epicurio.NestedListView>
public class NestedListView extends ListView implements OnTouchListener, OnScrollListener {
private int listViewTouchAction;
private static final int MAXIMUM_LIST_ITEMS_VIEWABLE = 99;
public NestedListView(Context context, AttributeSet attrs) {
super(context, attrs);
listViewTouchAction = -1;
setOnScrollListener(this);
setOnTouchListener(this);
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
if (getAdapter() != null && getAdapter().getCount() > MAXIMUM_LIST_ITEMS_VIEWABLE) {
if (listViewTouchAction == MotionEvent.ACTION_MOVE) {
scrollBy(0, -1);
}
}
}
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int newHeight = 0;
final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
if (heightMode != MeasureSpec.EXACTLY) {
ListAdapter listAdapter = getAdapter();
if (listAdapter != null && !listAdapter.isEmpty()) {
int listPosition = 0;
for (listPosition = 0; listPosition < listAdapter.getCount()
&& listPosition < MAXIMUM_LIST_ITEMS_VIEWABLE; listPosition++) {
View listItem = listAdapter.getView(listPosition, null, this);
//now it will not throw a NPE if listItem is a ViewGroup instance
if (listItem instanceof ViewGroup) {
listItem.setLayoutParams(new LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
}
listItem.measure(widthMeasureSpec, heightMeasureSpec);
newHeight += listItem.getMeasuredHeight();
}
newHeight += getDividerHeight() * listPosition;
}
if ((heightMode == MeasureSpec.AT_MOST) && (newHeight > heightSize)) {
if (newHeight > heightSize) {
newHeight = heightSize;
}
}
} else {
newHeight = getMeasuredHeight();
}
setMeasuredDimension(getMeasuredWidth(), newHeight);
}
#Override
public boolean onTouch(View v, MotionEvent event) {
if (getAdapter() != null && getAdapter().getCount() > MAXIMUM_LIST_ITEMS_VIEWABLE) {
if (listViewTouchAction == MotionEvent.ACTION_MOVE) {
scrollBy(0, 1);
}
}
return false;
}
}

Android add a ListView inside of ScrollView

I know it is a very bad practice that "don't put a ListView into a ScrollView" since ListView has it's own scroll. However, I have couple of other items (buttons and textviews) additional to ListView. For those, I definitely need to use a ScrollView. I found some solution (http://nex-otaku-en.blogspot.com/2010/12/android-put-listview-in-scrollview.html) to prevent collapsing the Listview. But, as i said, I need a ScrollView that encapsulates all items on my XML form. I have added my xml code, Please guide how to achieve this.
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ListView
android:id="#+id/listView1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:choiceMode="singleChoice">
</ListView>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<Button
android:id="#+id/button1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Button1" />
</LinearLayout>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/longtext" />
</LinearLayout>
</ScrollView>
ListView by itself is scrollable. Do not put ListView inside a scroll view.
Move your ListView outside scorllview. You can also add a header and footer to the listview.
Check the video by google
https://www.youtube.com/watch?v=wDBM6wVEO70
I found this solution from another post & found it working.
While all other solutions work when the list-items are of same height, this solution still provides perfect result even if the list-items are of variable height.
Use this customized class in the xml & you are good to go.
public class NestedListView extends ListView implements OnTouchListener, OnScrollListener {
private int listViewTouchAction;
private static final int MAXIMUM_LIST_ITEMS_VIEWABLE = 99;
public NestedListView(Context context, AttributeSet attrs) {
super(context, attrs);
listViewTouchAction = -1;
setOnScrollListener(this);
setOnTouchListener(this);
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
if (getAdapter() != null && getAdapter().getCount() > MAXIMUM_LIST_ITEMS_VIEWABLE) {
if (listViewTouchAction == MotionEvent.ACTION_MOVE) {
scrollBy(0, -1);
}
}
}
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int newHeight = 0;
final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
if (heightMode != MeasureSpec.EXACTLY) {
ListAdapter listAdapter = getAdapter();
if (listAdapter != null && !listAdapter.isEmpty()) {
int listPosition = 0;
for (listPosition = 0; listPosition < listAdapter.getCount()
&& listPosition < MAXIMUM_LIST_ITEMS_VIEWABLE; listPosition++) {
View listItem = listAdapter.getView(listPosition, null, this);
//now it will not throw a NPE if listItem is a ViewGroup instance
if (listItem instanceof ViewGroup) {
listItem.setLayoutParams(new LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
}
listItem.measure(widthMeasureSpec, heightMeasureSpec);
newHeight += listItem.getMeasuredHeight();
}
newHeight += getDividerHeight() * listPosition;
}
if ((heightMode == MeasureSpec.AT_MOST) && (newHeight > heightSize)) {
if (newHeight > heightSize) {
newHeight = heightSize;
}
}
} else {
newHeight = getMeasuredHeight();
}
setMeasuredDimension(getMeasuredWidth(), newHeight);
}
#Override
public boolean onTouch(View v, MotionEvent event) {
if (getAdapter() != null && getAdapter().getCount() > MAXIMUM_LIST_ITEMS_VIEWABLE) {
if (listViewTouchAction == MotionEvent.ACTION_MOVE) {
scrollBy(0, 1);
}
}
return false;
}
}
You can use the Expandable Listview for using the listview inside the scrollview, it will expends the listview as long the content length, create a Custom class with name ExpandableHeightListView
package com.knight.utils;
import android.content.Context;
import android.util.AttributeSet;
import android.view.ViewGroup;
import android.widget.ListView;
public class ExpandableHeightListView extends ListView
{
boolean expanded = false;
public ExpandableHeightListView(Context context)
{
super(context);
}
public ExpandableHeightListView(Context context, AttributeSet attrs)
{
super(context, attrs);
}
public ExpandableHeightListView(Context context, AttributeSet attrs,int defStyle)
{
super(context, attrs, defStyle);
}
public boolean isExpanded()
{
return expanded;
}
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
// HACK! TAKE THAT ANDROID!
if (isExpanded())
{
// Calculate entire height by providing a very large height hint.
// But do not use the highest 2 bits of this integer; those are
// reserved for the MeasureSpec mode.
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
ViewGroup.LayoutParams params = getLayoutParams();
params.height = getMeasuredHeight();
}
else
{
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
public void setExpanded(boolean expanded)
{
this.expanded = expanded;
}
}
After that Programmatically add this line into your code, it will expend the listview in side the scrollview,
Listview listview=(Listview)findviewbyid(R.id.listview1);
((ExpandableHeightListView)listview).setExpandable(true);

Handle onScrollChange for D-Pad and Touch for Custom HorizontalScrollView

I'm working on a HorizontalScrollview with Center lock. It is based off some code found in this stackoverflow thread:
HorizontalScrollView with imageviews as a child and while scrolling the center of the image in the screen should play animation?
The issue is that it didn't support D-Pad navigation correctly. It wouldn't scroll to the next item but jump positions. I modified the code so that it worked with D-Pad naviagtion correctly, but that made the Touch scrolling not work. Also for some reason even though the TextViews are added correctly the click listeners seem to get removed. Anyways, the main issue now is that if I add back in the code for onScrollChange event, it works correctly for Touch, but the D-Pad navigation can skip an item if it was off screen and then brought back on screen.
The following is the xml.layout being used:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/mainLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/serenity_bonsai_logo"
android:orientation="vertical"
tools:context=".MainActivity" >
<LinearLayout
android:id="#+id/main_menu_row1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:orientation="horizontal" >
<DigitalClock
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#50000000"
android:textColor="#F0F0F0"
android:textSize="20sp" />
</LinearLayout>
<us.nineworlds.serenity.widgets.CenterLockHorizontalScrollview
android:id="#+id/mainGalleryMenu"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#50000000"
android:layout_centerInParent="true"
android:clickable="true"
android:scrollbars="none" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="150dp"
android:layout_gravity="center_vertical"
android:background="#android:color/transparent"
android:orientation="horizontal"
android:clickable="true" >
</LinearLayout>
</us.nineworlds.serenity.widgets.CenterLockHorizontalScrollview>
</RelativeLayout>
I know the issue is around the onScrollChange method and how it is calculating what should be the new center view, but not sure how to get D-Pad and touch scrolling playing nicely together. Here is the relevant code for the CenterLockHorizontalScrollView class.
public class CenterLockHorizontalScrollview extends HorizontalScrollView {
private ListAdapter mAdapter;
private int mCenterViewPosition = -1;
private MenuDataSetObserver menuDataObserver;
private OnItemSelectedListener selectedItemListener;
private boolean keypadScrollEvent = false;
public CenterLockHorizontalScrollview(Context context, AttributeSet attrs) {
super(context, attrs);
this.setHorizontalFadingEdgeEnabled(true);
this.setHorizontalScrollBarEnabled(false);
this.setFadingEdgeLength(5);
this.setSmoothScrollingEnabled(true);
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
if (getChildCount() == 0) {
return;
}
initCenterView();
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (getChildCount() == 0)
return;
ViewGroup parent = (ViewGroup) getChildAt(0);
if (parent.getChildCount() == 0)
return;
View FirstChild = parent.getChildAt(0);
int LeftPadding = (getWidth() / 2)
- (FirstChild.getMeasuredWidth() / 2);
View LastChild = parent.getChildAt(getChildCount() - 1);
int RightPadding = (getWidth() / 2)
- (LastChild.getMeasuredWidth() / 2);
if (parent.getPaddingLeft() != LeftPadding
&& parent.getPaddingRight() != RightPadding) {
parent.setPadding(LeftPadding, parent.getPaddingTop(),
RightPadding, parent.getPaddingBottom());
requestLayout();
}
}
/* (non-Javadoc)
* #see android.view.View#onKeyDown(int, android.view.KeyEvent)
*/
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
int totalItems = 0;
if (mAdapter.getCount() > 0) {
totalItems = mAdapter.getCount();
}
int currentPosition = mCenterViewPosition;
if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
if (currentPosition > 0) {
setSelectedIndex(currentPosition - 1);
} else {
setSelectedIndex(totalItems - 1);
}
keypadScrollEvent = true;
scrollToSelectedIndex();
keypadScrollEvent = false;
return true;
}
if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
if (currentPosition < totalItems - 1) {
setSelectedIndex(currentPosition + 1);
} else {
setSelectedIndex(0);
}
keypadScrollEvent = true;
scrollToSelectedIndex();
keypadScrollEvent = false;
return true;
}
if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER ||
keyCode == KeyEvent.KEYCODE_ENTER) {
ViewGroup parent = (ViewGroup) getChildAt(0);
View view = parent.getChildAt(mCenterViewPosition);
view.setOnClickListener(new GalleryOnClickListener(view.getContext()));
view.performClick();
return true;
}
return super.onKeyDown(keyCode, event);
}
private int getCenterPositionFromView() {
int scrollingCenterView = getScrollingCenterView();
if (mCenterViewPosition != scrollingCenterView) {
ViewGroup parent = (ViewGroup) getChildAt(0);
View view = parent.getChildAt(scrollingCenterView);
selectedItemListener.onItemSelected(view, scrollingCenterView, scrollingCenterView);
mCenterViewPosition = scrollingCenterView;
}
return scrollingCenterView;
}
private int getScrollingCenterView() {
if(getChildCount() == 0)
return -1;
int centerView= 0;
int centerX = getScrollX() + (getWidth() / 2);
ViewGroup parent = (ViewGroup) getChildAt(0);
if(parent.getChildCount() == 0)
return -1;
View child = parent.getChildAt(0);
while(child != null && child.getRight() <= centerX && centerView < parent.getChildCount())
{
centerView++;
child = parent.getChildAt(centerView);
}
if(centerView >= parent.getChildCount()) {
centerView = parent.getChildCount() - 1;
}
return centerView;
}
public int getCenterViewPosition() {
return mCenterViewPosition;
}
public ListAdapter getAdapter() {
return mAdapter;
}
public void setAdapter(ListAdapter mAdapter) {
this.mAdapter = mAdapter;
if (menuDataObserver != null) {
mAdapter.unregisterDataSetObserver(menuDataObserver);
}
mAdapter.registerDataSetObserver(new MenuDataSetObserver());
}
private void fillViewWithAdapter() {
if (getChildCount() == 0 || mAdapter == null)
return;
ViewGroup parent = (ViewGroup) getChildAt(0);
parent.removeAllViews();
for (int i = 0; i < mAdapter.getCount(); i++) {
parent.addView(mAdapter.getView(i, null, parent));
}
setSelectedIndex(0);
}
#Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
if (keypadScrollEvent == false) {
getCenterPositionFromView();
}
initCenterView();
}
private void initCenterView() {
Log.i(getClass().getName(), "initCenterView");
if (getChildCount() == 0)
return;
ViewGroup parent = (ViewGroup) getChildAt(0);
if (parent.getChildCount() == 0)
return;
int centerView = getCenterViewPosition();
if (centerView == -1) {
mCenterViewPosition = 0;
centerView = 0;
}
if (centerView != -1 && centerView != mCenterViewPosition
&& parent.getChildAt(0).getLeft() >= 0) {
scrollToSelectedIndex();
}
if (centerView < 0 || centerView > parent.getChildCount())
return;
for (int i = 0; i <= parent.getChildCount(); i++) {
if (! (parent.getChildAt(i) instanceof TextView)) {
continue;
}
if (i == centerView) {
// Start Animation
//setSelectedIndex(i);
//scrollToSelectedIndex();
return;
} else {
// Remove Animation for other Views
}
}
}
public int getSelectedIndex() {
return getCenterViewPosition();
}
public void setSelectedIndex(int index) {
Log.i(getClass().getName(), "setSelectedIndex");
if (getChildCount() == 0)
return;
ViewGroup parent = (ViewGroup) getChildAt(0);
if (index < 0 || index > parent.getChildCount()) {
throw new ArrayIndexOutOfBoundsException(index);
}
mCenterViewPosition = index;
//onSelectedItemChanged.onSelectedChanged(this, mCenterViewPosition);
selectedItemListener.onItemSelected(parent.getChildAt(index), index, 0);
requestLayout();
}
protected void scrollToSelectedIndex() {
ViewGroup parent = (ViewGroup) getChildAt(0);
View child = parent.getChildAt(mCenterViewPosition);
if (child == null) {
return;
}
int offsetX = ((child.getLeft() + child.getRight()) / 2) - (this.getWidth() / 2);
smoothScrollTo(offsetX, 0);
}
public class MenuDataSetObserver extends DataSetObserver {
#Override
public void onChanged() {
fillViewWithAdapter();
}
}
public OnItemSelectedListener getOnItemSelectedListener() {
return selectedItemListener;
}
public void setOnItemSelectedListener(OnItemSelectedListener selectedItemListener) {
this.selectedItemListener = selectedItemListener;
}
}
With out the checks for center in onScrollChange D-Pad navigation works correctly but touch scrolling doesn't.
My recommendation would be to not override the onKeyDown event and instead attach an onClickListener. Have you considered using a ViewPager instead where you override the ViewPager width to account for the items contained within?

ListView inside a ScrollView [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Listview inside ScrollView is not scrolling on Android
I have a ListView inside a ScrollView and the problem is that the ScrollView is scrolling but ListView doesn't scroll. I think this is happening because of that ScrollView. Does anyone have a solution for this issue?
ListViews have built-in scrolling capabilities. Encapsulate it in any other layout like a LinearLayout or RelativeLayout.
I required having a listview inside a scrollview in order to prevent the entire screen from being extremely long. This allows you have to set the number of items displayed on the list, while the rest will be scrolled.
I use the following class in my app and so far it seems to work terrific.
public class NestedListView extends ListView implements OnScrollListener,
OnTouchListener {
private int listViewTouchAction;
private static final int MAXIMUM_LIST_ITEMS_VIEWABLE = 4;
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
if (getAdapter() != null && getAdapter().getCount() > MAXIMUM_LIST_ITEMS_VIEWABLE) {
if (listViewTouchAction == MotionEvent.ACTION_MOVE) {
scrollBy(0, -1);
}
}
}
public NestedListView(Context context, AttributeSet attrs) {
super(context, attrs);
listViewTouchAction = -1;
setOnScrollListener(this);
setOnTouchListener(this);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int newHeight = 0;
final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
if (heightMode != MeasureSpec.EXACTLY) {
ListAdapter listAdapter = getAdapter();
if (listAdapter != null && !listAdapter.isEmpty()) {
int listPosition = 0;
for (listPosition = 0; listPosition < listAdapter.getCount()
&& listPosition < MAXIMUM_LIST_ITEMS_VIEWABLE; listPosition++) {
View listItem = listAdapter.getView(listPosition, null,
this);
listItem.measure(widthMeasureSpec, heightMeasureSpec);
newHeight += listItem.getMeasuredHeight();
}
newHeight += getDividerHeight() * listPosition;
}
if ((heightMode == MeasureSpec.AT_MOST) && (newHeight > heightSize)) {
if (newHeight > heightSize) {
newHeight = heightSize;
}
}
} else {
newHeight = getMeasuredHeight();
}
setMeasuredDimension(getMeasuredWidth(), newHeight);
}
#Override
public boolean onTouch(View v, MotionEvent event) {
listViewTouchAction = event.getAction();
if (getAdapter() != null && getAdapter().getCount() > MAXIMUM_LIST_ITEMS_VIEWABLE) {
if (listViewTouchAction == MotionEvent.ACTION_MOVE) {
scrollBy(0, 1);
}
}
return false;
}
}
Use the following method and enjoy!
private void setListViewScrollable(final ListView list) {
list.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
listViewTouchAction = event.getAction();
if (listViewTouchAction == MotionEvent.ACTION_MOVE)
{
list.scrollBy(0, 1);
}
return false;
}
});
list.setOnScrollListener(new OnScrollListener() {
#Override
public void onScrollStateChanged(AbsListView view,
int scrollState) {
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
if (listViewTouchAction == MotionEvent.ACTION_MOVE)
{
list.scrollBy(0, -1);
}
}
});
}
listViewTouchAction is a global integer value.
If you can replace the line
list.scrollBy(0, 1);
with something else please share it with us.
You shouldn't nest a ListView inside a ScrollView.
If you're trying to scroll some other views along with the ListView, you might check out this answer.

Categories

Resources