enable users to slide card to the left or right smoothly and continuously

Overview

有图有真相

模仿探探首页的卡片滑动效果:

preview 不得不说,探探的ui效果真的很赞。在着手这个project之前,我没有参考过github上其它类似的开源项目。所以,如果这个project重复造了轮子,请不要打我。

在这个仓库竣工之时,有一个小伙伴发了我另一个开源工程,颇有相似之处。我下载了源码,导入了studio,apk跑起来的时候,发现它存在一些问题:卡片飞到两侧,如果动画没有结束,则不允许下一轮拖动。这对强迫症的用户来说,应该是很不爽的。

然而,探探却克服了所有这些问题。或许,这个问题只有积淀过这些知识点的人才能琢磨的透吧。我确实思考了很久,想到了一个还不错的方案。

无耻一点

如果我能不要脸一些,我会说这个项目有以下优点:

  • 快。真的流畅,滑动的手速再快也赶不上代码刷新view的速度快。
  • 高效。仅仅四个卡片view轻松搞定任意多的数据。
  • 灵活。自定义ViewGroup对卡片view的高度实现了自适应。
  • 细节。卡片之间联动的视觉效果,是像素级的精确。

不信,你下载下来look look。

使用方法

1. 在xml文件中引入CardSlidePanel

<com.stone.card.library.CardSlidePanel
        android:id="@+id/image_slide_panel"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        card:bottomMarginTop="38dp"
        card:itemMarginTop="10dp"
        card:yOffsetStep="13dp" />

2. 左右滑动监听

cardSwitchListener = new CardSlidePanel.CardSwitchListener() {

        @Override
        public void onShow(int index) {
            Log.d("Card", "正在显示-" + dataList.get(index).userName);
        }

        @Override
        public void onCardVanish(int index, int type) {
            Log.d("Card", "正在消失-" + dataList.get(index).userName + " 消失type=" + type);
        }
};
slidePanel.setCardSwitchListener(cardSwitchListener);

3. 绑定Adapter

slidePanel.setAdapter(new CardAdapter() {
        @Override
        public int getLayoutId() {
            // layout文件
            return R.layout.card_item;
        }

        @Override
        public int getCount() {
            // 卡片个数
            return dataList.size();
        }
        
        @Override
        public Rect obtainDraggableArea(View view) {
            // 可滑动区域定制,仅调用一次
            return new Rect(....)
        }

        @Override
        public void bindView(View view, int index) {
            // 数据绑定,参看demo
            viewHolder.bindData(dataList.get(index));
        }
});

4. 数据更新

// appendDataList
adapter.notifyDataSetChanged();

Demo安装包

apk download (就在thisProj工程之中)

License

