Giter VIP home page Giter VIP logo

quickreturn's Introduction

QuickReturn

Android Arsenal

Android ListView that implements the QuickReturn UI pattern. Written from scratch with focus on performance.

Demo

video thumbnail

Usage

In your build.gradle file:

dependencies {
    // ...
    compile 'com.felipecsl.quickreturn:library:1.5.1'
}

In your activity class:

private ListView listView;
private ArrayAdapter<String> adapter;
private QuickReturnAttacher quickReturnAttacher;
private TextView quickReturnTarget;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);

    // your listView :)
    listView = (ListView) findViewById(R.id.listView);

    // the quick return target view to be hidden/displayed
    quickReturnTarget = (TextView) findViewById(R.id.quickReturnTarget);

    // your inner adapter
    adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1);

    // Wrap your adapter with QuickReturnAdapter
    listView.setAdapter(new QuickReturnAdapter(adapter));

    // Attach a QuickReturnAttacher, which takes care of all of the hide/show functionality.
    quickReturnAttacher = QuickReturnAttacher.forView(listView);

    // Add a quick return targetView to the attacher.
    // You can pass a position argument (POSITION_TOP or POSITION_BOTTOM).
    // You can also optionally pass the size of the target view, which will be used to 
    // offset the list height, preventing it from hiding content behind the target view.
    quickReturnAttacher.addTargetView(quickReturnTarget, QuickReturnTargetView.POSITION_TOP, 50);

    // If you need to add an OnScrollListener to the listView, this is the correct
    // way to do so.
    // You have to add it on the QuickReturnAttacher instead
    // of adding on the listView directly.
    quickReturnAttacher.addOnScrollListener(this);
}

Check the sample app for an example of usage.

Features

  • Supports dynamic adapters. That means you can add and remove items from your adapter and it will still work nicely.
  • You don't have to subclass QuickReturnAdapter in order to use it. Just pass your own adapter to the constructor and you're done.
  • Animated transitions via QuickReturnAttacher.setAnimatedTransition(true)
  • Supports bottom (footer) quick return position via QuickReturnAttacher.setPosition(QuickReturnListView.POSITION_BOTTOM).
  • You can use it with any subclass of AbsListView, including ListView and GridView.
  • If you're using a GridView, you have to tell QuickReturnAdapter how many columns it has, via its constructor:
  • Automatically adjusts the ListView/GridView to prevent it from being hidden behind the target view, when it is placed at the top of the list.
  • Supports ScrollView as well!
public QuickReturnAdapter(final ListAdapter wrappedAdapter, final int numColumns)

Works with API Level 10 and above.

Known issues/Caveats

  • The Animated Transition will sometimes hide/show randomly when scrolling down very slowly.

Changelog

Please see the Changelog to check what's recently changed.

Credits

Heavily inspired/influenced by the nice work of Roman Nurik's and Nick Butcher's and Lars Werkman's QuickReturnListView

Contributing

  • Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
  • Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
  • Fork the project
  • Start a feature/bugfix branch
  • Commit and push until you are happy with your contribution
  • Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.

Copyright and license

Code and documentation copyright 2011-2014 Felipe Lima. Code released under the MIT license.

quickreturn's People

Contributors

dmitriigriazin avatar felipecsl avatar jgilfelt avatar sixmen avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

quickreturn's Issues

Couldn't click some rows

hi,
I have integrated quick return in my custom listview but i couldn't get click of some random rows
i have total of 4 buttons on each row with different different click events. Majorly found this issue in first and last position of listview
listview is populating from database and at the same time am getting latest values from server and by using notifydatasetcahnge am repopulating listview

CardsLib and QuickReturn

