GithubHelp home page GithubHelp logo

recyclerbanner's Introduction

RecyclerBanner

介绍

RecyclerBanner是一个利用RecycleView实现轮播图的自定义控件。

这里有相关博客介绍!

属性

属性名称  方法 意义 类型 默认值
app:showIndicator setShowIndicator(boolean showIndicator) 是否显示指示器 boolean true
app:interval setAutoPlayDuration(int autoPlayDuration) 轮播时间间隔 int 4000
app:isAutoPlaying setAutoPlaying(boolean isAutoPlaying) 是否开启自动轮播 boolean true
app:orientation setOrientation(int orientation) 轮播图方向 enum horizontal
app:itemSpace setItemSpace(int itemSpace) 图片间距 int 20
app:centerScale setCenterScale(float centerScale) 当前图片缩放比列 float 1.2
app:moveSpeed setMoveSpeed(float moveSpeed) 滚动速度,越大越快 float 1.0

效果如下图:

使用方法

设置一个带数据的RecyclerView.Adapter即可。

   <com.example.library.banner.BannerLayout
        android:id="@+id/recycler"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        app:autoPlaying="true"
        app:centerScale="1.3"
        app:itemSpace="20"
        app:moveSpeed="1.8"/>

BannerLayout  recyclerBanner =  findViewById(R.id.recycler);
bannerVertical =  findViewById(R.id.recycler_ver);

  List<String> list = new ArrayList<>();
        list.add("http://img0.imgtn.bdimg.com/it/u=1352823040,1166166164&fm=27&gp=0.jpg");
        list.add("http://img3.imgtn.bdimg.com/it/u=2293177440,3125900197&fm=27&gp=0.jpg");
        list.add("http://img3.imgtn.bdimg.com/it/u=3967183915,4078698000&fm=27&gp=0.jpg");
        list.add("http://img0.imgtn.bdimg.com/it/u=3184221534,2238244948&fm=27&gp=0.jpg");
        list.add("http://img4.imgtn.bdimg.com/it/u=1794621527,1964098559&fm=27&gp=0.jpg");
        list.add("http://img4.imgtn.bdimg.com/it/u=1243617734,335916716&fm=27&gp=0.jpg");
WebBannerAdapter webBannerAdapter=new WebBannerAdapter(this,list);
webBannerAdapter.setOnBannerItemClickListener(new BannerLayout.OnBannerItemClickListener() {
            @Override
            public void onItemClick(int position) {
                Toast.makeText(MainActivity.this, "点击了第  " + position+"  项", Toast.LENGTH_SHORT).show();
            }
        });
recyclerBanner.setAdapter(webBannerAdapter);

License

 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.

致谢

ViewPagerLayoutManager 使用了部分代码

recyclerbanner's People

Contributors

ren93 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  avatar  avatar  avatar  avatar  avatar

recyclerbanner's Issues

onCreateViewHolder

HI,你好啊。 我这边的日志发现,onCreateViewHolder执行了 好多次 ;
我记得,adapter 的oncreate方法,不应该执行这么多次的,有时间的话,你可以看一下啦;
比如我的 adapter.list 有120个,这么多;

    @Override
    public WebBannerAdapter.MzViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        LogTrack.i("create  "+(createCount++));
        return new MzViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_image, parent, false));
    }

执行了 好多次