Copyright 2016, xmuSistone

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Comments
  • 港真,发现一个问题

    港真,发现一个问题

    “无耻一点

    如果我能不要脸一些,我会说这个项目有以下优点:

    快。真的流畅,滑动的手速再快也赶不上代码刷新view的速度快。 高效。仅仅四个卡片view轻松搞定任意多的数据。 灵活。自定义ViewGroup对卡片view的高度实现了自适应。 细节。卡片之间联动的视觉效果,是像素级的精确。 不信,你下载下来look看看。”

    最后这句话“不信,你下载下来look看看。”是个病句哇,如果翻译的话:不信,你下载下来看看看看。。。这个很显然不符合本项目的文风呐。。所以是不是可以考虑改成“不信,你下载下来look look”。。。

    opened by hidetag 29
  • How  add CardItemView dinamically

    How add CardItemView dinamically

    Hi I'm using your library.I have one question.Is it a possible to add dinamically CardItemView view in CardSlidePanel.In this example you use static array,but i have json and different size array. I tried to remove some elements in you arrayList ,but i have IndexOf exceplion

    opened by Bekakk 21
  • How can we achieve different view types in this?

    How can we achieve different view types in this?

    I tried like this but my new view is null-

    ` slidePanel.setAdapter(new CardAdapter() { @Override public int getLayoutId(int index) { if (dataList.get(index).imagePath == null) { return R.layout.gads; } else { return R.layout.card_item; }

            }
    
            @Override
            public int getCount() {
                return dataList.size();
            }
    
            @Override
            public void bindView(View view, int index) {
                if (dataList.get(index).imagePath == null) {
                    AdViewHolder adViewHolder;
                    adViewHolder = new AdViewHolder(view);
                    AdRequest request = new AdRequest.Builder().build();
                    if (adViewHolder.adView != null) {
                        adViewHolder.adView.loadAd(request);
                        adViewHolder.adView.setAdListener(new AdListener() {
                            @Override
                            public void onAdFailedToLoad(int i) {
                                super.onAdFailedToLoad(i);
                            }
    
                            @Override
                            public void onAdLeftApplication() {
                                super.onAdLeftApplication();
                            }
    
                            @Override
                            public void onAdLoaded() {
                                super.onAdLoaded();
                            }
                        });
                    }
    
                } else {
                    Object tag = view.getTag();
                    ViewHolder viewHolder;
                    if (null != tag) {
                        viewHolder = (ViewHolder) tag;
                    } else {
                    viewHolder = new ViewHolder(view);
                        view.setTag(viewHolder);
                    }
    
                    viewHolder.bindData(dataList.get(index));
                }
    
            }
    
            @Override
            public Object getItem(int index) {
                return dataList.get(index);
            }
    
            @Override
            public Rect obtainDraggableArea(View view) {
                // 可滑动区域定制,该函数只会调用一次
                View contentView = view.findViewById(R.id.card_item_content);
                View topLayout = view.findViewById(R.id.card_top_layout);
                View bottomLayout = view.findViewById(R.id.card_bottom_layout);
                int left = view.getLeft() + contentView.getPaddingLeft() + topLayout.getPaddingLeft();
                int right = view.getRight() - contentView.getPaddingRight() - topLayout.getPaddingRight();
                int top = view.getTop() + contentView.getPaddingTop() + topLayout.getPaddingTop();
                int bottom = view.getBottom() - contentView.getPaddingBottom() - bottomLayout.getPaddingBottom();
                return new Rect(left, top, right, bottom);
            }
        });`
    
    opened by SkyTreasure 4
  • 关于计算消失finalY点的疑惑.

    关于计算消失finalY点的疑惑.

    childWith + changedView.getLeft() --> 不是很清楚具体的含义.

    //这里是向左消失的计算. finalY = yvel * (childWith + changedView.getLeft()) / (-xvel) + changedView.getTop()

    我这里换成了这样. 因为 X,Y 消失消耗时间一致. yvel / xvel = dy / dx finalY = changedView.getTop() + dx * yvel / xvel; 也就是. finalY = yvel * changedView.getRight() / (-xvel) + changedView.getTop();

    测试后发现这种算法也能完美运行.但是finalY是不一样的..这就疑惑了..到底哪个才比较合适?

    opened by pinkApple 4
  • How can i show 4 cards at a time instead of 3?

    How can i show 4 cards at a time instead of 3?

    I'm trying to show 4 cards at a time by changing VIEW_COUNT = 5. VIEW_COUNT is inside the class CardSlidePanel. But nothing is changing but if i'm assigning it as 3 or 2, it works well. Any help will be appreciated.

    opened by sachinvarma 0
  • 一个bug

    一个bug

    https://github.com/xmuSistone/CardSlidePanel/blob/70dab2540745c39bfef805c4621b52ebfb85fc97/CardSlidePanel/library/src/main/java/com/stone/card/library/CardSlidePanel.java#L226-L234 这里要改成index + 2 >= viewList.size(),否则调用processLinkageView(changedView);的时候ajustLinkageViewItem(changedView, rate2, 2); 会数组越界

    opened by Nstd 0
  • 数据加载问题

    数据加载问题

    每次划完了,重新给集合里添加数据,就会数组越界

    java.lang.IndexOutOfBoundsException: Index: 4, Size: 4 at java.util.ArrayList.get(ArrayList.java:411) at com.SimpleDate.FaMy.ui.view.tantan.CardSlidePanel.onLayout(CardSlidePanel.java:499) at android.view.View.layout(View.java:18878) at android.view.ViewGroup.layout(ViewGroup.java:5953) at android.support.design.widget.HeaderScrollingViewBehavior.layoutChild(HeaderScrollingViewBehavior.java:132) at android.support.design.widget.ViewOffsetBehavior.onLayoutChild(ViewOffsetBehavior.java:42) at android.support.design.widget.AppBarLayout$ScrollingViewBehavior.onLayoutChild(AppBarLayout.java:1361) at android.support.design.widget.CoordinatorLayout.onLayout(CoordinatorLayout.java:894) at android.view.View.layout(View.java:18878)

    opened by HalyangDream 2
  • Semi-transparent cards!

    Semi-transparent cards!

    Why are some cards semi-transparent? That is, their back cards are revealed http://www.upsara.com/images/ysbg_screenshot_1508184174.png http://www.upsara.com/images/vvbr_cap2ture.png http://www.upsara.com/images/lukm_screenshot_1508184195.png

    This problem does not exist in the demo file. But with the implementation of your project, there is such a problem without any changes!

    opened by Omid-naji 9
Owner
stone
Just go ahead.
stone
Viacheslav Veselov 0 Jul 8, 2022
Android sample app following best practices: Kotlin, Compose, Coroutines and Flow, Hilt, JetPack Navigation, ViewModel, MVVM and MVI, Retrofit, Coil

Foodies - Modern Android Architecture Foodies is a sample project that presents a modern 2021 approach to Android app development. The project tries t

null 362 Jan 2, 2023
🧸 A demo Disney app using Jetpack Compose and Hilt based on modern Android tech stacks and MVVM architecture.