One thing that happened when I used both CardsLib (Top Colored Material card) with QuickReturn (https://github.com/felipecsl/QuickReturn) is that the app wil crash when I scroll down near the bottom. It's okay when it's still far from the bottom.

This is the warning I got:

You are using generic adapter. Pay attention: your adapter has to call cardArrayAdapter#getView method.

This is how I set the adapter:

        listView.setAdapter(mCardArrayAdapter);
        listView.setAdapter(new QuickReturnAdapter(mCardArrayAdapter));

I've posted this issue in CardsLib git too:

gabrielemariotti/cardslib#448

Bottom position issue when listview has a padding

When listview has a top padding, bottom view gets the same bottom padding initially, when you scroll padding goes away.
It is caused by getComputedScrollY method, without - view.getTop() it is in correct place, however quick return just appears / disappears without smooth transition.

What about OnItemLongClickListener?

My ListView has the OnItemLongClickListener, and after wrapping the listAdapter with your library's one, all onLongClick events are delivered to the next Item in the list instead of the one being tapped. Should I make a crutch?

PS
I guess the point is the same as in "onItemClick wrong position #7" issue, however, the index had to be decremented there. Maybe the way it was fixed causes misbehavior of longClick?

issue #12

Hi Felipe,
is it possible to open #12 again and answer my second comment?

Thank you.

Issue with item selection

You library works great but with one major problem.

When I try to select an item in the list, it always selects the item next to it, like if I select the first one, it selects the second one and so on.

Can you please provide a solution to this problem?

Thanks in advance.

Incorrect recycled view when viewtypecount > 1

When I use your library for an ArrayAdapter with viewtypecount > 1. The recycled view in getView is not match with view type. I found the solution in your QuickReturnAdapter.java, just change to the following lines:

@Override
public int getItemViewType(final int position) {
    if (position < numColumns)
        return wrappedAdapter.getViewTypeCount();
    return wrappedAdapter.getItemViewType(position - numColumns);
}

Could you take a look at this fix:)

Thanks,
-Tuan

How Support swiperefreshlayout ?

Hi,

i try your component and seems that is not compatible with swiperefreshlayout when we have top view. Because top view is "front of" listView, the view of swiperefreshlayout isn't displayed (it's behind "top view"...)

Have you a suggest to have this 2 components together ?

READ_PHONE_STATE permission

Hi. Your library added permission READ_PHONE_STATE and app has a problem during install (e.g. avast antivirus detect it how dangerous app).

Please take a look my log manifest-merger-release-report.txt

android:uses-permission#android.permission.WRITE_EXTERNAL_STORAGE
IMPLIED from AndroidManifest.xml:2:1 reason: com.felipecsl.quickreturn has a targetSdkVersion < 4
android:uses-permission#android.permission.READ_PHONE_STATE
IMPLIED from AndroidManifest.xml:2:1 reason: com.felipecsl.quickreturn has a targetSdkVersion < 4
android:uses-permission#android.permission.READ_EXTERNAL_STORAGE
IMPLIED from AndroidManifest.xml:2:1 reason: com.felipecsl.quickreturn requested WRITE_EXTERNAL_STORAGE

Bottom target can hide content of listView

You say: "Automatically adjusts the ListView/GridView to prevent it from being hidden behind the target view, when it is placed at the top of the list."

But when we have a target view at bottom and a listView which have an height close to height of screen, the target view bottom hide last row.

How to fix it ?

Bug when setting listview position

If you set the position of the listview, like if you change following code in your sample, then you've got a very ugly visual bug. :)

Any ideas how to solve that?

Line 65:
if (viewGroup instanceof AbsListView) {
int numColumns = (viewGroup instanceof GridView) ? 3 : 1;
ListView absListView = (ListView) viewGroup;
absListView.setAdapter(new QuickReturnAdapter(adapter, numColumns));

    absListView.setSelectionFromTop(100, 30); // Add this line
}

NullPointer in QuickReturnAdapter

I've come across an error with the adapter using a list view with certain mobile phones.

Genymotion HTC one - API Level 18
sony xperia c5303 - API Level 18
sony xxperia Z1 - API Level 14

java.lang.NullPointerException
at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:548)
at android.view.View.measure(View.java:15848)
at com.felipecsl.quickreturn.library.widget.QuickReturnAdapter.getView(QuickReturnAdapter.java:99)

line 99:
v.measure(View.MeasureSpec.makeMeasureSpec( parent.getWidth() / numColumns , View.MeasureSpec.AT_MOST), heightMeasureSpec);

what could be causing the error? It works fine on other phones ive tested i.e nexus 5.

Blank area displays under target view as you scroll up