2018-11-16 14:25:29.784 26475-26475/com.renny.recyclerbanner I/LogTrack: [ (WebBannerAdapter.java:43) #onCreateViewHolder] create  0
2018-11-16 14:25:29.792 26475-26475/com.renny.recyclerbanner I/LogTrack: [ (WebBannerAdapter.java:49) #onBindViewHolder] bind 0
2018-11-16 14:25:29.816 26475-26475/com.renny.recyclerbanner I/LogTrack: [ (WebBannerAdapter.java:43) #onCreateViewHolder] create  1

...
2018-11-16 14:25:55.410 26475-26475/com.renny.recyclerbanner I/LogTrack: [ (WebBannerAdapter.java:49) #onBindViewHolder] bind 118
2018-11-16 14:25:55.709 26475-26475/com.renny.recyclerbanner I/LogTrack: [ (WebBannerAdapter.java:43) #onCreateViewHolder] create  121
2018-11-16 14:25:55.711 26475-26475/com.renny.recyclerbanner I/LogTrack: [ (WebBannerAdapter.java:49) #onBindViewHolder] bind 119

发现BannerLayoutManager十分耗资源问题

目前排查不到,发现view在滑动时是会不停刷,我把你的mavager用到子多类型布局中,而且布局里面的数据还会不停变,发现用原生的manager,数据加载和数据更新都没问题,但是换成这个manager之后数据的刷新就有问题了。

Image Selected Not Rounded

whatsapp image 2018-06-26 at 12 19 50 pm
if you can see image selected not rounded.

this is my code : xml
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="250dp" android:layout_height="250dp" android:background="@color/bgwhite" app:cardCornerRadius="10dp"> <ImageView android:id="@+id/image" android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="centerCrop" /> </android.support.v7.widget.CardView>

this is java code:

`private BannerLayout bannerLayout;
private HomeBannerAdapter homeBannerAdapter;

  bannerLayout = (BannerLayout)v.findViewById(R.id.recycler);

    List<Integer>list = new ArrayList<>();
    list.add(R.mipmap.pic1);
    list.add(R.mipmap.pic2);
    list.add(R.mipmap.pic3);
    list.add(R.mipmap.pic4);

    homeBannerAdapter = new HomeBannerAdapter(getActivity(), list);
    homeBannerAdapter.setOnBannerItemClickListener(new BannerLayout.OnBannerItemClickListener() {
        @Override
        public void onItemClick(int position) {

        }
    });
    bannerLayout.setShowIndicator(false);
    bannerLayout.setAdapter(homeBannerAdapter);`

my adapter :

`public class HomeBannerAdapter extends RecyclerView.Adapter<HomeBannerAdapter.MzViewHolder> {

private Context context;
private List<Integer> urlList;
private BannerLayout.OnBannerItemClickListener onBannerItemClickListener;

public HomeBannerAdapter(Context context, List<Integer> urlList) {
    this.context = context;
    this.urlList = urlList;
}

public void setOnBannerItemClickListener(BannerLayout.OnBannerItemClickListener onBannerItemClickListener) {
    this.onBannerItemClickListener = onBannerItemClickListener;
}

@Override
public HomeBannerAdapter.MzViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    return new MzViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_home_image, parent, false));
}

@Override
public void onBindViewHolder(HomeBannerAdapter.MzViewHolder holder, final int position) {
    if (urlList == null || urlList.isEmpty())
        return;
    final int P = position % urlList.size();
    //String url = urlList.get(P);
    ImageView img = (ImageView) holder.imageView;

    Picasso.get().load(urlList.get(P)).into(img);
    img.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (onBannerItemClickListener != null) {
                onBannerItemClickListener.onItemClick(P);
            }

        }
    });
}

@Override
public int getItemCount() {
    if (urlList != null) {
        return urlList.size();
    }
    return 0;
}


class MzViewHolder extends RecyclerView.ViewHolder {
   ImageView imageView;

    MzViewHolder(View itemView) {
        super(itemView);
        imageView = (ImageView) itemView.findViewById(R.id.image);
    }
}

}`

this is bannerlayout code:

`public class BannerLayout extends FrameLayout {

private int autoPlayDuration; // refresh interval

private boolean showIndicator; // Whether indicator is displayed
private RecyclerView indicatorContainer;
private Drawable mSelectedDrawable;
private Drawable mUnselectedDrawable;
private IndicatorAdapter indicatorAdapter;
private   int indicatorMargin; // indicator spacing
private RecyclerView mRecyclerView;

private  BannerLayoutManager mLayoutManager;

private int WHAT_AUTO_PLAY = 1000;

private boolean hasInit;
private int bannerSize = 1;
private int currentIndex;
private boolean isPlaying = false;

private boolean isAutoPlaying = true;
int itemSpace;
float centerScale;
float moveSpeed;
protected Handler mHandler = new Handler(new Handler.Callback() {
    @Override
    public boolean handleMessage(Message msg) {
        if (msg.what == WHAT_AUTO_PLAY) {
            if (currentIndex == mLayoutManager.getCurrentPosition()) {
                ++currentIndex;
                mRecyclerView.smoothScrollToPosition(currentIndex);
                mHandler.sendEmptyMessageDelayed(WHAT_AUTO_PLAY, autoPlayDuration);
                refreshIndicator();
            }
        }
        return false;
    }
});

public BannerLayout(Context context) {
    this(context, null);
}

public BannerLayout(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
}

public BannerLayout(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    initView(context, attrs);
}

protected void initView(Context context, AttributeSet attrs) {

    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.BannerLayout);
    showIndicator = a.getBoolean(R.styleable.BannerLayout_showIndicator, true);
    autoPlayDuration = a . getInt ( R . styleable . BannerLayout_interval , 4000 );
    isAutoPlaying = a.getBoolean(R.styleable.BannerLayout_autoPlaying, true);
    itemSpace = a.getInt(R.styleable.BannerLayout_itemSpace, 20);
    centerScale = a.getFloat(R.styleable.BannerLayout_centerScale, 1.2f);
    moveSpeed = a.getFloat(R.styleable.BannerLayout_moveSpeed, 1.0f);
    if (mSelectedDrawable == null) {
        // draw the default selected state graphic
        GradientDrawable selectedGradientDrawable = new GradientDrawable();
        selectedGradientDrawable.setShape(GradientDrawable.OVAL);
        selectedGradientDrawable.setColor(Color.RED);
        selectedGradientDrawable.setSize(dp2px(5), dp2px(5));
        selectedGradientDrawable.setCornerRadius(dp2px(5) / 2);
        mSelectedDrawable = new LayerDrawable(new Drawable[]{selectedGradientDrawable});
    }
    if (mUnselectedDrawable == null) {
        // draw the default unselected state graphics
        GradientDrawable unSelectedGradientDrawable = new GradientDrawable();
        unSelectedGradientDrawable.setShape(GradientDrawable.OVAL);
        unSelectedGradientDrawable.setColor(Color.GRAY);
        unSelectedGradientDrawable.setSize(dp2px(5), dp2px(5));
        unSelectedGradientDrawable.setCornerRadius(dp2px(5) / 2);
        mUnselectedDrawable = new LayerDrawable(new Drawable[]{unSelectedGradientDrawable});
    }

    indicatorMargin = dp2px(4);
    int marginLeft = dp2px(16);
    int marginRight = dp2px(0);
    int marginBottom = dp2px(11);
    int gravity = GravityCompat.START;
    int o = a.getInt(R.styleable.BannerLayout_orientation, 0);
    int orientation = 0;
    if (o == 0) {
        orientation = OrientationHelper.HORIZONTAL;
    } else  if (o ==  1 ) {
        orientation = OrientationHelper.VERTICAL;
    }
    a.recycle();
    // Carousel section
    mRecyclerView = new RecyclerView(context);
    LayoutParams vpLayoutParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.MATCH_PARENT);
    addView(mRecyclerView, vpLayoutParams);
    mLayoutManager = new BannerLayoutManager(getContext(), orientation);
    mLayoutManager.setItemSpace(itemSpace);
    mLayoutManager.setCenterScale(centerScale);
    mLayoutManager.setMoveSpeed(moveSpeed);
    mRecyclerView . setLayoutManager (mLayoutManager);
    new CenterSnapHelper().attachToRecyclerView(mRecyclerView);


    // indicator section
    indicatorContainer = new RecyclerView(context);
    LinearLayoutManager indicatorLayoutManager = new LinearLayoutManager(context, orientation, false);
    indicatorContainer . setLayoutManager (indicatorLayoutManager);
    indicatorAdapter = new IndicatorAdapter();
    indicatorContainer . setAdapter (indicatorAdapter);
    LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
            ViewGroup.LayoutParams.WRAP_CONTENT);
    params.gravity = Gravity.BOTTOM | gravity;
    params.setMargins(marginLeft, 0, marginRight, marginBottom);
    addView(indicatorContainer, params);
    if (!showIndicator) {
        indicatorContainer.setVisibility(GONE);
    }
}

// Set whether to prohibit scrolling
public void setAutoPlaying(boolean isAutoPlaying) {
    this.isAutoPlaying = isAutoPlaying;
    setPlaying(this.isAutoPlaying);
}

public boolean isPlaying() {
    return isPlaying;
}

// Set whether to display the indicator
public void setShowIndicator(boolean showIndicator) {
    this.showIndicator = showIndicator;
    indicatorContainer.setVisibility(showIndicator ? VISIBLE : GONE);
}

// Set the current image scaling factor
public void setCenterScale(float centerScale) {
    this.centerScale = centerScale;
    mLayoutManager.setCenterScale(centerScale);
}

// Set the speed of following the finger
public void setMoveSpeed(float moveSpeed) {
    this.moveSpeed = moveSpeed;
    mLayoutManager.setMoveSpeed(moveSpeed);
}

// Set the picture spacing
public  void  setItemSpace ( int  itemSpace ) {
    this.itemSpace = itemSpace;
    mLayoutManager.setItemSpace(itemSpace);
}

/**
 * Set the rotation interval
 *
 * @param autoPlayDuration time milliseconds
 */
public  void  setAutoPlayDuration ( int  autoPlayDuration ) {
    this.autoPlayDuration = autoPlayDuration;
}

public void setOrientation(int orientation) {
    mLayoutManager.setOrientation(orientation);
}

/**
 * Set whether to play automatically (locked)
 *
 * @param playing Start playing
 */
protected synchronized void setPlaying(boolean playing) {
    if (isAutoPlaying && hasInit) {
        if (!isPlaying && playing) {
            mHandler.sendEmptyMessageDelayed(WHAT_AUTO_PLAY, autoPlayDuration);
            isPlaying = true;
        } else if (isPlaying && !playing) {
            mHandler.removeMessages(WHAT_AUTO_PLAY);
            isPlaying = false;
        }
    }
}


/**
 * Set carousel data set
 */
public void setAdapter(RecyclerView.Adapter adapter) {
    hasInit = false;
    mRecyclerView.setAdapter(adapter);
    bannerSize = adapter . getItemCount ();
    mLayoutManager.setInfinite(bannerSize >= 3);
    setPlaying(true);
    mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {

        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            if (dx != 0) {
                setPlaying(false);
            }
        }

        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
            int first = mLayoutManager.getCurrentPosition();
            Log.d("xxx", "onScrollStateChanged");
            if (currentIndex != first) {
                currentIndex = first;
            }
            if (newState == SCROLL_STATE_IDLE) {
                setPlaying(true);
            }
            refreshIndicator();
        }
    });
    hasInit = true;
}

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    switch (ev.getAction()) {
        case MotionEvent.ACTION_DOWN:
            setPlaying(false);
            break;
        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_CANCEL:
            setPlaying(true);
            break;
    }
    return super.dispatchTouchEvent(ev);
}

@Override
protected void onAttachedToWindow() {
    super.onAttachedToWindow();
    setPlaying(true);
}

@Override
protected void onDetachedFromWindow() {
    super.onDetachedFromWindow();
    setPlaying(false);
}

@Override
protected void onWindowVisibilityChanged(int visibility) {
    super.onWindowVisibilityChanged(visibility);
    if (visibility == VISIBLE) {
        setPlaying(true);
    } else {
        setPlaying(false);
    }
}

/**
 * Marking point adapter
 */
protected class IndicatorAdapter extends RecyclerView.Adapter {

    int currentPosition = 0;

    public void setPosition(int currentPosition) {
        this.currentPosition = currentPosition;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        ImageView bannerPoint = new ImageView(getContext());
        RecyclerView.LayoutParams lp = new RecyclerView.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.WRAP_CONTENT);
        lp.setMargins(indicatorMargin, indicatorMargin, indicatorMargin, indicatorMargin);
        bannerPoint . setLayoutParams (lp);
        return new RecyclerView.ViewHolder(bannerPoint) {
        };
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        ImageView bannerPoint = (ImageView) holder.itemView;
        bannerPoint.setImageDrawable(currentPosition == position ? mSelectedDrawable : mUnselectedDrawable);

    }

    @Override
    public int getItemCount() {
        return bannerSize;
    }
}

protected int dp2px(int dp) {
    return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
            Resources.getSystem().getDisplayMetrics());
}

/**
 * Change instruction points for navigation
 */
protected synchronized void refreshIndicator() {
    if (showIndicator && bannerSize > 1) {
        indicatorAdapter.setPosition(currentIndex % bannerSize);
        indicatorAdapter.notifyDataSetChanged();
    }
}

public interface OnBannerItemClickListener {
    void  onItemClick ( int  position );
}

}
`

性能问题

如果recyclerview的getItemCount设置成Integer.MAX_VALUE,会不会导致程序所占内存偏大甚至内存泄漏问题。

左滑动有bug

老哥,你这个demo有个bug,向左滑动时有时会滑动好几张,我用这个到项目中时,不知道怎么回事有时向左一下滑动4,5张,根本停不下来,,

滑动问题

快速滑动情况下,banner也会快速滑动,不能每次只滑动一个item,指示圆点也只会在停止滑动时候才会定位到准确位置,体验不是很好

样式有问题,偶尔会变形

# 左右滑动一会偶现样式变形,左右间距不对
不知道怎么贴上手机截图,我这边有变形的截图,这是一个很大的bug

如何每次只滑动一张

你好,3D效果如何设置每次滑动只能滑动一张,demo里可以滑动很多张,我通过设置滑动速度,但是效果不好

可以增加个改变滑动速度的方法

@OverRide
public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) {
LinearSmoothScroller linearSmoothScroller = new LinearSmoothScroller(recyclerView.getContext()) {

        //This returns the milliseconds it takes to
        //scroll one pixel.
        @Override
        protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
            return MILLISECONDS_PER_INCH / displayMetrics.density;
        }
    };
    linearSmoothScroller.setTargetPosition(position);
    startSmoothScroll(linearSmoothScroller);
}

public void setSpeedSlow() {
MILLISECONDS_PER_INCH = context.getResources().getDisplayMetrics().density * 0.7f;
}

我在BannerLayoutManager加了滑动速度控制的方法,但是
在图片快滑动到最中间时,会突然加快一下,找不出原因,大神帮忙看下原因

横向左滑有bug

这个项目是自动轮播图,如果不滑动recycleview则不会回调mRecyclerView.addOnScrollListener而是直接进入handler处理。
左滑滑动的item毫无规律,有时先向右滑几张然后再向左滑动几张,有时一直在滑动,停不下来,debug追踪下代码,发现问题出在:
@OverRide
public int scrollHorizontallyBy(int dx, RecyclerView.Recycler recycler, RecyclerView.State state) {
Log.i(TAG,"dx "+dx);
if (mOrientation == VERTICAL) {
return 0;
}
return scrollBy(dx, recycler, state);
}
右滑的时候dx值返回正常,左滑的时候dx会不断的输出值而且有正数有负数,而这个方法是重写LayoutManager的方法,这个项目并没有对dx这个值做处理,推测可能是LayoutManager的问题
大神看下这个问题是什么原因造成的?

IndexOutOfBoundsException

cn.com.zhiyihealth.s1.Ui.banner.BannerLayoutManager.layoutItems(BannerLayoutManager.java:684)

5 cn.com.zhiyihealth.s1.Ui.banner.BannerLayoutManager.scrollBy(BannerLayoutManager.java:631)
6 cn.com.zhiyihealth.s1.Ui.banner.BannerLayoutManager.scrollHorizontallyBy(BannerLayoutManager.java:595) 我在banner 滑动的时候下载完数据 重新setlist

使用layoutmanager出现的问题

我现在只使用了BannerLayoutManager,recyclerview和adapter是自己写的。但是就没办法有图片放大效果。图片被裁剪了。但我在item中margintop 一段位移后,就能够有放大效果。这个是为什么呢
image

>เฝะจื

นำบ่ขวะ

_Originally posted by @buornhnufnofnำบ้งฝงพ

请问,左右两边的item可以不设置倾斜吗?如何进行控制了?

OverFlyingLayoutManager本身支持数据的无限滚动,数据加载完成之后,默认选择index=0的位置居中,index=1(第二个item)显示在左侧,最后一个item显示在右侧;即数据都是由左向右排列的
请问,是否可以由右向左排列,实现向左滑出现最后一条,向右滑出现下一条;
求解答~~

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.