DisneyCompose A demo Disney app using compose and Hilt based on modern Android tech-stacks and MVVM architecture. Fetching data from the network and i

Jaewoong Eum 791 Dec 30, 2022
A sample Android application with a strong focus on a clean architecture, automated unit and UI testing and continuous integration.

Android playground This is a sample Android application with a strong focus on a clean architecture, automated unit and UI testing and continuous inte

null 6 Jun 4, 2022
OpenPacketSniffer - Monitors and handles network packets sent and received to/from a host

Packet Sniffer Monitors network activity and logs all packets that have been sent/received by the client's host. Settings In Main.kt, the PcapHandler

Neel 0 Jan 5, 2022
Do's and Don'ts for Android development, by Futurice developers

Best practices in Android development Avoid reinventing the wheel by following these guidelines. Lessons learned from Android developers in Futurice.

Futurice 20.2k Dec 31, 2022
Movie discovery app showcasing MVP, RxJava, Dagger 2 and Clean Architecture

MovieGuide ?? Refactoring in progress ??‍♀️ ⛏ ?? ??️ ?? ?? ?? Comments and new issues are welcome. ?? Currently not accepting external PRs that touch

Arun Sasidharan 2.6k Dec 25, 2022
Basic example of using ItemTouchHelper to add drag & drop and swipe-to-dismiss to RecyclerView.

Another drag and swipe library? This project is an example of basic drag & drop and swipe-to-dismiss with RecyclerView using ItemTouchHelper. It corre

Paul Burke 2.5k Dec 24, 2022
A simple chat demo for socket.io and Android

socket.io-android-chat This is a simple chat demo for socket.io and Android. You can connect to https://socket-io-chat.now.sh using this app. Installa

Naoyuki Kanezawa 1.9k Dec 30, 2022
A simple app to showcase Androids Material Design and some of the cool new cool stuff in Android Lollipop. RecyclerView, CardView, ActionBarDrawerToggle, DrawerLayout, Animations, Android Compat Design, Toolbar

#Android-LollipopShowcase This is a simple showcase to show off Android's all new Material Design and some other cool new stuff which is (new) in Andr

Mike Penz 1.8k Nov 10, 2022
Android common lib demo, include ImageCache, HttpCache, DropDownListView, DownloadManager, install apk silent and so on, you can find description

android-demo 关于我,欢迎关注 微博:Trinea 主页:trinea.cn 邮箱:trinea.cn#gmail.com 微信:codek2 依赖:trinea-android-common android-auto-scroll-view-pager viewpager-indica

Trinea 1.1k Nov 10, 2022
📚 Sample Android Components Architecture on a modular word focused on the scalability, testability and maintainability written in Kotlin, following best practices using Jetpack.

Android Components Architecture in a Modular Word Android Components Architecture in a Modular Word is a sample project that presents modern, 2020 app

Madalin Valceleanu 2.3k Dec 30, 2022
Sample application demonstrating Android design and animation

android-movies-demo This is a sample application showing off some interesting design/development interactions for a talk given at Droidcon 2013. As it

Daniel Lew 359 Jan 1, 2023
This repo contains example code for O'Reilly's "Programming Android" by Zigured Mednieks, Laird Dornin, Blake Meike and Masumi Nakamura

This repo contains working code for the example in O'Reilly's _Programming Android, 2nd Edition_; Mednieks, Dornin, Meike, Nakamura (http://shop.orei

G. Blake Meike 214 Nov 25, 2022
[] Port of Jake Wharton's U2020 sample app with use of MVP and Dagger 2

U+2020-mvp [DEPRECATED] We recomend to try Moxy framework instead of our solution. Port of Jake Wharton's U2020 sample app with use of MVP pattern and

Live Typing 315 Nov 14, 2022
This repo contains example code for O'Reilly's "Programming Android" by Zigured Mednieks, Laird Dornin, Blake Meike and Masumi Nakamura

This repo contains working code for the example in O'Reilly's _Programming Android, 2nd Edition_; Mednieks, Dornin, Meike, Nakamura (http://shop.orei

G. Blake Meike 165 Nov 11, 2022
A simple app to showcase Androids Material Design and some of the cool new cool stuff in Android Lollipop. RecyclerView, CardView, ActionBarDrawerToggle, DrawerLayout, Animations, Android Compat Design, Toolbar

#Android-LollipopShowcase This is a simple showcase to show off Android's all new Material Design and some other cool new stuff which is (new) in Andr

Mike Penz 1.8k Nov 10, 2022
A demo of the power menu with Reveal and other animations

MaterialPowerMenu A demo of the power menu with Reveal and other animations Some days ago, I saw a gif on Google+ demonstating a concept of Android Po

Naman Dwivedi 888 Oct 11, 2022
How to apply meaningful and delightful motion in a sample Android app

Applying meaningful motion on Android How to apply meaningful and delightful motion in a sample Android app Read the complete post at https://medium.c

André Mion 167 Dec 19, 2022