Hi. Is there a way to prevent the blank area on the target view (as you scroll up) or is this is an existing issue (I didn't see it in the issues list)? I've tried setting the target view's height as not only 0, but other +/- values, as well. I've also tried leaving it off, but the issue persists. Please help. Hopefully there is an easy fix. This library is great, otherwise. Thank you!

Here is a video demonstrating the issue.

Here is my code:

activity_main.xml

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

    <TextView
        android:id="@+id/testTextView"
        android:layout_width="match_parent"
        android:layout_height="90dp"
        android:paddingLeft="10dp"
        android:gravity="center_vertical"
        android:ellipsize="end"
        android:maxLines="1"
        android:textColor="@android:color/white"
        android:background="@android:color/black"
        android:textStyle="bold"
        android:text="Test Title"
        android:textAppearance="?android:attr/textAppearanceLarge" />

    <ListView
        android:id="@android:id/list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@android:color/holo_blue_light"/>

</LinearLayout>

act_student_menu_item.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:orientation="vertical">

    <RelativeLayout
        android:id="@+id/studentMenuContainer"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingLeft="16dp"
        android:paddingRight="8dp"
        android:layout_centerVertical="true"
        android:orientation="horizontal">

        <ImageView
            android:id="@+id/studentPhotoIcon"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_centerInParent="true"
            android:src="@drawable/icon_photo_grey" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="20dp"
            android:layout_toRightOf="@+id/studentPhotoIcon"
            android:layout_centerInParent="true"
            android:orientation="vertical">

            <TextView
                android:id="@+id/studentNameText"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:ellipsize="end"
                android:textColor="@android:color/white"
                android:textStyle="bold"
                android:textAppearance="?android:attr/textAppearanceLarge" />

            <TextView
                android:id="@+id/studentPointsText"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="5dp"
                android:textColor="@android:color/white"
                android:textAppearance="?android:attr/textAppearanceMedium" />

        </LinearLayout>


    </RelativeLayout>

</RelativeLayout>

onCreate in MainActivity.java

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    // The list view to show/hide on scroll.
    ListView listView = (ListView) findViewById(android.R.id.list);
    TextView testTextView = (TextView) findViewById(R.id.testTextView);
    TestAdapter testAdapter = new TestAdapter(this, android.R.layout.simple_spinner_item,
            getListData());
    // Wrap the adapter with QuickReturnAdapter.
    listView.setAdapter(new QuickReturnAdapter(testAdapter));
    // Attach QuickReturn Attacher, which takes care of all of the hide/show functionality.
    QuickReturnAttacher qrAttacher = QuickReturnAttacher.forView(listView);
    /**
     * Add a quick return targetView to the attacher.
     * You can pass a position argument (POSITION_TOP or POSITION_BOTTOM). You can also optionally pass the size of
     * the target view, which will be used to offset the list height, preventing it from hiding content behind the
     * target view.
     */
    qrAttacher.addTargetView(testTextView, QuickReturnTargetView.POSITION_TOP, 0);
}

TestAdapter.java

public class TestAdapter extends ArrayAdapter<StudentMenuItem> {
    private final Context currentContext;
    private List<StudentMenuItem> studentMenuItems;
    ImageView studentPhotoIcon;
    TextView studentNameText;

    public TestAdapter(Context context, int layoutResourceId, List<StudentMenuItem> studentMenuItems) {
        super(context, layoutResourceId, studentMenuItems);
        currentContext = context;
        this.studentMenuItems = studentMenuItems;
    }

    @Override
    public View getDropDownView(int position, View convertView, ViewGroup parent) {
        View studentMenuOption = convertView;
        if (studentMenuOption == null) {
            LayoutInflater inflater =  (LayoutInflater) currentContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            studentMenuOption = inflater.inflate(R.layout.act_student_menu_item, parent, false);
        }
        StudentMenuItem current = studentMenuItems.get(position);
        studentNameText = (TextView) studentMenuOption.findViewById(R.id.studentNameText);
        studentNameText.setText(current.getStudentName());
        TextView studentPointsText = (TextView) studentMenuOption.findViewById(R.id.studentPointsText);
        studentPointsText.setText(current.getStudentPoints());
        studentPhotoIcon = (ImageView) studentMenuOption.findViewById(R.id.studentPhotoIcon);
        return studentMenuOption;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        return getDropDownView(position, convertView, parent);
    }
}

