I am trying to implement Collapsing Toolbar By Using ConstraintLayout. After Trying a lot, I couldn't able to get the desire effects.I have follow this link in youtube (https://www.youtube.com/watch?v=8lAXJ5NFXTM at the 21 min). My Source code is:-
activity.main.xml:-
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".activities.MainActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="#dimen/app_bar_height"
android:theme="#style/AppTheme.AppBarOverlay"
android:fitsSystemWindows="false">
<com.example.study.helpers.NoAnimCollapsibleConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:minHeight="40dp"
app:layout_scrollFlags="scroll|enterAlways|snap|exitUntilCollapsed"/>
</android.support.design.widget.AppBarLayout>
<include layout="#layout/content_main" />
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="#dimen/fab_margin"
android:src="#drawable/ic_border_color_white_24dp"/>
</android.support.design.widget.CoordinatorLayout>
content_main.xml:-
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context=".activities.MainActivity"
tools:showIn="#layout/activity_main">
<TextView
android:id="#+id/textView3"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="#string/some_long_text"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
NoAnimCollapsibleConstraintLayout.java:-
import android.content.Context;
import android.support.constraint.ConstraintLayout;
import android.support.constraint.ConstraintSet;
import android.support.design.widget.AppBarLayout;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.Toast;
import com.example.study.R;
public class NoAnimCollapsibleConstraintLayout extends ConstraintLayout implements AppBarLayout.OnOffsetChangedListener {
private static final String TAG = NoAnimCollapsibleConstraintLayout.class.getSimpleName();
private float mTransitionThreshold = 0.35f;
private int mLastPosition = 0;
private boolean mToolbarOpen = true;
private ConstraintSet mOpenToolbarSet = new ConstraintSet();
private ConstraintSet mCloseToolbarSet = new ConstraintSet();
public NoAnimCollapsibleConstraintLayout(Context context) { super(context, null); }
public NoAnimCollapsibleConstraintLayout(Context context, AttributeSet attrs) { super(context, attrs, 0); }
public NoAnimCollapsibleConstraintLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); }
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (getParent() instanceof AppBarLayout){
Log.d(TAG, "Instance AppBarLayout");
AppBarLayout appBarLayout = (AppBarLayout)getParent();
appBarLayout.addOnOffsetChangedListener(this);
mOpenToolbarSet.clone(getContext(), R.layout.open);
mCloseToolbarSet.clone(getContext(), R.layout.close);
}else {
Log.d(TAG, "Instance if Not Parent");
}
}
#Override
public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
Log.d(TAG, "onOffsetChanged");
if (mLastPosition == verticalOffset){
return;
}
mLastPosition = verticalOffset;
Float progress = ( Math.abs(verticalOffset / (float) (appBarLayout.getHeight()))) ;
AppBarLayout.LayoutParams params = (AppBarLayout.LayoutParams) getLayoutParams();
params.topMargin = -verticalOffset;
setLayoutParams(params);
if ( mToolbarOpen && progress > mTransitionThreshold) {
Log.d(TAG, "Apply close.xml");
mCloseToolbarSet.applyTo(this);
mToolbarOpen = false;
}else if ( !mToolbarOpen && progress < mTransitionThreshold){
Log.d(TAG, "Apply open.xml");
mOpenToolbarSet.applyTo(this);
mToolbarOpen = true;
}
}
}
open.xml:-
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/open"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/imageView2"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:contentDescription="#string/app_name"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="#drawable/study" />
</android.support.constraint.ConstraintLayout>
close.xml:-
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/close"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/textView4"
android:layout_width="0dp"
android:layout_height="30dp"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="#string/app_name"
android:textColor="#android:color/white"
android:textSize="#dimen/text_size_16"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
After Applying this code open.xml and close.xml design not shown when I am trying to collapse Toolbar. This is the screenshot which I am getting in output:-
Without Collapse (open.xml design missing) :-
https://www.dropbox.com/s/c0rh126rinmopd4/Screen_Shot1.png?dl=0)
With Collpase (close.xml design missing):-
https://www.dropbox.com/s/cdlbg84lmht3gv0/Screen_Shot2.png?dl=0
I've been trying to do the same thing after watching the video.
Add the id "constraint" to both root ConstraintLayout
You did inflate your view in NoAnimCollapsibleConstraintLayout, so inflate and then find constraint view
import android.content.Context;
import android.support.constraint.ConstraintLayout;
import android.support.constraint.ConstraintSet;
import android.support.design.widget.AppBarLayout;
import android.support.transition.TransitionManager;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
public class NoAnimCollapsibleConstraintLayout extends ConstraintLayout
implements AppBarLayout.OnOffsetChangedListener {
private static final String TAG = NoAnimCollapsibleConstraintLayout.class.getSimpleName();
private float mTransitionThreshold = 0.35f;
private int mLastPosition = 0;
private boolean mToolbarOpen = true;
private ConstraintSet mOpenToolbarSet = new ConstraintSet();
private ConstraintSet mCloseToolbarSet = new ConstraintSet();
private ConstraintLayout constraint;
public NoAnimCollapsibleConstraintLayout(Context context) {
this(context, null);
}
public NoAnimCollapsibleConstraintLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public NoAnimCollapsibleConstraintLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
LayoutInflater.from(getContext()).inflate(R.layout.open, this, true);
constraint = findViewById(R.id.constraint);
}
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (getParent() instanceof AppBarLayout) {
Log.d(TAG, "Instance AppBarLayout");
AppBarLayout appBarLayout = (AppBarLayout) getParent();
appBarLayout.addOnOffsetChangedListener(this);
mOpenToolbarSet.clone(constraint);
mCloseToolbarSet.clone(getContext(), R.layout.close);
} else {
Log.d(TAG, "Instance if Not Parent");
}
}
#Override
public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
Log.d(TAG, "onOffsetChanged");
if (mLastPosition == verticalOffset) {
return;
}
mLastPosition = verticalOffset;
Float progress = (Math.abs(verticalOffset / (float) (appBarLayout.getHeight())));
AppBarLayout.LayoutParams params = (AppBarLayout.LayoutParams) getLayoutParams();
params.topMargin = -verticalOffset;
setLayoutParams(params);
TransitionManager.beginDelayedTransition(constraint);
if (mToolbarOpen && progress > mTransitionThreshold) {
Log.d(TAG, "Apply close.xml");
mCloseToolbarSet.applyTo(constraint);
mToolbarOpen = false;
} else if (!mToolbarOpen && progress < mTransitionThreshold) {
Log.d(TAG, "Apply open.xml");
mOpenToolbarSet.applyTo(constraint);
mToolbarOpen = true;
}
}
}
This has an animation in and it seems to work for me. try and make sure the same view is in both, even if it is just to move it or visibility gone
EDIT: https://github.com/BigFishStudios/ConstraintToolbar here is a code example of this working
Hope this helps :D
So, situation is this:
I need to implement AppBar scroll behaviour in my main activity, but, I already have CoordinatorLayout and AppBarLayout in my fragment with the same scroll behaviour.
Here is the xml from both of the layouts:
activity_main:
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#EBEDEC">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/toolbar_open_nav"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:src="#drawable/filter_icon" />
<RelativeLayout
android:id="#+id/main_activity_images_relative"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/toolbar_fencity_image"
android:layout_width="200dp"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:layout_margin="#dimen/layout_padding"
android:src="#drawable/toolbarimg"
android:visibility="gone" />
</RelativeLayout>
</RelativeLayout>
</android.support.v7.widget.Toolbar>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<FrameLayout
android:id="#+id/main_content"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#android:color/transparent" />
<com.bitage.carlo.fencity.ui.view.BottomMenuView
android:id="#+id/bottom_menu"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" />
</LinearLayout>
</RelativeLayout>
and a fragment xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="?attr/actionBarSize"
android:orientation="vertical">
<android.support.design.widget.AppBarLayout
android:id="#+id/novita_app_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RelativeLayout
android:id="#+id/novita_search_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/background"
app:layout_scrollFlags="scroll|enterAlways|snap">
<EditText
android:id="#+id/search_edit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="#dimen/layout_padding"
android:background="#null"
android:hint="#string/search"
android:imeOptions="actionDone"
android:paddingEnd="#dimen/layout_padding"
android:paddingLeft="#dimen/padding_start"
android:paddingRight="#dimen/layout_padding"
android:paddingStart="#dimen/padding_start"
android:singleLine="true" />
<ImageView
android:id="#+id/search_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="#dimen/layout_padding"
android:layout_marginStart="#dimen/layout_padding"
android:src="#drawable/ic_search" />
</RelativeLayout>
</android.support.design.widget.AppBarLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<android.support.v7.widget.RecyclerView
android:id="#+id/places_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="#android:color/transparent"
android:src="#drawable/nav_shadow" />
</RelativeLayout>
</android.support.design.widget.CoordinatorLayout>
Now, I need this to stay the same if possible, just somehow to add the scroll behavior app:layout_scrollFlags="scroll|enterAlways|snap" on toolbar only in this fragment, while search from the fragment still has the same behaviour.
How can I achieve this?
So, you can do next:
in your Fragment class, you have recyclerview. Now, what you want to do is put the recyclerView.addOnScrollListener(new YourScrollListenerClass(context, toolbar, coordinatorLayout));
Coordinator layout is the one of the fragment, please bear that in mind.
Now, create a new class YourScrollListenerClass:
public class YourScrollListenerClass extends RecyclerView.OnScrollListener {
private Context mContext;
private Toolbar mToolbar;
private CoordinatorLayout mCoordinatorLayout;
private int mToolbarHeight;
private int mCoordinatorLayoutTopMargin;
public YourScrollListenerClass(Context context, #Nullable Toolbar toolbar, #Nullable final CoordinatorLayout mCoordinatorLayout) {
this.mContext = context;
mToolbar = toolbar;
this.mCoordinatorLayout = mCoordinatorLayout;
if (mToolbar != null && mCoordinatorLayout != null) {
mToolbar.post(new Runnable() {
#Override
public void run() {
mToolbarHeight = mToolbar.getHeight();
}
});
mCoordinatorLayout.post(new Runnable() {
#Override
public void run() {
mCoordinatorLayoutTopMargin = ((FrameLayout.LayoutParams) mCoordinatorLayout.getLayoutParams()).topMargin;
}
});
}
}
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
if (recyclerView != null) {
if (mToolbar != null) {
float offset = mToolbar.getTranslationY() - dy;
if (offset <= 0 && offset >= -(mToolbar.getHeight())) {
mToolbar.setTranslationY(mToolbar.getTranslationY() - dy);
FrameLayout.LayoutParams params1 = (FrameLayout.LayoutParams) mCoordinatorLayout.getLayoutParams();
params1.setMargins(0, params1.topMargin - dy, 0, 0);
mCoordinatorLayout.setLayoutParams(params1);
}
}
}
}
#Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (RecyclerView.SCROLL_STATE_IDLE == newState) {
if(mToolbar != null) {
if (Math.abs(mToolbar.getTranslationY()) <= mToolbar.getHeight() / 2) {
ObjectAnimator animator = ObjectAnimator.ofFloat(mToolbar, View.TRANSLATION_Y, mToolbar.getTranslationY(), 0);
animator.setDuration(300);
animator.start();
MarginAnimation animation = new MarginAnimation(mCoordinatorLayout, ((FrameLayout.LayoutParams) mCoordinatorLayout.getLayoutParams()).topMargin, mCoordinatorLayoutTopMargin);
mCoordinatorLayout.startAnimation(animation);
} else {
ObjectAnimator animator = ObjectAnimator.ofFloat(mToolbar, View.TRANSLATION_Y, mToolbar.getTranslationY(), -mToolbarHeight);
animator.setDuration(300);
animator.start();
MarginAnimation animation = new MarginAnimation(mCoordinatorLayout, ((FrameLayout.LayoutParams) mCoordinatorLayout.getLayoutParams()).topMargin, 0);
mCoordinatorLayout.startAnimation(animation);
}
}
}
}
}
And for the margin animation, create new Class
public class MarginAnimation extends Animation {
private View mView;
private float mToMargin;
private float mFromMargin;
private Context mContext;
public MarginAnimation(View v, float fromTop, float toTop) {
mFromMargin = fromTop;
mToMargin = toTop;
mView = v;
setDuration(300);
}
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
float topMargin = (mToMargin - mFromMargin) * interpolatedTime + mFromMargin;
Log.d("TopMargin", String.valueOf(topMargin));
FrameLayout.LayoutParams p = (FrameLayout.LayoutParams) mView.getLayoutParams();
p.setMargins(0, (int) topMargin, 0, 0);
mView.setLayoutParams(p);
mView.requestLayout();
}
#Override
public void initialize(int width, int height, int parentWidth, int parentHeight) {
super.initialize(width, height, parentWidth, parentHeight);
}
#Override
public boolean willChangeBounds() {
return true;
}
}
Hope this helps...
I am having trouble with a scrolling ListView inside a ScrollView. I have an Activity which has some EditTexts in the top part and then a tab host with two tabs which have one ListView each. When the EditText views are focused, the soft keyboard comes up and as I have a ScrollView, the content is scrollable. But the problem comes when there are more items in ListViews (ones in tabs), I am not able to scroll the ListView, even if there are more items.
The following is the layout XML:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="?backgroundImage"
android:orientation="vertical">
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="50dip"
android:layout_alignParentBottom="true"
android:layout_margin="10dip"
android:id="#+id/buttons">
<Button
android:text="Save"
android:layout_margin="2dip"
android:textSize="20dip"
android:id="#+id/btnSaveorUpdate"
android:layout_height="wrap_content"
android:layout_width="145dip"></Button>
<Button
android:text="Cancel"
android:layout_margin="2dip"
android:textSize="20dip"
android:id="#+id/btnCancelorDelete"
android:layout_height="wrap_content"
android:layout_width="145dip"></Button>
</LinearLayout>
<ScrollView
android:layout_above="#id/buttons"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:fillViewport="true"
android:layout_margin="10dip">
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_margin="10dip">
<TextView
android:text="Bill details"
android:textColor="?textColorDark"
android:layout_alignParentTop="true"
android:id="#+id/txtEnterDetails"
android:textSize="25dip"
android:textStyle="bold"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_marginBottom="2dip"></TextView>
<LinearLayout
android:focusable="true"
android:focusableInTouchMode="true"
android:layout_width="0dip"
android:layout_height="0dip" />
<EditText
android:layout_width="fill_parent"
android:hint="Enter data"
android:inputType="numberDecimal"
android:id="#+id/txtSample"
android:textSize="#dimen/editText"
android:layout_height="#dimen/editTextHeight"
android:text=""></EditText>
<EditText
android:layout_width="fill_parent"
android:id="#+id/txtDescription"
android:hint="Enter description"
android:textSize="#dimen/editText"
android:layout_height="#dimen/editTextHeight"
android:inputType="text"
android:text=""></EditText>
<EditText
android:layout_width="fill_parent"
android:id="#+id/txtComment"
android:hint="Enter comment (if any)"
android:textSize="#dimen/editText"
android:layout_height="#dimen/editTextHeight"
android:inputType="text"
android:text=""></EditText>
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/txtDate"
android:layout_width="wrap_content"
android:text=""
android:textSize="20dip"
android:textColor="?textColorDark"
android:layout_marginLeft="10dip"
android:layout_height="#dimen/editTextHeight"
android:layout_gravity="center_vertical" />
<Button
android:id="#+id/btnPickDate"
android:layout_width="wrap_content"
android:layout_height="#dimen/editTextHeight"
android:text="Select date"
android:layout_margin="2dip"
android:textSize="15dip"
android:layout_gravity="center_vertical" />
</LinearLayout>
<TabHost
android:id="#+id/tabhost"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:id="#+id/linearLayout1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<TabWidget
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#android:id/tabs"></TabWidget>
<FrameLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#android:id/tabcontent">
<ScrollView
android:layout_above="#id/buttons"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:fillViewport="true"
android:id="#+id/tab1">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TableLayout
android:layout_height="wrap_content"
android:layout_width="fill_parent">
<TableRow
android:id="#+id/tableRow1"
android:layout_marginLeft="2dip"
android:layout_marginRight="5dip"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:src="#drawable/ic_menu_invite"
android:layout_width="40dip"
android:layout_height="40dip"
android:layout_gravity="center_vertical"></ImageView>
<TextView
android:text="Add friend"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_centerVertical="true"
android:textColor="?textColorDark"
android:textSize="#dimen/editText"
android:layout_gravity="center_vertical" />
</LinearLayout>
</TableRow>
<TableRow
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dip"
android:layout_marginRight="5dip">
<TextView
android:id="#+id/txtData1"
android:layout_width="170dip"
android:layout_height="wrap_content"
android:text="Data"
android:textSize="14dip"
android:textStyle="bold"
android:textColor="#000000">
</TextView>
<TextView
android:id="#+id/txtData2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Sample"
android:textSize="13dip"
android:textColor="#000000"></TextView>
</TableRow>
</TableLayout>
<ListView
android:cacheColorHint="#00000000"
android:id="#+id/ListView01"
android:layout_height="wrap_content"
android:layout_width="fill_parent" />
</LinearLayout>
</ScrollView>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:id="#+id/tab2"
android:orientation="vertical">
<TableLayout
android:layout_height="wrap_content"
android:layout_width="fill_parent">
<TableRow
android:id="#+id/tableRow2"
android:layout_marginLeft="2dip"
android:layout_marginRight="5dip"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:src="#drawable/ic_menu_invite"
android:layout_width="40dip"
android:layout_height="40dip"
android:layout_gravity="center_vertical"></ImageView>
<TextView
android:text="Sample"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_centerVertical="true"
android:textColor="?textColorDark"
android:textSize="#dimen/editText"
android:layout_gravity="center_vertical" />
</LinearLayout>
</TableRow>
<TableRow
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dip"
android:layout_marginRight="5dip">
<TextView
android:id="#+id/txtUser1"
android:layout_width="170dip"
android:layout_height="wrap_content"
android:text="User"
android:textSize="14dip"
android:textStyle="bold"
android:textColor="#000000">
</TextView>
<TextView
android:id="#+id/txtUserData"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="UserData"
android:textSize="13dip"
android:textColor="#000000"></TextView>
</TableRow>
</TableLayout>
<ListView
android:cacheColorHint="#00000000"
android:id="#+id/ListView02"
android:layout_height="wrap_content"
android:layout_width="fill_parent" />
</LinearLayout>
</FrameLayout>
</LinearLayout>
</TabHost>
</LinearLayout>
</ScrollView>
</RelativeLayout>
Please can anyone tell me what the problem is here? I have another post on the ListView inside ScrollView problem, but they were of no use in my case.
I found a solution that works excellently and can scroll the ListView without problems:
ListView lv = (ListView)findViewById(R.id.myListView); // your listview inside scrollview
lv.setOnTouchListener(new ListView.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
// Disallow ScrollView to intercept touch events.
v.getParent().requestDisallowInterceptTouchEvent(true);
break;
case MotionEvent.ACTION_UP:
// Allow ScrollView to intercept touch events.
v.getParent().requestDisallowInterceptTouchEvent(false);
break;
}
// Handle ListView touch events.
v.onTouchEvent(event);
return true;
}
});
What this does is disable the TouchEvents on the ScrollView and make the ListView intercept them. It is simple and works all the time.
You shouldn't put a ListView inside a ScrollView because the ListView class implements its own scrolling and it just doesn't receive gestures because they all are handled by the parent ScrollView. I strongly recommend you to simplify your layout somehow. For example you can add views you want to be scrolled to the ListView as headers or footers.
UPDATE:
Starting from API Level 21 (Lollipop) nested scroll containers are officially supported by Android SDK. There're a bunch of methods in View and ViewGroup classes which provide this functionality. To make nested scrolling work on the Lollipop you have to enable it for a child scroll view by adding android:nestedScrollingEnabled="true" to its XML declaration or by explicitly calling setNestedScrollingEnabled(true).
If you want to make nested scrolling work on pre-Lollipop devices, which you probably do, you have to use corresponding utility classes from the Support library. First you have to replace you ScrollView with NestedScrollView. The latter implements both NestedScrollingParent and NestedScrollingChild so it can be used as a parent or a child scroll container.
But ListView doesn't support nested scrolling, therefore you need to subclass it and implement NestedScrollingChild. Fortunately, the Support library provides NestedScrollingChildHelper class, so you just have to create an instance of this class and call its methods from the corresponding methods of your view class.
I have also one solution. I always use this method. Try this
<ScrollView
android:id="#+id/createdrill_scrollView"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_marginTop="15dp" >
<net.thepaksoft.fdtrainer.NestedListView
android:id="#+id/crewList"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
android:layout_weight="1"
android:background="#drawable/round_shape"
android:cacheColorHint="#00000000" >
</net.thepaksoft.fdtrainer.NestedListView>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_marginTop="15dp" >
<net.thepaksoft.fdtrainer.NestedListView
android:id="#+id/benchmarksList"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
android:layout_weight="1"
android:background="#drawable/round_shape"
android:cacheColorHint="#00000000" >
</net.thepaksoft.fdtrainer.NestedListView>
</LinearLayout>
</ScrollView>
NestedListView.java class:
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 have to just replace your <ScrollView ></ScrollView> with this Custom ScrollView like <com.tmd.utils.VerticalScrollview > </com.tmd.utils.VerticalScrollview >
package com.tmd.utils;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
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:
Log.i("VerticalScrollview", "onInterceptTouchEvent: DOWN super false" );
super.onTouchEvent(ev);
break;
case MotionEvent.ACTION_MOVE:
return false; // redirect MotionEvents to ourself
case MotionEvent.ACTION_CANCEL:
Log.i("VerticalScrollview", "onInterceptTouchEvent: CANCEL super false" );
super.onTouchEvent(ev);
break;
case MotionEvent.ACTION_UP:
Log.i("VerticalScrollview", "onInterceptTouchEvent: UP super false" );
return false;
default: Log.i("VerticalScrollview", "onInterceptTouchEvent: " + action ); break;
}
return false;
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
super.onTouchEvent(ev);
Log.i("VerticalScrollview", "onTouchEvent. action: " + ev.getAction() );
return true;
}
}
I had a same issue and while googling I found your question. Yes marked answer worked for me also but there was some issue. Anyways I found another solution.
which works perfectly without doing any jugglery.
I know this question is asked long ago, but who ever is stuck for now can solve this by adding this line into your ListView
android:nestedScrollingEnabled="true"
For Example -
<ListView
android:id="#+id/listView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:nestedScrollingEnabled="true" />
Here is the exact method of using Listview with in the Scrollview. All we have to handle touch events.
lstvNextTracks.setOnTouchListener(new OnTouchListener()
{
#Override
public boolean onTouch(View v, MotionEvent event)
{
Log.e("Lisview *************", "focused");
SCView.requestDisallowInterceptTouchEvent(true);
return false;
}
});
SCView.setOnTouchListener(new OnTouchListener()
{
#Override
public boolean onTouch(View v, MotionEvent event)
{
int arr[] = new int[] { 1, 2 };
lstvNextTracks.getLocationOnScreen(arr);
/* Get bounds of child Listview*/
int lstvTop = arr[0];
int lstvBottom = arr[1] + lstvNextTracks.getHeight();
int lstvLeft = arr[1];
int lstvRight = arr[0] + lstvNextTracks.getWidth();
float x = event.getRawX();
float y = event.getRawY();
if (event.getAction() == MotionEvent.ACTION_DOWN)
{
/*check if child ListView bounds are touched*/
if (x > lstvTop && x < lstvBottom && y > lstvLeft && y < lstvRight)
{
SCView.clearFocus();
/*This statement tells the ScrollView to do not handle this touch event, so the child Listview will handle this touch event and will scroll */
SCView.requestDisallowInterceptTouchEvent(true);
/*The child Listview isFocusable attribute must be set to true otherwise it will not work*/
lstvNextTracks.requestFocus();
return true;
} else
return false;
} else if (event.getAction() == MotionEvent.ACTION_MOVE)
{
if (x > lstvTop && x < lstvBottom && y > lstvLeft && y < lstvRight)
{
SCView.clearFocus();
SCView.requestDisallowInterceptTouchEvent(true);
lstvNextTracks.requestFocus();
return true;
} else
return false;
} else if (event.getAction() == MotionEvent.ACTION_UP)
{
SCView.clearFocus();
SCView.requestDisallowInterceptTouchEvent(true);
lstvNextTracks.requestFocus();
return false;
} else
{
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.
Enjoy!
Its a bad practice to have two different scrolling views together. ListView itself has its own scrolling functionality and height is auto adjusted according to Adapter settings for your row items (Keelping in mind, we are not setting specific height to ListView in our Layout xml). However in your case, you can replace ListView with a class and this will adjust height for your ListView keeping in mind that your ListView is inside ScrollView.
This will help you:
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;
}
}
Now extend your ListView with this class, just change your ListView tag from your resource xml to smothing like this,
<yourpackagename.ExpandableHeightListview
android:id="#+id/listView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/White"
android:scrollbars="none"
android:orientation="vertical"
android:fadingEdge="none">
</cyourpackagename.ExpandableHeightListview>
This will solve your scrolling problem of ListView, as now the parent scrolling is managed by ScrollView rather then ListView.
I've similar issue and resolved by creating custom class by extending with ListView.
ScrollableListView.java
import android.content.Context;
import android.util.AttributeSet;
import android.widget.ListView;
public class ScrollableListView extends ListView {
public ScrollableListView (Context context, AttributeSet attrs) {
super(context, attrs);
}
public ScrollableListView (Context context) {
super(context);
}
public ScrollableListView (Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}
}
Usage:
<com.my.package.ScrollableListView
android:id="#+id/listview"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
Add:
android:nestedScrollingEnabled="true"
requestDisallowInterceptTouchEvent (boolean disallowIntercept)
Called when a child does not want this parent and its ancestors to intercept touch events with onInterceptTouchEvent(MotionEvent).
This parent should pass this call onto its parents. This parent must obey this request for the duration of the touch (that is, only clear the flag after this parent has received an up or a cancel.
Try this answer,
listview.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
// Disallow the touch request for parent scroll on touch of child view
scrollView.requestDisallowInterceptTouchEvent(true);
int action = event.getActionMasked();
switch (action) {
case MotionEvent.ACTION_UP:
scrollView.requestDisallowInterceptTouchEvent(false);
break;
}
return false;
}
});
The best solution is to use NestedScrollVew with RecyclerView or if you want to go with Listview then you can add header and footer view to this.
For example:
View footerView = ((LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.outofoffice_footer_view, null, false);
infoListView.addFooterView(footerView);
I have tried and tested nearly all the methods mentioned above, trust me, after completely running away from RecyclerView, I replaced my ListView with RecyclerView and it worked perfectly. Didnt need any 3rd Party library for ExtendedHeightListView and all, just plain and simple RecyclerView.
So Heres my Layout file before recyclerView:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/scrollView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:elevation="5dp">
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/relativeLayoutre"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="2dp"
tools:context="com.example.android.udamovappv3.activities.DetailedActivity">
<android.support.v7.widget.Toolbar
android:id="#+id/my_toolbar_detail"
android:layout_width="match_parent"
android:layout_height="56dp"
android:layout_gravity="top"
android:background="?attr/colorPrimary"
android:elevation="4dp"
android:theme="#style/ThemeOverlay.AppCompat.ActionBar"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light" />
<TextView
android:id="#+id/title_name"
android:layout_width="fill_parent"
android:layout_height="128dp"
android:layout_alignParentStart="true"
android:layout_marginTop="59dp"
android:background="#079ED9"
android:gravity="left|center"
android:padding="25dp"
android:text="Name"
android:textColor="#ffffff"
android:textSize="30sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="#+id/my_toolbar_detail"
app:layout_constraintVertical_bias="0.0"
tools:layout_editor_absoluteX="0dp" />
<ImageView
android:id="#+id/iv_poster"
android:layout_width="131dp"
android:layout_height="163dp"
android:layout_alignStart="#+id/my_toolbar_detail"
android:layout_below="#+id/title_name"
android:layout_marginBottom="15dp"
android:layout_marginRight="8dp"
android:layout_marginTop="15dp"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:srcCompat="#mipmap/ic_launcher" />
<Button
android:id="#+id/bt_mark_as_fav"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/iv_poster"
android:layout_alignParentEnd="true"
android:layout_marginBottom="11dp"
android:layout_marginEnd="50dp"
android:background="#079ED9"
android:text="Mark As \n Favorite"
android:textSize="10dp" />
<TextView
android:id="#+id/tv_runTime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignStart="#+id/tv_rating"
android:layout_below="#+id/tv_releaseDate"
android:layout_marginTop="11dp"
android:text="TextView"
android:textSize="20sp" />
<TextView
android:id="#+id/tv_releaseDate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignStart="#+id/tv_runTime"
android:layout_alignTop="#+id/iv_poster"
android:text="TextView"
android:textSize="25dp" />
<TextView
android:id="#+id/tv_rating"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignStart="#+id/bt_mark_as_fav"
android:layout_below="#+id/tv_runTime"
android:layout_marginTop="11dp"
android:text="TextView" />
<TextView
android:id="#+id/tv_overview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/iv_poster"
android:layout_centerHorizontal="true"
android:layout_marginBottom="5dp"
android:foregroundGravity="center"
android:text="adasdasdfadfsasdfasdfasdfasdfnb agfjuanfalsbdfjbdfklbdnfkjasbnf;kasbdnf;kbdfas;kdjabnf;lbdnfo;aidsnfl';asdfj'plasdfj'pdaskjf'asfj'p[asdfk"
android:textColor="#000000"
/>
<RelativeLayout
android:id="#+id/foodItemActvity_linearLayout_fragments"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_below="#+id/tv_overview">
<TextView
android:id="#+id/fragment_dds_review_textView_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Reviews:"
android:textAppearance="?android:attr/textAppearanceMedium" />
<com.github.paolorotolo.expandableheightlistview.ExpandableHeightListView
android:id="#+id/expandable_listview"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:layout_alignParentBottom="true"
android:layout_alignParentStart="true"
android:layout_below="#+id/fragment_dds_review_textView_label"
android:padding="8dp">
</com.github.paolorotolo.expandableheightlistview.ExpandableHeightListView>
</RelativeLayout>
</RelativeLayout>
</ScrollView>
THIS IS AFTER REPLACING MY LISTVIEW WITH ONE OF THE MANY SOLUTIONS MENTIONED ABOVE. So the problem was that the listview was not behaving properly due to 2 scrollview bug(maybe not a bug) in android.
I replaced the
with recycler view to form form my final layout.
This is my recycler view adapter:
public class TrailerAdapter extends RecyclerView.Adapter<TrailerAdapter.TrailerAdapterViewHolder> {
private ArrayList<String> Youtube_URLS;
private Context Context;
public TrailerAdapter(Context context, ArrayList<String> Youtube_URLS){
this.Context = context;
this.Youtube_URLS = Youtube_URLS;
}
#Override
public TrailerAdapter.TrailerAdapterViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.trailer_layout, parent, false);
return new TrailerAdapterViewHolder(view);
}
#Override
public void onBindViewHolder(TrailerAdapter.TrailerAdapterViewHolder holder, int position) {
Picasso.with(Context).load(R.drawable.ic_play_arrow_black_24dp).into(holder.iv_playbutton);
holder.item_id.setText(Youtube_URLS.get(position));
}
#Override
public int getItemCount() {
if(Youtube_URLS.size()==0){
return 0;
}else{
return Youtube_URLS.size();
}
}
public class TrailerAdapterViewHolder extends RecyclerView.ViewHolder {
ImageView iv_playbutton;
TextView item_id;
public TrailerAdapterViewHolder(View itemView) {
super(itemView);
iv_playbutton = (ImageView)itemView.findViewById(R.id.play_button);
item_id = (TextView)itemView.findViewById(R.id.tv_trailer_sequence);
}
}
}
And this is my RecyclerView custom layout:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="56dp"
android:padding="6dip" >
<ImageView
android:id="#+id/play_button"
android:layout_width="70dp"
android:layout_height="wrap_content"
android:layout_marginRight="6dip"
android:layout_marginStart="12dp"
android:src="#drawable/ic_play_arrow_black_24dp"
android:layout_centerVertical="true"
android:layout_alignParentStart="true" />
<TextView
android:id="#+id/tv_trailer_sequence"
android:layout_width="wrap_content"
android:layout_height="26dip"
android:layout_centerVertical="true"
android:layout_toEndOf="#+id/play_button"
android:ellipsize="marquee"
android:gravity="center"
android:maxLines="1"
android:text="Description"
android:textSize="12sp" />
</RelativeLayout>
And VOILA, I got the desired effect of ListView(Now RecyclerView) within a scollview.
Heres the Final Image of the UI
On a final note, I believe that replacing the RecyclerView was a better choice for me, as it improved the overall app stability, and also helped me understand RecyclerView better. If I were to suggest a solution, Im going to say replace your ListView with a RecyclerView.
I have had this error.And my solution is following as:
1. Create a custom listview which is non scrollable
public class NonScrollListView extends ListView {
public NonScrollListView(Context context) {
super(context);
}
public NonScrollListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public NonScrollListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int heightMeasureSpec_custom = MeasureSpec.makeMeasureSpec(
Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, heightMeasureSpec_custom);
ViewGroup.LayoutParams params = getLayoutParams();
params.height = getMeasuredHeight();
}
}
2. Use above custom class for xml file
<com.Example.NonScrollListView
android:id="#+id/lv_nonscroll_list"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</com.Example.NonScrollListView>
Hope best for you.
Above solution given by #Shailesh Rohit works perfectly fine. Some tricks has to be done.
If you are putting helper class inside the same class( main class) then make Helper class as static and getListViewSize() not be static.
Most important, write "Helper.getListViewSize(listView);" statement after setting adapter for the first time like "listView.setAdapter(myAdapter);" as well as when ever you are using "myAdapter.notifyDataSetChanged();"
Usage is shown below.
listView = (ListView) findViewById(R.id.listView);
myAdapter = new ArrayAdapter(this,android.R.layout.simple_list_item_1, listValues);
listView .setAdapter(myAdapter);
Helper.getListViewSizelistView(listView);
myAdapter.notifyDataSetChanged();
Helper.getListViewSizelistView(listView);
Best Code
<android.support.v4.widget.NestedScrollView
android:id="#+id/scrollView1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#+id/btmlyt"
android:layout_below="#+id/deshead_tv">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<TextView
android:id="#+id/des_tv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="#+id/btmlyt"
android:background="#android:color/white"
android:paddingLeft="3dp"
android:paddingRight="3dp"
android:scrollbars="vertical"
android:paddingTop="3dp"
android:text="description"
android:textColor="#android:color/black"
android:textSize="18sp" />
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
Here is the best example
Add NestedScrollView instead of Scrollview
Add this line in ListView android:nestedScrollingEnabled="true"
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:nestedScrollingEnabled="true"
/>
</androidx.core.widget.NestedScrollView>
Demo_ListView_In_ScrollView
==============================
package com.app.custom_seekbar;
import java.util.ArrayList;
import android.app.Activity;
import android.os.Bundle;
import android.widget.ListView;
public class Demo_ListView_In_ScrollView extends Activity
{
ListView listview;
ArrayList<String> data=null;
listview_adapter adapter=null;
#Override
protected void onCreate(Bundle savedInstanceState)
{
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
super.setContentView(R.layout.demo_listview_in_scrollview_activity);
init();
set_data();
set_adapter();
}
public void init()
{
listview=(ListView)findViewById(R.id.listView1);
data=new ArrayList<String>();
}
public void set_data()
{
data.add("Meet");
data.add("prachi");
data.add("shailesh");
data.add("manoj");
data.add("sandip");
data.add("zala");
data.add("tushar");
data.add("Meet");
data.add("prachi");
data.add("shailesh");
data.add("manoj");
data.add("sandip");
data.add("zala");
data.add("tushar");
data.add("Meet");
data.add("prachi");
data.add("shailesh");
data.add("manoj");
data.add("sandip");
data.add("zala");
data.add("tushar");
data.add("Meet");
data.add("prachi");
data.add("shailesh");
data.add("manoj");
data.add("sandip");
data.add("zala");
data.add("tushar");
data.add("Meet");
data.add("prachi");
data.add("shailesh");
data.add("manoj");
data.add("sandip");
data.add("zala");
data.add("tushar");
data.add("Meet");
data.add("prachi");
data.add("shailesh");
data.add("manoj");
data.add("sandip");
data.add("zala");
data.add("tushar");
data.add("Meet");
data.add("prachi");
data.add("shailesh");
data.add("manoj");
data.add("sandip");
data.add("zala");
data.add("tushar");
data.add("Meet");
data.add("prachi");
data.add("shailesh");
data.add("manoj");
data.add("sandip");
data.add("zala");
data.add("tushar");
data.add("Meet");
data.add("prachi");
data.add("shailesh");
data.add("manoj");
data.add("sandip");
data.add("zala");
data.add("tushar");
data.add("Meet");
data.add("prachi");
data.add("shailesh");
data.add("manoj");
data.add("sandip");
data.add("zala");
data.add("tushar");
data.add("Meet");
data.add("prachi");
data.add("shailesh");
data.add("manoj");
data.add("sandip");
data.add("zala");
data.add("tushar");
data.add("Meet");
data.add("prachi");
data.add("shailesh");
data.add("manoj");
data.add("sandip");
data.add("zala");
data.add("tushar");
data.add("Meet");
data.add("prachi");
data.add("shailesh");
data.add("manoj");
data.add("sandip");
data.add("zala");
data.add("tushar");
}
public void set_adapter()
{
adapter=new listview_adapter(Demo_ListView_In_ScrollView.this,data);
listview.setAdapter(adapter);
Helper.getListViewSize(listview); // set height of listview according to Arraylist item
}
}
========================
listview_adapter
==========================
package com.app.custom_seekbar;
import java.util.ArrayList;
import android.app.Activity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TextView;
public class listview_adapter extends ArrayAdapter<String>
{
private final Activity context;
ArrayList<String>data;
class ViewHolder
{
public TextView tv_name;
public ScrollView scroll;
public LinearLayout l1;
}
public listview_adapter(Activity context, ArrayList<String> all_data) {
super(context, R.layout.item_list_xml, all_data);
this.context = context;
data=all_data;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View rowView = convertView;
ViewHolder viewHolder;
if (rowView == null)
{
LayoutInflater inflater = context.getLayoutInflater();
rowView = inflater.inflate(R.layout.item_list_xml, null);
viewHolder = new ViewHolder();
viewHolder.tv_name=(TextView)rowView.findViewById(R.id.textView1);
rowView.setTag(viewHolder);
}
else
viewHolder = (ViewHolder) rowView.getTag();
viewHolder.tv_name.setText(data.get(position).toString());
return rowView;
}
}
===================================
Helper class (source: https://www.androidhub4you.com/2012/12/listview-into-scrollview-in-android.html)
====================================
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListAdapter;
import android.widget.ListView;
public class Helper {
public static void getListViewSize(ListView myListView) {
ListAdapter myListAdapter = myListView.getAdapter();
if (myListAdapter == null) {
//do nothing return null
return;
}
//set listAdapter in loop for getting final size
int totalHeight = 0;
for (int size = 0; size < myListAdapter.getCount(); size++) {
View listItem = myListAdapter.getView(size, null, myListView);
listItem.measure(0, 0);
totalHeight += listItem.getMeasuredHeight();
}
//setting listview item in adapter
ViewGroup.LayoutParams params = myListView.getLayoutParams();
params.height = totalHeight + (myListView.getDividerHeight() * (myListAdapter.getCount() - 1));
myListView.setLayoutParams(params);
// print height of adapter on log
Log.i("height of listItem:", String.valueOf(totalHeight));
}
}
========================
demo_listview_in_scrollview_activity.xml
========================
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ScrollView
android:id="#+id/scrollView1"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ListView
android:id="#+id/listView1"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout>
</ScrollView>
</LinearLayout>
================
item_list_xml.xml
==================
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:gravity="center"
android:text="TextView"
android:textSize="14sp" />
</LinearLayout>
As According to me while you are using setOnTouchListener om parent or child stop the scrolling of parent as you touch on child else stop scrolling of child as you touch on parent
Try this with ScrollView, not with ListView.
public class xScrollView extends ScrollView
{
;
;
#Override
public boolean onInterceptTouchEvent (MotionEvent ev)
{
return false;
}
}
replace ListView by RecycleView inside ScrollView. it runs smoothly without additional source code:
<ScrollView 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"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.example.hung.recycleviewtest.MainActivityFragment"
>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.RecyclerView
android:id="#+id/recycle_view"
android:layout_width="match_parent"
android:layout_height="400dp"
android:background="#android:color/darker_gray"/>
<android.support.v7.widget.RecyclerView
android:id="#+id/recycle_view_a"
android:layout_marginTop="40dp"
android:layout_below="#id/recycle_view"
android:layout_width="match_parent"
android:layout_height="400dp"
android:background="#android:color/darker_gray"/>
</RelativeLayout>
</ScrollView>
For ListView inside ScrollView use NestedScrollView it can handle this
functionality very easily:
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="5dip"/>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
I found a solution for that,
Instead of using scrollview, You can use addHeaderview and addFooterview of listview
Here is my snippet,
// create separate layout and add it dynamically
scrollview=getLayoutInflater().inflate(R.layout.yourlayout,null);
lv=(ListView)listview.findViewById(R.id.listView2);
lv.addHeaderView(scrollview);
lv.setContentView(lv);
Now, with the listview your layout also can be scrolled. Enjoy it!!!
Replace ScrollView by android.support.v4.widget.NestedScrollView inside xml. it runs
1) Use in XML:::: android.support.v4.widget.NestedScrollView
instead of:::: ScrollView
2) And use for list view in this way using NonScrollListView in cs file:
public class NonScrollListView extends ListView {
public NonScrollListView(Context context) {
super(context);
}
public NonScrollListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public NonScrollListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int heightMeasureSpec_custom = MeasureSpec.makeMeasureSpec(
Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, heightMeasureSpec_custom);
ViewGroup.LayoutParams params = getLayoutParams();
params.height = getMeasuredHeight();
}
}
3) Finally use this code to identify scrollview in cs file:
NonScrollListView listView = (NonScrollListView) view.findViewById(R.id.listview);
You cannot add a ListView in a scroll View, as list view also scolls and there would be a synchonization problem between listview scroll and scroll view scoll.
You can make a CustomList View and add this method into it.
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
/*
* Prevent parent controls from stealing our events once we've gotten a touch down
*/
if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
ViewParent p = getParent();
if (p != null) {
p.requestDisallowInterceptTouchEvent(true);
}
}
return false;
}
Dont give scroll view to ListView, coz it has that setting default
<ListView
android:cacheColorHint="#00000000"
android:id="#+id/ListView01"
android:layout_height="wrap_content"
android:layout_width="fill_parent" />
I have a CustomListView where I'm showing some text and getting an image displayed using Picasso's library. I created a xml file inside the drawable folder and for drawable-21 folder for the Ripple Effect but for some reason the effect is not going above the ImageView.
Here's my files:
drawable:
listview_item_background.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<solid
android:color="#ffdadada"/>
</shape>
</item>
<item>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<solid
android:color="#ffffff"/>
</shape>
</item>
</selector>
drawable-v21:
listview_item_background.xml
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#ffdadada">
<item android:drawable="#android:color/white"/>
</ripple>
activity_main:
<?xml version="1.0"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<android.support.design.widget.AppBarLayout
android:id="#+id/app_bar_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.design.widget.CollapsingToolbarLayout
android:id="#+id/collapsing_toolbar"
android:layout_width="match_parent"
android:layout_height="150dp"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:expandedTitleMarginStart="20dp"
app:expandedTitleMarginEnd="20dp"
app:contentScrim="#color/colorPrimary"
android:background="#color/colorPrimary">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="150dp"
android:gravity="start|bottom"
app:layout_collapseMode="parallax"
android:background="#color/colorPrimary"
android:orientation="vertical">
...
</LinearLayout>
<android.support.v7.widget.Toolbar
android:layout_height="?attr/actionBarSize"
android:layout_width="match_parent"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
app:layout_collapseMode="pin"
app:theme="#style/ToolbarTheme"
android:background="#android:color/transparent"
android:id="#+id/main_toolbar">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:id="#+id/toolbar_title"
android:textSize="20sp"
android:textColor="#ffffff"/>
</android.support.v7.widget.Toolbar>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
android:id="#+id/scroll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
android:background="#eeeeee">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
tools:ignore="UselessParent">
<packagename.NestedListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:divider="#eeeeee"
android:drawSelectorOnTop="true"/>
</LinearLayout>
</FrameLayout>
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>
NestedListView:
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) {
}
#SuppressLint("DrawAllocation")
#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;
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 == View.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;
}
MainActivity:
NestedListView list = (NestedListView)findViewById(android.R.id.list);
CustomList adapter = new CustomList(MainActivity.this, myRssFeed.getList());
adapter.addAll();
list.setAdapter(adapter);
custom_listview_item:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.CardView
android:id="#+id/card_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardCornerRadius="2dp"
app:cardElevation="2dp"
android:layout_marginBottom="#dimen/cardMarginVertical"
android:layout_marginLeft="#dimen/cardMarginHorizontal"
android:layout_marginRight="#dimen/cardMarginHorizontal"
android:layout_marginTop="#dimen/cardMarginVertical"
app:cardPreventCornerOverlap="false"
app:contentPadding="0dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="#drawable/listview_item_background"
android:id="#+id/ln">
<ImageView
android:layout_width="match_parent"
android:layout_height="170dp"
android:background="#d6d6d6"
android:contentDescription="#null"
android:id="#+id/image"
android:scaleType="centerCrop" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingRight="16dp"
android:paddingLeft="16dp"
android:layout_marginBottom="8dp"
android:textSize="18sp"
android:fontFamily="sans-serif"
tools:ignore="HardcodedText,UnusedAttribute"
android:id="#+id/title"/>
<Button
android:layout_width="match_parent"
android:layout_height="36dp"
android:layout_marginTop="16dp"
android:paddingEnd="6dp"
android:paddingRight="6dp"
android:background="#drawable/listview_item_background"
android:text="#string/condividi"
android:textStyle="bold"
android:textSize="16sp"
android:textColor="#color/material_text_dialogs"
android:gravity="center|center_vertical|center_horizontal"
android:stateListAnimator="#null"
tools:ignore="RtlHardcoded,RtlSymmetry,UnusedAttribute"
android:id="#+id/condividi"/>
</LinearLayout>
</android.support.v7.widget.CardView>
</FrameLayout>
CustomList class:
public class CustomList extends ArrayAdapter<RSSItem> {
private static Activity context = null;
private final List<RSSItem> web;
public CustomList(Activity context, List<RSSItem> web) {
super(context, R.layout.new_listview, web);
CustomList.context = context;
this.web = web;
}
#Override
public View getView(final int position, View view, ViewGroup parent) {
LayoutInflater inflater = context.getLayoutInflater();
#SuppressLint({"ViewHolder", "InflateParams"}) final View rowView = inflater.inflate(R.layout.new_listview, null, true);
ImageView imageView = (ImageView)rowView.findViewById(R.id.image);
Picasso.with(context).load(web.get(position).getImage()).into(imageView);
TextView textView = (TextView)rowView.findViewById(R.id.title);
textView.setText(Html.fromHtml(web.get(position).getTitle()));
LinearLayout linearLayout = (LinearLayout)rowView.findViewById(R.id.notizia);
linearLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String url = web.get(position).getLink();
if (!url.startsWith("http://") && !url.startsWith("https://"))
url = "http://" + url;
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
String title = "Completa azione usando:";
Intent chooser = Intent.createChooser(browserIntent, title);
context.startActivity(chooser);
}
});
Button button = (Button)rowView.findViewById(R.id.condividi);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
return rowView;
}
}
That's how I display the ImageView.
Could you help me please?
I managed to fix the issue without an extra layout in my case.:
<CardView ...>
<RelativeLayout
...
android:clickable="true"
android:focusable="true"
android:foreground="?attr/selectableItemBackground">
<ImageView .../>
</RelativeLayout>
</CardView>
Few days back I was also facing same issue. I solved my issue by wrapping ImageView inside FrameLayout and applying android:foreground property on FrameLayout. You also have to set android:clickable property of FrameLayout to true or should set onClickListener to FrameLayout.
Please check my answer in following thread in following link.
Let me know if it helps.
My specific question is: How I can achieve an effect like this: http://youtu.be/EJm7subFbQI
The bounce effect is not important, but i need the "sticky" effect for the headers. Where do I start?, In what can I base me? I need something that I can implement on API 8 to up.
Thanks.
There are a few solutions that already exist for this problem. What you're describing are section headers and have come to be referred to as sticky section headers in Android.
Sticky List Headers
Sticky Scroll Views
HeaderListView
EDIT: Had some free time to add the code of fully working example. Edited the answer accordingly.
For those who don't want to use 3rd party code (or cannot use it directly, e.g. in Xamarin), this could be done fairly easily by hand.
The idea is to use another ListView for the header. This list view contains only the header items. It will not be scrollable by the user (setEnabled(false)), but will be scrolled from code based on main lists' scrolling. So you will have two lists - headerListview and mainListview, and two corresponding adapters headerAdapter and mainAdapter. headerAdapter only returns section views, while mainAdapter supports two view types (section and item). You will need a method that takes a position in the main list and returns a corresponding position in the sections list.
Main activity
public class MainActivity extends AppCompatActivity {
public static final int TYPE_SECTION = 0;
public static final int TYPE_ITEM = 1;
ListView mainListView;
ListView headerListView;
MainAdapter mainAdapter;
HeaderAdapter headerAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mainListView = (ListView)findViewById(R.id.list);
headerListView = (ListView)findViewById(R.id.header);
mainAdapter = new MainAdapter();
headerAdapter = new HeaderAdapter();
headerListView.setEnabled(false);
headerListView.setAdapter(headerAdapter);
mainListView.setAdapter(mainAdapter);
mainListView.setOnScrollListener(new AbsListView.OnScrollListener(){
#Override
public void onScrollStateChanged(AbsListView view, int scrollState){
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
// this should return an index in the headers list, based one the index in the main list. The logic for this is highly dependent on your data.
int pos = mainAdapter.getSectionIndexForPosition(firstVisibleItem);
// this makes sure our headerListview shows the proper section (the one on the top of the mainListview)
headerListView.setSelection(pos);
// this makes sure that headerListview is scrolled exactly the same amount as the mainListview
if(mainAdapter.getItemViewType(firstVisibleItem + 1) == TYPE_SECTION){
headerListView.setSelectionFromTop(pos, mainListView.getChildAt(0).getTop());
}
}
});
}
public class MainAdapter extends BaseAdapter{
int count = 30;
#Override
public int getItemViewType(int position){
if((float)position / 10 == (int)((float)position/10)){
return TYPE_SECTION;
}else{
return TYPE_ITEM;
}
}
#Override
public int getViewTypeCount(){ return 2; }
#Override
public int getCount() { return count - 1; }
#Override
public Object getItem(int position) { return null; }
#Override
public long getItemId(int position) { return position; }
public int getSectionIndexForPosition(int position){ return position / 10; }
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = getLayoutInflater().inflate(R.layout.item, parent, false);
position++;
if(getItemViewType(position) == TYPE_SECTION){
((TextView)v.findViewById(R.id.text)).setText("SECTION "+position);
}else{
((TextView)v.findViewById(R.id.text)).setText("Item "+position);
}
return v;
}
}
public class HeaderAdapter extends BaseAdapter{
int count = 5;
#Override
public int getCount() { return count; }
#Override
public Object getItem(int position) { return null; }
#Override
public long getItemId(int position) { return position; }
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = getLayoutInflater().inflate(R.layout.item, parent, false);
((TextView)v.findViewById(R.id.text)).setText("SECTION "+position*10);
return v;
}
}
}
A couple of things to note here. We do not want to show the very first section in the main view list, because it would produce a duplicate (it's already shown in the header). To avoid that, in your mainAdapter.getCount():
return actualCount - 1;
and make sure the first line in your getView() method is
position++;
This way your main list will be rendering all cells but the first one.
Another thing is that you want to make sure your headerListview's height matches the height of the list item. In this example the height is fixed, but it could be tricky if your items height is not set to an exact value in dp. Please refer to this answer for how to address this: https://stackoverflow.com/a/41577017/291688
Main layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin">
<ListView
android:id="#+id/header"
android:layout_width="match_parent"
android:layout_height="48dp"/>
<ListView
android:id="#+id/list"
android:layout_below="#+id/header"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
Item / header layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="48dp">
<TextView
android:id="#+id/text"
android:gravity="center_vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</LinearLayout>
Add this in your app.gradle file
compile 'se.emilsjolander:StickyScrollViewItems:1.1.0'
then my layout, where I have added android:tag ="sticky" to specific views like textview or edittext not LinearLayout, looks like this. It also uses databinding, ignore that.
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="temp"
type="com.lendingkart.prakhar.lendingkartdemo.databindingmodel.BusinessDetailFragmentModel" />
<variable
name="presenter"
type="com.lendingkart.prakhar.lendingkartdemo.presenters.BusinessDetailsPresenter" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.lendingkart.prakhar.lendingkartdemo.customview.StickyScrollView
android:id="#+id/sticky_scroll"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- scroll view child goes here -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
card_view:cardCornerRadius="5dp"
card_view:cardUseCompatPadding="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
style="#style/group_view_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/businessdetailtitletextviewbackground"
android:padding="#dimen/activity_horizontal_margin"
android:tag="sticky"
android:text="#string/business_contact_detail" />
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="7dp">
<android.support.design.widget.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#string/comapnyLabel"
android:textSize="16sp" />
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp">
<android.support.design.widget.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#string/contactLabel"
android:textSize="16sp" />
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp">
<android.support.design.widget.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#string/emailLabel"
android:textSize="16sp" />
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp">
<android.support.design.widget.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#string/NumberOfEmployee"
android:textSize="16sp" />
</android.support.design.widget.TextInputLayout>
</LinearLayout>
</android.support.v7.widget.CardView>
<android.support.v7.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
card_view:cardCornerRadius="5dp"
card_view:cardUseCompatPadding="true">
<TextView
style="#style/group_view_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/businessdetailtitletextviewbackground"
android:padding="#dimen/activity_horizontal_margin"
android:tag="sticky"
android:text="#string/nature_of_business" />
</android.support.v7.widget.CardView>
<android.support.v7.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
card_view:cardCornerRadius="5dp"
card_view:cardUseCompatPadding="true">
<TextView
style="#style/group_view_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/businessdetailtitletextviewbackground"
android:padding="#dimen/activity_horizontal_margin"
android:tag="sticky"
android:text="#string/taxation" />
</android.support.v7.widget.CardView>
</LinearLayout>
</com.lendingkart.prakhar.lendingkartdemo.customview.StickyScrollView>
</LinearLayout>
</layout>
style group for the textview looks this
<style name="group_view_text" parent="#android:style/TextAppearance.Medium">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textColor">#color/edit_text_color</item>
<item name="android:textSize">16dp</item>
<item name="android:layout_centerVertical">true</item>
<item name="android:textStyle">bold</item>
</style>
and the background for the textview goes like this:(#drawable/businessdetailtitletextviewbackground)
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<solid android:color="#color/edit_text_color" />
</shape>
</item>
<item android:bottom="2dp">
<shape android:shape="rectangle">
<solid android:color="#color/White" />
</shape>
</item>
</layer-list>
For those looking for a solution in 2020, I have quickly created a solution extending the Layout Manager from ruslansharipov project (Sticky Header) and combining it whith the RecycleView Adapter from lisawray Groupie project (Expandable RecycleView).
You can see my example here
Result Here
You can reach this effect using SuperSLiM library. It provides you a LayoutManager for RecyclerView with interchangeable linear, grid, and staggered displays of views.
A good demo is located in github repository
It is simply to get such result
app:slm_headerDisplay="inline|sticky"
or
app:slm_headerDisplay="sticky"
I have used one special class to achieve listview like iPhone.
You can find example with source code here. https://demonuts.com/android-recyclerview-sticky-header-like-iphone/
This class which has updated listview is as
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.animation.AlphaAnimation;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import android.widget.ListView;
import android.widget.RelativeLayout;
public class HeaderListView extends RelativeLayout {
// TODO: Handle listViews with fast scroll
// TODO: See if there are methods to dispatch to mListView
private static final int FADE_DELAY = 1000;
private static final int FADE_DURATION = 2000;
private InternalListView mListView;
private SectionAdapter mAdapter;
private RelativeLayout mHeader;
private View mHeaderConvertView;
private FrameLayout mScrollView;
private AbsListView.OnScrollListener mExternalOnScrollListener;
public HeaderListView(Context context) {
super(context);
init(context, null);
}
public HeaderListView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
mListView = new InternalListView(getContext(), attrs);
LayoutParams listParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
listParams.addRule(ALIGN_PARENT_TOP);
mListView.setLayoutParams(listParams);
mListView.setOnScrollListener(new HeaderListViewOnScrollListener());
mListView.setVerticalScrollBarEnabled(false);
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (mAdapter != null) {
mAdapter.onItemClick(parent, view, position, id);
}
}
});
addView(mListView);
mHeader = new RelativeLayout(getContext());
LayoutParams headerParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
headerParams.addRule(ALIGN_PARENT_TOP);
mHeader.setLayoutParams(headerParams);
mHeader.setGravity(Gravity.BOTTOM);
addView(mHeader);
// The list view's scroll bar can be hidden by the header, so we display our own scroll bar instead
Drawable scrollBarDrawable = getResources().getDrawable(R.drawable.scrollbar_handle_holo_light);
mScrollView = new FrameLayout(getContext());
LayoutParams scrollParams = new LayoutParams(scrollBarDrawable.getIntrinsicWidth(), LayoutParams.MATCH_PARENT);
scrollParams.addRule(ALIGN_PARENT_RIGHT);
scrollParams.rightMargin = (int) dpToPx(2);
mScrollView.setLayoutParams(scrollParams);
ImageView scrollIndicator = new ImageView(context);
scrollIndicator.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
scrollIndicator.setImageDrawable(scrollBarDrawable);
scrollIndicator.setScaleType(ScaleType.FIT_XY);
mScrollView.addView(scrollIndicator);
mScrollView.setVisibility(INVISIBLE);
addView(mScrollView);
}
public void setAdapter(SectionAdapter adapter) {
mAdapter = adapter;
mListView.setAdapter(adapter);
}
public void setOnScrollListener(AbsListView.OnScrollListener l) {
mExternalOnScrollListener = l;
}
private class HeaderListViewOnScrollListener implements AbsListView.OnScrollListener {
private int previousFirstVisibleItem = -1;
private int direction = 0;
private int actualSection = 0;
private boolean scrollingStart = false;
private boolean doneMeasuring = false;
private int lastResetSection = -1;
private int nextH;
private int prevH;
private View previous;
private View next;
private AlphaAnimation fadeOut = new AlphaAnimation(1f, 0f);
private boolean noHeaderUpToHeader = false;
private boolean didScroll = false;
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (mExternalOnScrollListener != null) {
mExternalOnScrollListener.onScrollStateChanged(view, scrollState);
}
didScroll = true;
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if (mExternalOnScrollListener != null) {
mExternalOnScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
}
if (!didScroll) {
return;
}
firstVisibleItem -= mListView.getHeaderViewsCount();
if (firstVisibleItem < 0) {
mHeader.removeAllViews();
return;
}
updateScrollBar();
if (visibleItemCount > 0 && firstVisibleItem == 0 && mHeader.getChildAt(0) == null) {
addSectionHeader(0);
lastResetSection = 0;
}
int realFirstVisibleItem = getRealFirstVisibleItem(firstVisibleItem, visibleItemCount);
if (totalItemCount > 0 && previousFirstVisibleItem != realFirstVisibleItem) {
direction = realFirstVisibleItem - previousFirstVisibleItem;
actualSection = mAdapter.getSection(realFirstVisibleItem);
boolean currIsHeader = mAdapter.isSectionHeader(realFirstVisibleItem);
boolean prevHasHeader = mAdapter.hasSectionHeaderView(actualSection - 1);
boolean nextHasHeader = mAdapter.hasSectionHeaderView(actualSection + 1);
boolean currHasHeader = mAdapter.hasSectionHeaderView(actualSection);
boolean currIsLast = mAdapter.getRowInSection(realFirstVisibleItem) == mAdapter.numberOfRows(actualSection) - 1;
boolean prevHasRows = mAdapter.numberOfRows(actualSection - 1) > 0;
boolean currIsFirst = mAdapter.getRowInSection(realFirstVisibleItem) == 0;
boolean needScrolling = currIsFirst && !currHasHeader && prevHasHeader && realFirstVisibleItem != firstVisibleItem;
boolean needNoHeaderUpToHeader = currIsLast && currHasHeader && !nextHasHeader && realFirstVisibleItem == firstVisibleItem && Math.abs(mListView.getChildAt(0).getTop()) >= mListView.getChildAt(0).getHeight() / 2;
noHeaderUpToHeader = false;
if (currIsHeader && !prevHasHeader && firstVisibleItem >= 0) {
resetHeader(direction < 0 ? actualSection - 1 : actualSection);
} else if ((currIsHeader && firstVisibleItem > 0) || needScrolling) {
if (!prevHasRows) {
resetHeader(actualSection-1);
}
startScrolling();
} else if (needNoHeaderUpToHeader) {
noHeaderUpToHeader = true;
} else if (lastResetSection != actualSection) {
resetHeader(actualSection);
}
previousFirstVisibleItem = realFirstVisibleItem;
}
if (scrollingStart) {
int scrolled = realFirstVisibleItem >= firstVisibleItem ? mListView.getChildAt(realFirstVisibleItem - firstVisibleItem).getTop() : 0;
if (!doneMeasuring) {
setMeasurements(realFirstVisibleItem, firstVisibleItem);
}
int headerH = doneMeasuring ? (prevH - nextH) * direction * Math.abs(scrolled) / (direction < 0 ? nextH : prevH) + (direction > 0 ? nextH : prevH) : 0;
mHeader.scrollTo(0, -Math.min(0, scrolled - headerH));
if (doneMeasuring && headerH != mHeader.getLayoutParams().height) {
LayoutParams p = (LayoutParams) (direction < 0 ? next.getLayoutParams() : previous.getLayoutParams());
p.topMargin = headerH - p.height;
mHeader.getLayoutParams().height = headerH;
mHeader.requestLayout();
}
}
if (noHeaderUpToHeader) {
if (lastResetSection != actualSection) {
addSectionHeader(actualSection);
lastResetSection = actualSection + 1;
}
mHeader.scrollTo(0, mHeader.getLayoutParams().height - (mListView.getChildAt(0).getHeight() + mListView.getChildAt(0).getTop()));
}
}
private void startScrolling() {
scrollingStart = true;
doneMeasuring = false;
lastResetSection = -1;
}
private void resetHeader(int section) {
scrollingStart = false;
addSectionHeader(section);
mHeader.requestLayout();
lastResetSection = section;
}
private void setMeasurements(int realFirstVisibleItem, int firstVisibleItem) {
if (direction > 0) {
nextH = realFirstVisibleItem >= firstVisibleItem ? mListView.getChildAt(realFirstVisibleItem - firstVisibleItem).getMeasuredHeight() : 0;
}
previous = mHeader.getChildAt(0);
prevH = previous != null ? previous.getMeasuredHeight() : mHeader.getHeight();
if (direction < 0) {
if (lastResetSection != actualSection - 1) {
addSectionHeader(Math.max(0, actualSection - 1));
next = mHeader.getChildAt(0);
}
nextH = mHeader.getChildCount() > 0 ? mHeader.getChildAt(0).getMeasuredHeight() : 0;
mHeader.scrollTo(0, prevH);
}
doneMeasuring = previous != null && prevH > 0 && nextH > 0;
}
private void updateScrollBar() {
if (mHeader != null && mListView != null && mScrollView != null) {
int offset = mListView.computeVerticalScrollOffset();
int range = mListView.computeVerticalScrollRange();
int extent = mListView.computeVerticalScrollExtent();
mScrollView.setVisibility(extent >= range ? View.INVISIBLE : View.VISIBLE);
if (extent >= range) {
return;
}
int top = range == 0 ? mListView.getHeight() : mListView.getHeight() * offset / range;
int bottom = range == 0 ? 0 : mListView.getHeight() - mListView.getHeight() * (offset + extent) / range;
mScrollView.setPadding(0, top, 0, bottom);
fadeOut.reset();
fadeOut.setFillBefore(true);
fadeOut.setFillAfter(true);
fadeOut.setStartOffset(FADE_DELAY);
fadeOut.setDuration(FADE_DURATION);
mScrollView.clearAnimation();
mScrollView.startAnimation(fadeOut);
}
}
private void addSectionHeader(int actualSection) {
View previousHeader = mHeader.getChildAt(0);
if (previousHeader != null) {
mHeader.removeViewAt(0);
}
if (mAdapter.hasSectionHeaderView(actualSection)) {
mHeaderConvertView = mAdapter.getSectionHeaderView(actualSection, mHeaderConvertView, mHeader);
mHeaderConvertView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
mHeaderConvertView.measure(MeasureSpec.makeMeasureSpec(mHeader.getWidth(), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
mHeader.getLayoutParams().height = mHeaderConvertView.getMeasuredHeight();
mHeaderConvertView.scrollTo(0, 0);
mHeader.scrollTo(0, 0);
mHeader.addView(mHeaderConvertView, 0);
} else {
mHeader.getLayoutParams().height = 0;
mHeader.scrollTo(0, 0);
}
mScrollView.bringToFront();
}
private int getRealFirstVisibleItem(int firstVisibleItem, int visibleItemCount) {
if (visibleItemCount == 0) {
return -1;
}
int relativeIndex = 0, totalHeight = mListView.getChildAt(0).getTop();
for (relativeIndex = 0; relativeIndex < visibleItemCount && totalHeight < mHeader.getHeight(); relativeIndex++) {
totalHeight += mListView.getChildAt(relativeIndex).getHeight();
}
int realFVI = Math.max(firstVisibleItem, firstVisibleItem + relativeIndex - 1);
return realFVI;
}
}
public ListView getListView() {
return mListView;
}
public void addHeaderView(View v) {
mListView.addHeaderView(v);
}
private float dpToPx(float dp) {
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getContext().getResources().getDisplayMetrics());
}
protected class InternalListView extends ListView {
public InternalListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected int computeVerticalScrollExtent() {
return super.computeVerticalScrollExtent();
}
#Override
protected int computeVerticalScrollOffset() {
return super.computeVerticalScrollOffset();
}
#Override
protected int computeVerticalScrollRange() {
return super.computeVerticalScrollRange();
}
}
}
XML usage
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.example.parsaniahardik.listview_stickyheader_ios.HeaderListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/lv">
</com.example.parsaniahardik.listview_stickyheader_ios.HeaderListView>