Note: getListData() just returns List<StudentMenuItem> to populate the list.

Quick Return target hide scroll thumb when scroll to top!!

I investigate the code and see that QuickReturn use a dummy invisible row to prevent the first item of listview overlap by the QuickReturn target
...
if (position < numColumns) {
if (convertView == null)
v = new View(parent.getContext());
else
v = convertView;
v.setLayoutParams(new AbsListView.LayoutParams(
AbsListView.LayoutParams.MATCH_PARENT,
targetViewHeight));

        finalHeight = targetViewHeight;
    } 

...
But by using this technique, the scroll thumb of scroll bar will be hidden by the quickreturn target when we scroll to top also.

Could you modify the code to add a dummy header instead of dummy row to prevent this happen?

Start hidden?

Is there any way to have the quick return layer start out hidden and only come out when the list is scrolled?

I don't see any public methods to manually set the state of the view.

Obrigado!

IndexOutOfBoundsException when clicking Button as Target View

My "target view" is a button. It often (1/3 of the time?) throws this error when being clicked:

02-25 21:59:26.460 21264-21264/com.androidfu.nowplaying.app E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.androidfu.nowplaying.app, PID: 21264
java.lang.IndexOutOfBoundsException: Invalid index 1, size is 1
at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)
at java.util.ArrayList.get(ArrayList.java:308)
at android.widget.HeaderViewListAdapter.isEnabled(HeaderViewListAdapter.java:164)
at android.widget.ListView.dispatchDraw(ListView.java:3307)
at android.view.View.draw(View.java:15117)
at android.widget.AbsListView.draw(AbsListView.java:4083)
at android.view.View.updateDisplayListIfDirty(View.java:14048)
at android.view.View.getDisplayList(View.java:14071)
at android.view.View.draw(View.java:14838)
at android.view.ViewGroup.drawChild(ViewGroup.java:3404)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3198)
at android.view.View.updateDisplayListIfDirty(View.java:14043)
at android.view.View.getDisplayList(View.java:14071)
at android.view.View.draw(View.java:14838)
at android.view.ViewGroup.drawChild(ViewGroup.java:3404)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3198)
at android.view.View.updateDisplayListIfDirty(View.java:14043)
at android.view.View.getDisplayList(View.java:14071)
at android.view.View.draw(View.java:14838)
at android.view.ViewGroup.drawChild(ViewGroup.java:3404)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3198)
at android.view.View.updateDisplayListIfDirty(View.java:14043)
at android.view.View.getDisplayList(View.java:14071)
at android.view.View.draw(View.java:14838)
at android.view.ViewGroup.drawChild(ViewGroup.java:3404)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3198)
at android.view.View.draw(View.java:15117)
at com.android.internal.widget.ActionBarOverlayLayout.draw(ActionBarOverlayLayout.java:501)
at android.view.View.updateDisplayListIfDirty(View.java:14048)
at android.view.View.getDisplayList(View.java:14071)
at android.view.View.draw(View.java:14838)
at android.view.ViewGroup.drawChild(ViewGroup.java:3404)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3198)
at android.view.View.draw(View.java:15117)
at android.widget.FrameLayout.draw(FrameLayout.java:592)
at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:2595)
at android.view.View.updateDisplayListIfDirty(View.java:14048)
at android.view.View.getDisplayList(View.java:14071)
at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:266)
at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:272)
at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:311)
at android.view.ViewRootImpl.draw(ViewRootImpl.java:2492)
at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2337)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1968)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1054)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5779)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767)
at android.view.Choreographer.doCallbacks(Choreographer.java:580)
at android.view.Choreographer.doFrame(Choreographer.java:550)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5221)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)

Quick Return broken when calling ListView.onRestoreInstanceState(state)

if we initialize Quick Return with the listview and then call listview.onRestoreInstanceState(state) which will make the list view restore it previous instance (scroll to last value). The QuickReturnTarget will become unstable and will hide/show randomly when scroll up or down.

Anyone has solution for this?

onItemClick wrong position

Hi @felipecsl

Maybe I'm wrong, but I think OnItemClickListener works incorrect:
position=0 for header
position=1 for first list item

So, should I manually decrement position into the onItemClick()?

onclick

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.