Android进阶 — GitHub开源控件的使用合集

1、QuantityView 类似购物车数量调节:

效果图:

项目在GitHub上的地址:

https://github.com/himanshu-soni/QuantityView

项目使用:

在gradle中添加

compile ‘me.himanshusoni.quantityview:quantity-view:1.1.3‘

在XML中添加布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:background="@color/md_white_1000"
    android:orientation="vertical"
    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=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Default"
        android:textAppearance="?android:textAppearanceLarge" />

    <me.himanshusoni.quantityview.QuantityView
        android:id="@+id/quantityView_default"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        app:qv_quantity="10" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:text="Custom 1"
        android:textAppearance="?android:textAppearanceLarge" />

    <me.himanshusoni.quantityview.QuantityView
        android:id="@+id/quantityView_custom_1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        app:qv_addButtonText="ADD MORE"
        app:qv_addButtonTextColor="@color/md_green_500"
        app:qv_maxQuantity="20"
        app:qv_quantity="15"
        app:qv_removeButtonText="REMOVE"
        app:qv_removeButtonTextColor="@color/md_red_500" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:text="Custom 2"
        android:textAppearance="?android:textAppearanceLarge" />

    <me.himanshusoni.quantityview.QuantityView
        android:id="@+id/quantityView_custom_2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        app:qv_addButtonBackground="@drawable/add_selector"
        app:qv_addButtonTextColor="@color/md_white_1000"
        app:qv_quantity="20"
        app:qv_removeButtonBackground="@drawable/remove_selector"
        app:qv_removeButtonTextColor="@color/md_white_1000" />

</LinearLayout>

Java中的使用代码:

public class SlideDateTimeActivity extends FragmentActivity {

    @Bind(R.id.button)
    Button button;

    private SimpleDateFormat mFormatter = new SimpleDateFormat("MMMM dd yyyy hh:mm aa");
    private Button mButton;

    private SlideDateTimeListener listener = new SlideDateTimeListener() {

        @Override
        public void onDateTimeSet(Date date) {
            Toast.makeText(SlideDateTimeActivity.this,
                    mFormatter.format(date), Toast.LENGTH_SHORT).show();
        }

        // Optional cancel listener
        @Override
        public void onDateTimeCancel() {
            Toast.makeText(SlideDateTimeActivity.this,
                    "Canceled", Toast.LENGTH_SHORT).show();
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_slide_date_time_picker);
        ButterKnife.bind(this);
        button.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                new SlideDateTimePicker.Builder(getSupportFragmentManager())
                        .setListener(listener)
                        .setInitialDate(new Date())
                        //.setMinDate(minDate)
                        //.setMaxDate(maxDate)
                        //.setIs24HourTime(true)
                        //.setTheme(SlideDateTimePicker.HOLO_DARK)
                        //.setIndicatorColor(Color.parseColor("#990000"))
                        .build()
                        .show();
            }
        });
    }

}

2、Justified 实现Textview和Edittext文字左右对齐。

效果图:

项目在GitHub上的地址:

https://github.com/programingjd/justified

项目使用:

在gradle中添加

compile ‘com.uncopt:android.justified:1.0‘

在XML中添加布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical"
    tools:context="com.zerom.mtest.Justifiedtextview">

    <me.biubiubiu.justifytext.library.JustifyTextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/margin_20"
        android:text="预览版目前已经包括Android Wear最新API,这些新API可以让开发者以语音的方式定制和扩展他们的通知。其提供的仿真器可用于预览包括方形和圆形可穿戴设备上出现的通知方式,与此同时,谷歌也希望在未来几个月内继续为Android Wear设备提供新的API和功能。" />

    <me.biubiubiu.justifytext.library.JustifyTextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/margin_20"
        android:text="Tests whether this string matches the given regularExpression. This method returns true only if the regular expression matches the entire input string. A common mistake is to assume that this method behaves like contains(CharSequence); if you want to match anywhere within the input string, you need to add .* to the beginning and end of your regular expression. See matches(String, CharSequence)." />

</LinearLayout>

3、android-shapeLoadingView实现高仿新版58 加载动画

效果图:

项目在GitHub上的地址:

https://github.com/zzz40500/android-shapeLoadingView

项目使用:

在gradle中添加

compile ‘com.github.zzz40500:android-shapeLoadingView:1.0.3.2‘

在XML中添加布局:

<?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:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    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=".ShapeLoadingctivity">

    <com.mingle.widget.LoadingView
        android:id="@+id/loadView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        app:loadingText="加载中..." />

</RelativeLayout>

4、SlideDateTimePicker实现时间选择器,可以选择年月日小时分钟

效果图:

项目在GitHub上的地址:

https://github.com/jjobes/SlideDateTimePicker

项目使用:

添加依赖包;

Java中的使用代码:

public class SlideDateTimeActivity extends FragmentActivity {

    @Bind(R.id.button)
    Button button;

    private SimpleDateFormat mFormatter = new SimpleDateFormat("MMMM dd yyyy hh:mm aa");
    private Button mButton;

    private SlideDateTimeListener listener = new SlideDateTimeListener() {

        @Override
        public void onDateTimeSet(Date date) {
            Toast.makeText(SlideDateTimeActivity.this,
                    mFormatter.format(date), Toast.LENGTH_SHORT).show();
        }

        // Optional cancel listener
        @Override
        public void onDateTimeCancel() {
            Toast.makeText(SlideDateTimeActivity.this,
                    "Canceled", Toast.LENGTH_SHORT).show();
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_slide_date_time_picker);
        ButterKnife.bind(this);
        button.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                new SlideDateTimePicker.Builder(getSupportFragmentManager())
                        .setListener(listener)
                        .setInitialDate(new Date())
                        //.setMinDate(minDate)
                        //.setMaxDate(maxDate)
                        //.setIs24HourTime(true)
                        //.setTheme(SlideDateTimePicker.HOLO_DARK)
                        //.setIndicatorColor(Color.parseColor("#990000"))
                        .build()
                        .show();
            }
        });
    }

}

5、Labelview实现标签功能,在控件上面展示斜的文字

效果图:

项目在GitHub上的地址:

https://github.com/linger1216//labelview

项目使用:

在gradle中添加

compile ‘com.github.linger1216:labelview:v1.1.0‘

在XML中添加布局:

<ScrollView 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"
    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=".MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:orientation="vertical"
        android:layout_height="wrap_content">

        <com.lid.lib.LabelButtonView
            android:id="@+id/labelbutton"
            android:layout_width="200dp"
            android:layout_height="48dp"
            android:background="#03a9f4"
            android:gravity="center"
            android:text="Button"
            android:textColor="#ffffff"
            app:label_backgroundColor="#C2185B"
            app:label_distance="20dp"
            app:label_height="20dp"
            app:label_orientation="RIGHT_TOP"
            app:label_text="HD"
            app:label_textSize="12sp" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="24dp">

            <com.lid.lib.LabelImageView
                android:id="@+id/image1"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:scaleType="centerCrop"
                android:src="@mipmap/image1"
                app:label_backgroundColor="#C2185B"
                app:label_orientation="LEFT_TOP"
                app:label_text="CHINA" />

            <com.lid.lib.LabelImageView
                android:id="@+id/image2"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:scaleType="centerCrop"
                android:src="@mipmap/image2"
                app:label_backgroundColor="#C2185B"
                app:label_orientation="RIGHT_TOP"
                app:label_text="KUNQU" />
        </LinearLayout>

        <com.lid.lib.LabelTextView
            android:id="@+id/text"
            android:layout_width="wrap_content"
            android:layout_height="48dp"
            android:layout_gravity="center"
            android:layout_marginTop="8dp"
            android:background="#212121"
            android:gravity="center"
            android:padding="16dp"
            android:text="TextView"
            android:textColor="#ffffff"
            app:label_backgroundColor="#03A9F4"
            app:label_distance="15dp"
            app:label_orientation="LEFT_TOP"
            app:label_text="POP"
            app:label_textSize="10sp" />

        <com.lid.lib.LabelButtonView
            android:id="@+id/click"
            android:layout_width="match_parent"
            android:layout_height="48dp"
            android:layout_gravity="center_horizontal"
            android:layout_marginTop="8dp"
            android:background="#E91E63"
            android:gravity="center"
            android:text="ListView demo"
            android:textColor="#ffffff"
            app:label_backgroundColor="#03A9F4"
            app:label_distance="15dp"
            app:label_orientation="RIGHT_TOP"
            app:label_text="click"
            app:label_textSize="10sp" />

        <com.lid.lib.LabelButtonView
            android:id="@+id/click11"
            android:layout_width="match_parent"
            android:layout_height="48dp"
            android:layout_gravity="center_horizontal"
            android:layout_marginTop="8dp"
            android:background="#E91E63"
            android:gravity="center"
            android:text="recyclerview demo"
            android:textColor="#ffffff"
            app:label_backgroundColor="#03A9F4"
            app:label_distance="15dp"
            app:label_orientation="RIGHT_TOP"
            app:label_text="click"
            app:label_textSize="10sp" />

    </LinearLayout>

</ScrollView>

6、PullZoomView实现类似微信,下拉listview,顶部图片放大效果

项目在GitHub上的地址:

https://github.com/Frank-Zhu/PullZoomView

项目使用:

在gradle中添加

compile ‘com.github.frank-zhu:pullzoomview:1.0.0‘

在XML中添加布局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
    <com.zerom.mtest.parallaxListView.ParallaxScollListView
        android:id="@+id/layout_listview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:cacheColorHint="@null"
        android:duplicateParentState="true"
        android:scrollingCache="false"
        android:headerDividersEnabled="false"
        android:footerDividersEnabled="false"
        android:overScrollMode="never"
        android:scrollbars="none"
        />
</RelativeLayout>

Java中的代码:

ParallaxScollListView.class

public class ParallaxScollListView extends ListView implements AbsListView.OnScrollListener {

    public final static double NO_ZOOM = 1;
    public final static double ZOOM_X2 = 2;

    private ImageView mImageView;
    private int mDrawableMaxHeight = -1;
    private int mImageViewHeight = -1;
    private int mDefaultImageViewHeight = 0;
    private double mZoomRatio;

    private interface OnOverScrollByListener {
        public boolean overScrollBy(int deltaX, int deltaY, int scrollX,
                                    int scrollY, int scrollRangeX, int scrollRangeY,
                                    int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent);
    }

    private interface OnTouchEventListener {
        public void onTouchEvent(MotionEvent ev);
    }

    public ParallaxScollListView(Context context, AttributeSet attrs,
                                 int defStyle) {
        super(context, attrs, defStyle);
        init(context);
    }

    public ParallaxScollListView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public ParallaxScollListView(Context context) {
        super(context);
        init(context);
    }

    public void init(Context context) {
        mDefaultImageViewHeight = context.getResources().getDimensionPixelSize(R.dimen.size_default_height);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        initViewsBounds(mZoomRatio);
    }

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
    }

    @Override
    protected boolean overScrollBy(int deltaX, int deltaY, int scrollX,
                                   int scrollY, int scrollRangeX, int scrollRangeY,
                                   int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {
        boolean isCollapseAnimation = false;

        isCollapseAnimation = scrollByListener.overScrollBy(deltaX, deltaY,
                scrollX, scrollY, scrollRangeX, scrollRangeY, maxOverScrollX,
                maxOverScrollY, isTouchEvent)
                || isCollapseAnimation;

        return isCollapseAnimation || super.overScrollBy(deltaX, deltaY,
                scrollX, scrollY, scrollRangeX, scrollRangeY, maxOverScrollX,
                maxOverScrollY, isTouchEvent);
    }

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem,
                         int visibleItemCount, int totalItemCount) {
    }

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
        View firstView = (View) mImageView.getParent();
        // firstView.getTop < getPaddingTop means mImageView will be covered by top padding,
        // so we can layout it to make it shorter
        if (firstView.getTop() < getPaddingTop() && mImageView.getHeight() > mImageViewHeight) {
            mImageView.getLayoutParams().height = Math.max(mImageView.getHeight() - (getPaddingTop() - firstView.getTop()), mImageViewHeight);
            // to set the firstView.mTop to 0,
            // maybe use View.setTop() is more easy, but it just support from Android 3.0 (API 11)
            firstView.layout(firstView.getLeft(), 0, firstView.getRight(), firstView.getHeight());
            mImageView.requestLayout();
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        touchListener.onTouchEvent(ev);
        return super.onTouchEvent(ev);
    }

    public void setParallaxImageView(ImageView iv) {
        mImageView = iv;
        mImageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
    }

    private void initViewsBounds(double zoomRatio) {
        if (mImageViewHeight == -1) {
            mImageViewHeight = mImageView.getHeight();
            if (mImageViewHeight <= 0) {
                mImageViewHeight = mDefaultImageViewHeight;
            }
            double ratio = ((double) mImageView.getDrawable().getIntrinsicWidth()) / ((double) mImageView.getWidth());

            mDrawableMaxHeight = (int) ((mImageView.getDrawable().getIntrinsicHeight() / ratio) * (zoomRatio > 1 ?
                    zoomRatio : 1));
        }
    }

    public void setZoomRatio(double zoomRatio) {
        mZoomRatio = zoomRatio;
    }

    private OnOverScrollByListener scrollByListener = new OnOverScrollByListener() {
        @Override
        public boolean overScrollBy(int deltaX, int deltaY, int scrollX,
                                    int scrollY, int scrollRangeX, int scrollRangeY,
                                    int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {
            if (mImageView.getHeight() <= mDrawableMaxHeight && isTouchEvent) {
                if (deltaY < 0) {
                    if (mImageView.getHeight() - deltaY / 2 >= mImageViewHeight) {
                        mImageView.getLayoutParams().height = mImageView.getHeight() - deltaY / 2 < mDrawableMaxHeight ?
                                mImageView.getHeight() - deltaY / 2 : mDrawableMaxHeight;
                        mImageView.requestLayout();
                    }
                } else {
                    if (mImageView.getHeight() > mImageViewHeight) {
                        mImageView.getLayoutParams().height = mImageView.getHeight() - deltaY > mImageViewHeight ?
                                mImageView.getHeight() - deltaY : mImageViewHeight;
                        mImageView.requestLayout();
                        return true;
                    }
                }
            }
            return false;
        }
    };

    private OnTouchEventListener touchListener = new OnTouchEventListener() {
        @Override
        public void onTouchEvent(MotionEvent ev) {
            if (ev.getAction() == MotionEvent.ACTION_UP) {
                if (mImageViewHeight - 1 < mImageView.getHeight()) {
                    ResetAnimimation animation = new ResetAnimimation(
                            mImageView, mImageViewHeight);
                    animation.setDuration(300);
                    mImageView.startAnimation(animation);
                }
            }
        }
    };

    public class ResetAnimimation extends Animation {
        int targetHeight;
        int originalHeight;
        int extraHeight;
        View mView;

        protected ResetAnimimation(View view, int targetHeight) {
            this.mView = view;
            this.targetHeight = targetHeight;
            originalHeight = view.getHeight();
            extraHeight = this.targetHeight - originalHeight;
        }

        @Override
        protected void applyTransformation(float interpolatedTime,
                                           Transformation t) {

            int newHeight;
            newHeight = (int) (targetHeight - extraHeight * (1 - interpolatedTime));
            mView.getLayoutParams().height = newHeight;
            mView.requestLayout();
        }
    }
}

ParallaxListViewActivity.class

public class ParallaxListViewActivity extends AppCompatActivity {

    @Bind(R.id.layout_listview)
    ParallaxScollListView layoutListview;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_parallax_list_view);
        ButterKnife.bind(this);

        View header = LayoutInflater.from(this).inflate(R.layout.listview_header, null);
        ImageView mImageView = (ImageView) header.findViewById(R.id.layout_header_image);

        layoutListview.setZoomRatio(ParallaxScollListView.ZOOM_X2);
        layoutListview.setParallaxImageView(mImageView);
        layoutListview.addHeaderView(header);

        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
                android.R.layout.simple_expandable_list_item_1,
                new String[]{
                        "First Item",
                        "Second Item",
                        "Third Item",
                        "Fifth Item",
                        "Sixth Item",
                        "Seventh Item",
                        "Eighth Item",
                        "Ninth Item",
                        "Tenth Item",
                        "....."
                }
        );
        layoutListview.setAdapter(adapter);
    }
}

7、SwipeMenuListView实现listview滑动删除。

效果图:

项目在GitHub上的地址:

https://github.com/baoyongzhang/SwipeMenuListView

项目使用:

在gradle中添加

compile ‘com.baoyz.swipemenulistview:library:1.3.0‘

有两种侧滑删除的列表,一种是侧滑内容都一样的列表,SimpleActivity.class;

另一种是侧滑内容不一样的列表,DifferentMenuActivity.class;

SimpleActivity.class

public class SimpleActivity extends AppCompatActivity {

    private List<ApplicationInfo> mAppList;
    private AppAdapter mAdapter;
    private SwipeMenuListView mListView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_simple);

        mAppList = getPackageManager().getInstalledApplications(0);

        mListView = (SwipeMenuListView) findViewById(R.id.listView);

        mAdapter = new AppAdapter();
        mListView.setAdapter(mAdapter);

        // step 1. create a MenuCreator
        SwipeMenuCreator creator = new SwipeMenuCreator() {

            @Override
            public void create(SwipeMenu menu) {
                // create "open" item
                SwipeMenuItem openItem = new SwipeMenuItem(
                        getApplicationContext());
                // set item background
                openItem.setBackground(new ColorDrawable(Color.rgb(0xC9, 0xC9,
                        0xCE)));
                // set item width
                openItem.setWidth(dp2px(90));
                // set item title
                openItem.setTitle("Open");
                // set item title fontsize
                openItem.setTitleSize(18);
                // set item title font color
                openItem.setTitleColor(Color.WHITE);
                // add to menu
                menu.addMenuItem(openItem);

                // create "delete" item
                SwipeMenuItem deleteItem = new SwipeMenuItem(
                        getApplicationContext());
                // set item background
                deleteItem.setBackground(new ColorDrawable(Color.rgb(0xF9,
                        0x3F, 0x25)));
                // set item width
                deleteItem.setWidth(dp2px(90));
                // set a icon
                deleteItem.setIcon(R.mipmap.ic_delete);
                // add to menu
                menu.addMenuItem(deleteItem);
            }
        };
        // set creator
        mListView.setMenuCreator(creator);

        // step 2. listener item click event
        mListView.setOnMenuItemClickListener(new SwipeMenuListView.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(int position, SwipeMenu menu, int index) {
                ApplicationInfo item = mAppList.get(position);
                switch (index) {
                    case 0:
                        // open
                        open(item);
                        break;
                    case 1:
                        // delete
//                  delete(item);
                        mAppList.remove(position);
                        mAdapter.notifyDataSetChanged();
                        break;
                }
                return false;
            }
        });

        // set SwipeListener
        mListView.setOnSwipeListener(new SwipeMenuListView.OnSwipeListener() {

            @Override
            public void onSwipeStart(int position) {
                // swipe start
            }

            @Override
            public void onSwipeEnd(int position) {
                // swipe end
            }
        });

        // set MenuStateChangeListener
        mListView.setOnMenuStateChangeListener(new SwipeMenuListView.OnMenuStateChangeListener() {
            @Override
            public void onMenuOpen(int position) {
            }

            @Override
            public void onMenuClose(int position) {
            }
        });

        // other setting
//      listView.setCloseInterpolator(new BounceInterpolator());

        // test item long click
        mListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {

            @Override
            public boolean onItemLongClick(AdapterView<?> parent, View view,
                                           int position, long id) {
                Toast.makeText(getApplicationContext(), position + " long click", Toast.LENGTH_SHORT).show();
                return false;
            }
        });

    }

    private void delete(ApplicationInfo item) {
        // delete app
        try {
            Intent intent = new Intent(Intent.ACTION_DELETE);
            intent.setData(Uri.fromParts("package", item.packageName, null));
            startActivity(intent);
        } catch (Exception e) {
        }
    }

    private void open(ApplicationInfo item) {
        // open app
        Intent resolveIntent = new Intent(Intent.ACTION_MAIN, null);
        resolveIntent.addCategory(Intent.CATEGORY_LAUNCHER);
        resolveIntent.setPackage(item.packageName);
        List<ResolveInfo> resolveInfoList = getPackageManager()
                .queryIntentActivities(resolveIntent, 0);
        if (resolveInfoList != null && resolveInfoList.size() > 0) {
            ResolveInfo resolveInfo = resolveInfoList.get(0);
            String activityPackageName = resolveInfo.activityInfo.packageName;
            String className = resolveInfo.activityInfo.name;

            Intent intent = new Intent(Intent.ACTION_MAIN);
            intent.addCategory(Intent.CATEGORY_LAUNCHER);
            ComponentName componentName = new ComponentName(
                    activityPackageName, className);

            intent.setComponent(componentName);
            startActivity(intent);
        }
    }

    class AppAdapter extends BaseAdapter {

        @Override
        public int getCount() {
            return mAppList.size();
        }

        @Override
        public ApplicationInfo getItem(int position) {
            return mAppList.get(position);
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            if (convertView == null) {
                convertView = View.inflate(getApplicationContext(),
                        R.layout.item_list_app, null);
                new ViewHolder(convertView);
            }
            ViewHolder holder = (ViewHolder) convertView.getTag();
            ApplicationInfo item = getItem(position);
            holder.iv_icon.setImageDrawable(item.loadIcon(getPackageManager()));
            holder.tv_name.setText(item.loadLabel(getPackageManager()));
            holder.iv_icon.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Toast.makeText(SimpleActivity.this, "iv_icon_click", Toast.LENGTH_SHORT).show();
                }
            });
            holder.tv_name.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Toast.makeText(SimpleActivity.this,"iv_icon_click",Toast.LENGTH_SHORT).show();
                }
            });
            return convertView;
        }

        class ViewHolder {
            ImageView iv_icon;
            TextView tv_name;

            public ViewHolder(View view) {
                iv_icon = (ImageView) view.findViewById(R.id.iv_icon);
                tv_name = (TextView) view.findViewById(R.id.tv_name);
                view.setTag(this);
            }
        }

    }

    private int dp2px(int dp) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
                getResources().getDisplayMetrics());
    }

}

DifferentMenuActivity.class

public class DifferentMenuActivity extends AppCompatActivity {

    private List<ApplicationInfo> mAppList;
    private AppAdapter mAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_simple);

        mAppList = getPackageManager().getInstalledApplications(0);

        SwipeMenuListView listView = (SwipeMenuListView) findViewById(R.id.listView);
        mAdapter = new AppAdapter();
        listView.setAdapter(mAdapter);

        // step 1. create a MenuCreator
        SwipeMenuCreator creator = new SwipeMenuCreator() {

            @Override
            public void create(SwipeMenu menu) {
                // Create different menus depending on the view type
                switch (menu.getViewType()) {
                    case 0:
                        createMenu1(menu);
                        break;
                    case 1:
                        createMenu2(menu);
                        break;
                    case 2:
                        createMenu3(menu);
                        break;
                }
            }

            private void createMenu1(SwipeMenu menu) {
                SwipeMenuItem item1 = new SwipeMenuItem(
                        getApplicationContext());
                item1.setBackground(new ColorDrawable(Color.rgb(0xE5, 0x18,
                        0x5E)));
                item1.setWidth(dp2px(90));
                item1.setIcon(R.mipmap.ic_action_favorite);
                menu.addMenuItem(item1);
                SwipeMenuItem item2 = new SwipeMenuItem(
                        getApplicationContext());
                item2.setBackground(new ColorDrawable(Color.rgb(0xC9, 0xC9,
                        0xCE)));
                item2.setWidth(dp2px(90));
                item2.setIcon(R.mipmap.ic_action_good);
                menu.addMenuItem(item2);
            }

            private void createMenu2(SwipeMenu menu) {
                SwipeMenuItem item1 = new SwipeMenuItem(
                        getApplicationContext());
                item1.setBackground(new ColorDrawable(Color.rgb(0xE5, 0xE0,
                        0x3F)));
                item1.setWidth(dp2px(90));
                item1.setIcon(R.mipmap.ic_action_important);
                menu.addMenuItem(item1);
                SwipeMenuItem item2 = new SwipeMenuItem(
                        getApplicationContext());
                item2.setBackground(new ColorDrawable(Color.rgb(0xF9,
                        0x3F, 0x25)));
                item2.setWidth(dp2px(90));
                item2.setIcon(R.mipmap.ic_action_discard);
                menu.addMenuItem(item2);
            }

            private void createMenu3(SwipeMenu menu) {
                SwipeMenuItem item1 = new SwipeMenuItem(
                        getApplicationContext());
                item1.setBackground(new ColorDrawable(Color.rgb(0x30, 0xB1,
                        0xF5)));
                item1.setWidth(dp2px(90));
                item1.setIcon(R.mipmap.ic_action_about);
                menu.addMenuItem(item1);
                SwipeMenuItem item2 = new SwipeMenuItem(
                        getApplicationContext());
                item2.setBackground(new ColorDrawable(Color.rgb(0xC9, 0xC9,
                        0xCE)));
                item2.setWidth(dp2px(90));
                item2.setIcon(R.mipmap.ic_action_share);
                menu.addMenuItem(item2);
            }
        };
        // set creator
        listView.setMenuCreator(creator);

        // step 2. listener item click event
        listView.setOnMenuItemClickListener(new SwipeMenuListView.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(int position, SwipeMenu menu, int index) {
                ApplicationInfo item = mAppList.get(position);
                switch (index) {
                    case 0:
                        // open
                        break;
                    case 1:
                        // delete
//                  delete(item);
                        mAppList.remove(position);
                        mAdapter.notifyDataSetChanged();
                        break;
                }
                return false;
            }
        });

    }

    class AppAdapter extends BaseAdapter {

        @Override
        public int getCount() {
            return mAppList.size();
        }

        @Override
        public ApplicationInfo getItem(int position) {
            return mAppList.get(position);
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public int getViewTypeCount() {
            // menu type count
            return 3;
        }

        @Override
        public int getItemViewType(int position) {
            // current menu type
            return position % 3;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            if (convertView == null) {
                convertView = View.inflate(getApplicationContext(),
                        R.layout.item_list_app, null);
                new ViewHolder(convertView);
            }
            ViewHolder holder = (ViewHolder) convertView.getTag();
            ApplicationInfo item = getItem(position);
            holder.iv_icon.setImageDrawable(item.loadIcon(getPackageManager()));
            holder.tv_name.setText(item.loadLabel(getPackageManager()));
            return convertView;
        }

        class ViewHolder {
            ImageView iv_icon;
            TextView tv_name;

            public ViewHolder(View view) {
                iv_icon = (ImageView) view.findViewById(R.id.iv_icon);
                tv_name = (TextView) view.findViewById(R.id.tv_name);
                view.setTag(this);
            }
        }
    }

    private int dp2px(int dp) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
                getResources().getDisplayMetrics());
    }

}

8、gif-movie-view实现播放gif图像

项目在GitHub上的地址:

https://github.com/sbakhtiarov/gif-movie-view

项目使用:

自定义View:

GifMovieView.class

public class GifMovieView extends View {

    private static final int DEFAULT_MOVIEW_DURATION = 1000;

    private int mMovieResourceId;
    private Movie mMovie;

    private long mMovieStart;
    private int mCurrentAnimationTime = 0;

    /**
     * Position for drawing animation frames in the center of the view.
     */
    private float mLeft;
    private float mTop;

    /**
     * Scaling factor to fit the animation within view bounds.
     */
    private float mScale;

    /**
     * Scaled movie frames width and height.
     */
    private int mMeasuredMovieWidth;
    private int mMeasuredMovieHeight;

    private volatile boolean mPaused = false;
    private boolean mVisible = true;

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

    public GifMovieView(Context context, AttributeSet attrs) {
        this(context, attrs, R.styleable.CustomTheme_gifMoviewViewStyle);
    }

    public GifMovieView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);

        setViewAttributes(context, attrs, defStyle);
    }

    private void setViewAttributes(Context context, AttributeSet attrs, int defStyle) {

        /**
         * Starting from HONEYCOMB have to turn off HW acceleration to draw
         * Movie on Canvas.
         */
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            setLayerType(View.LAYER_TYPE_SOFTWARE, null);
        }

        final TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.GifMoviewView, defStyle,
                R.style.Widget_GifMoviewView);

        mMovieResourceId = array.getResourceId(R.styleable.GifMoviewView_gif, -1);
        mPaused = array.getBoolean(R.styleable.GifMoviewView_paused, false);

        array.recycle();

        if (mMovieResourceId != -1) {
            mMovie = Movie.decodeStream(getResources().openRawResource(mMovieResourceId));
        }
    }

    public void setMovieResource(int movieResId) {
        this.mMovieResourceId = movieResId;
        mMovie = Movie.decodeStream(getResources().openRawResource(mMovieResourceId));
        requestLayout();
    }

    public void setMovie(Movie movie) {
        this.mMovie = movie;
        requestLayout();
    }

    public Movie getMovie() {
        return mMovie;
    }

    public void setMovieTime(int time) {
        mCurrentAnimationTime = time;
        invalidate();
    }

    public void setPaused(boolean paused) {
        this.mPaused = paused;

        /**
         * Calculate new movie start time, so that it resumes from the same
         * frame.
         */
        if (!paused) {
            mMovieStart = android.os.SystemClock.uptimeMillis() - mCurrentAnimationTime;
        }

        invalidate();
    }

    public boolean isPaused() {
        return this.mPaused;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        if (mMovie != null) {
            int movieWidth = mMovie.width();
            int movieHeight = mMovie.height();

            /*
             * Calculate horizontal scaling
             */
            float scaleH = 1f;
            int measureModeWidth = MeasureSpec.getMode(widthMeasureSpec);

            if (measureModeWidth != MeasureSpec.UNSPECIFIED) {
                int maximumWidth = MeasureSpec.getSize(widthMeasureSpec);
                if (movieWidth > maximumWidth) {
                    scaleH = (float) movieWidth / (float) maximumWidth;
                }
            }

            /*
             * calculate vertical scaling
             */
            float scaleW = 1f;
            int measureModeHeight = MeasureSpec.getMode(heightMeasureSpec);

            if (measureModeHeight != MeasureSpec.UNSPECIFIED) {
                int maximumHeight = MeasureSpec.getSize(heightMeasureSpec);
                if (movieHeight > maximumHeight) {
                    scaleW = (float) movieHeight / (float) maximumHeight;
                }
            }

            /*
             * calculate overall scale
             */
            mScale = 1f / Math.max(scaleH, scaleW);

            mMeasuredMovieWidth = (int) (movieWidth * mScale);
            mMeasuredMovieHeight = (int) (movieHeight * mScale);

            setMeasuredDimension(mMeasuredMovieWidth, mMeasuredMovieHeight);

        } else {
            /*
             * No movie set, just set minimum available size.
             */
            setMeasuredDimension(getSuggestedMinimumWidth(), getSuggestedMinimumHeight());
        }
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);

        /*
         * Calculate left / top for drawing in center
         */
        mLeft = (getWidth() - mMeasuredMovieWidth) / 2f;
        mTop = (getHeight() - mMeasuredMovieHeight) / 2f;

        mVisible = getVisibility() == View.VISIBLE;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (mMovie != null) {
            if (!mPaused) {
                updateAnimationTime();
                drawMovieFrame(canvas);
                invalidateView();
            } else {
                drawMovieFrame(canvas);
            }
        }
    }

    /**
     * Invalidates view only if it is visible.
     * <br>
     * {@link #postInvalidateOnAnimation()} is used for Jelly Bean and higher.
     *
     */
    private void invalidateView() {
        if(mVisible) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                postInvalidateOnAnimation();
            } else {
                invalidate();
            }
        }
    }

    /**
     * Calculate current animation time
     */
    private void updateAnimationTime() {
        long now = android.os.SystemClock.uptimeMillis();

        if (mMovieStart == 0) {
            mMovieStart = now;
        }

        int dur = mMovie.duration();

        if (dur == 0) {
            dur = DEFAULT_MOVIEW_DURATION;
        }

        mCurrentAnimationTime = (int) ((now - mMovieStart) % dur);
    }

    /**
     * Draw current GIF frame
     */
    private void drawMovieFrame(Canvas canvas) {

        mMovie.setTime(mCurrentAnimationTime);

        canvas.save(Canvas.MATRIX_SAVE_FLAG);
        canvas.scale(mScale, mScale);
        mMovie.draw(canvas, mLeft / mScale, mTop / mScale);
        canvas.restore();
    }

    @Override
    public void onScreenStateChanged(int screenState) {
        super.onScreenStateChanged(screenState);
        mVisible = screenState == SCREEN_STATE_ON;
        invalidateView();
    }

    @Override
    protected void onVisibilityChanged(View changedView, int visibility) {
        super.onVisibilityChanged(changedView, visibility);
        mVisible = visibility == View.VISIBLE;
        invalidateView();
    }

    @Override
    protected void onWindowVisibilityChanged(int visibility) {
        super.onWindowVisibilityChanged(visibility);
        mVisible = visibility == View.VISIBLE;
        invalidateView();
    }
}

XML中的布局:

<?xml version="1.0" encoding="utf-8"?>
<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"
    xmlns:custom="http://schemas.android.com/apk/res-auto"
    android:fillViewport="true">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#FFFFFFFF"
        android:gravity="center_horizontal"
        android:orientation="vertical"
        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=".MainActivity" >

        <com.zerom.mtest.GifMove.GifMovieView
            android:id="@+id/gif1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="onGifClick" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal" >

            <com.zerom.mtest.GifMove.GifMovieView
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:onClick="onGifClick"
                custom:gif="@mipmap/gif_heart" />

            <com.zerom.mtest.GifMove.GifMovieView
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:onClick="onGifClick"
                custom:gif="@mipmap/gif_heart" />

            <com.zerom.mtest.GifMove.GifMovieView
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:onClick="onGifClick"
                custom:gif="@mipmap/gif_heart" />

            <com.zerom.mtest.GifMove.GifMovieView
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:onClick="onGifClick"
                custom:gif="@mipmap/gif_heart" />
        </LinearLayout>
    </LinearLayout>

</ScrollView>

Activity中使用:

public class GifMoveActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_gif_move);

        final GifMovieView gif1 = (GifMovieView) findViewById(R.id.gif1);
        assert gif1 != null;
        gif1.setMovieResource(R.mipmap.gif_heart);
    }

    public void onGifClick(View v) {
        GifMovieView gif = (GifMovieView) v;
        gif.setPaused(!gif.isPaused());
    }
}

9、BubbleView实现类似聊天气泡的view

效果图:

项目使用:

在gradle中添加

compile ‘com.lguipeng.bubbleview:library:1.0.0‘

在XML中添加布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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_margin="20dp"
    android:divider="@drawable/divider"
    android:gravity="center_horizontal"
    android:orientation="vertical"
    android:showDividers="middle">

    <com.github.library.bubbleview.BubbleTextVew
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="10dp"
        android:text="Hello BubbleTextVew"
        android:textColor="@android:color/white"
        android:textSize="20sp"
        app:angle="8dp"
        app:arrowHeight="10dp"
        app:arrowLocation="right"
        app:arrowPosition="14dp"
        app:arrowWidth="8dp"
        app:bubbleColor="#7EC0EE" />

    <com.github.library.bubbleview.BubbleImageView
        android:id="@+id/bubble_image"
        android:layout_width="180dp"
        android:layout_height="wrap_content"
        android:src="@drawable/girl"
        app:angle="6dp"
        app:arrowHeight="8dp"
        app:arrowLocation="top"
        app:arrowPosition="15dp"
        app:arrowWidth="10dp" />

    <com.github.library.bubbleview.BubbleLinearLayout
        android:id="@+id/bubble_layout"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:angle="4dp"
        app:arrowHeight="10dp"
        app:arrowLocation="left"
        app:arrowPosition="10dp"
        app:arrowWidth="8dp"
        app:bubbleColor="#7EC0EE">

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:src="@mipmap/ic_launcher" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:layout_marginRight="4dp"
            android:text="BubbleLinearLayout Text"
            android:textColor="@android:color/white" />
    </com.github.library.bubbleview.BubbleLinearLayout>

    <com.github.library.bubbleview.BubbleTextVew
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="10dp"
        android:text="Hello BubbleTextVew"
        android:textColor="@android:color/white"
        app:angle="2dp"
        app:arrowHeight="10dp"
        app:arrowLocation="bottom"
        app:arrowPosition="10dp"
        app:arrowWidth="8dp"
        app:bubbleColor="#ff4444" />
</LinearLayout>

10、MaterialFavoriteButton收藏与取消收藏

效果图:

项目在GitHub上的地址:

https://github.com/IvBaranov/MaterialFavoriteButton

项目使用:

在gradle中添加

compile ‘com.github.ivbaranov:materialfavoritebutton:0.1.2‘

在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"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context=".MaterialFavoriteButtonActivity">

    <android.support.design.widget.AppBarLayout
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:theme="@style/AppTheme.AppBarOverlay">

        <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/AppTheme.PopupOverlay" />

    </android.support.design.widget.AppBarLayout>

    <include layout="@layout/content_main" />

</android.support.design.widget.CoordinatorLayout>

content_main.xml

<?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:layout_width="match_parent"
    android:layout_height="match_parent"
    android:scrollbars="none"
    >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <android.support.v7.widget.CardView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="@dimen/card_margin">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical">

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:padding="@dimen/text_padding"
                    android:text="Basic"
                    android:textAppearance="@style/TextAppearance.AppCompat.Title" />

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:padding="@dimen/text_padding"
                    android:text="@string/ipsum_1" />

                <com.github.ivbaranov.mfb.MaterialFavoriteButton
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content" />

            </LinearLayout>

        </android.support.v7.widget.CardView>

        <android.support.v7.widget.CardView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="@dimen/card_margin">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical">

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:padding="@dimen/text_padding"
                    android:text="Nice"
                    android:textAppearance="@style/TextAppearance.AppCompat.Title" />

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:padding="@dimen/text_padding"
                    android:text="@string/ipsum_en_1914_1" />

                <RelativeLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content">

                    <TextView
                        android:id="@+id/counter_text"
                        android:layout_width="wrap_content"
                        android:layout_height="match_parent"
                        android:layout_centerVertical="true"
                        android:layout_marginLeft="@dimen/starred_margin"
                        android:text="@string/starred" />

                    <TextView
                        android:id="@+id/counter_value"
                        android:layout_width="wrap_content"
                        android:layout_height="match_parent"
                        android:layout_centerVertical="true"
                        android:layout_toRightOf="@+id/counter_text"
                        android:layout_marginLeft="@dimen/counter_value_margin" />

                    <com.github.ivbaranov.mfb.MaterialFavoriteButton
                        android:id="@+id/favorite_nice"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_alignParentRight="true"
                        app:mfb_rotation_duration="400"
                        app:mfb_rotation_angle="216"
                        app:mfb_bounce_duration="700" />

                </RelativeLayout>

            </LinearLayout>

        </android.support.v7.widget.CardView>

        <android.support.v7.widget.CardView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="@dimen/card_margin">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical">

                <RelativeLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content">

                    <TextView
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:padding="@dimen/text_padding"
                        android:text="Custom"
                        android:textAppearance="@style/TextAppearance.AppCompat.Title" />

                    <com.github.ivbaranov.mfb.MaterialFavoriteButton
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_alignParentRight="true"
                        app:mfb_rotation_duration="700"
                        app:mfb_rotation_angle="360"
                        app:mfb_favorite_image="@mipmap/ic_event_available_black_24dp"
                        app:mfb_not_favorite_image="@mipmap/ic_event_busy_black_24dp"
                        app:mfb_animate_unfavorite="true"
                        app:mfb_bounce_duration="0" />

                </RelativeLayout>

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:padding="@dimen/text_padding"
                    android:text="@string/ipsum_2" />

            </LinearLayout>

        </android.support.v7.widget.CardView>

    </LinearLayout>

</ScrollView>

Activity中实现:

public class MaterialFavoriteButtonActivity extends AppCompatActivity {

    private TextView niceCounter;
    private int niceCounterValue = 37;

    @Override protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_material_favorite_button);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        //in the toolbar
        MaterialFavoriteButton toolbarFavorite = new MaterialFavoriteButton.Builder(this) //
                .favorite(true)
                .color(MaterialFavoriteButton.STYLE_WHITE)
                .type(MaterialFavoriteButton.STYLE_HEART)
                .rotationDuration(400)
                .create();
        toolbar.addView(toolbarFavorite);
        toolbarFavorite.setOnFavoriteChangeListener(
                new MaterialFavoriteButton.OnFavoriteChangeListener() {
                    @Override
                    public void onFavoriteChanged(MaterialFavoriteButton buttonView, boolean favorite) {
                        Snackbar.make(buttonView, getString(R.string.toolbar_favorite_snack) + favorite,
                                Snackbar.LENGTH_SHORT).show();
                    }
                });

        //nice cardview
        niceCounter = (TextView) findViewById(R.id.counter_value);
        niceCounter.setText(String.valueOf(niceCounterValue));
        MaterialFavoriteButton materialFavoriteButtonNice =
                (MaterialFavoriteButton) findViewById(R.id.favorite_nice);
        materialFavoriteButtonNice.setFavorite(true, false);
        materialFavoriteButtonNice.setOnFavoriteChangeListener(
                new MaterialFavoriteButton.OnFavoriteChangeListener() {
                    @Override
                    public void onFavoriteChanged(MaterialFavoriteButton buttonView, boolean favorite) {
                        if (favorite) {
                            niceCounterValue++;
                        } else {
                            niceCounterValue--;
                        }
                    }
                });
        materialFavoriteButtonNice.setOnFavoriteAnimationEndListener(
                new MaterialFavoriteButton.OnFavoriteAnimationEndListener() {
                    @Override
                    public void onAnimationEnd(MaterialFavoriteButton buttonView, boolean favorite) {
                        niceCounter.setText(String.valueOf(niceCounterValue));
                    }
                });
    }

}

11、Photoview 图片放大缩放功能

效果图:

项目在GitHub上的地址:

https://github.com/chrisbanes/PhotoView

项目使用:

在gradle中添加

compile ‘com.github.chrisbanes:PhotoView:1.2.6‘

在XML中添加布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:gravity="center"
    tools:context="com.zerom.mtest.PhotoViewActivity">

    <uk.co.senab.photoview.PhotoView
        android:id="@+id/pv_photoview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:src="@mipmap/ico_guide01"
        />

</LinearLayout>

Activity中使用:

public class PhotoViewActivity extends AppCompatActivity {

    @Bind(R.id.pv_photoview)
    PhotoView pvPhotoview;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_photo_view);
        ButterKnife.bind(this);

        PhotoViewAttacher photoViewAttacher = new PhotoViewAttacher(pvPhotoview);
        photoViewAttacher.update();
    }
}

12、Caldroid ,一个更好的Android日历控件

效果图:

项目在GitHub上的地址:

https://github.com/roomorama/Caldroid

项目使用:

在gradle中添加

 compile ‘com.roomorama:caldroid:3.0.1‘

在XML中添加布局:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <LinearLayout
            android:id="@+id/calendar1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">
        </LinearLayout>

        <LinearLayout
            android:id="@+id/button_layout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <Button
                android:id="@+id/customize_button"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="@string/customize"/>

            <Button
                android:id="@+id/show_dialog_button"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="@string/show_dialog"/>
        </LinearLayout>

        <TextView
            android:id="@+id/textview"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>

    </LinearLayout>
</ScrollView>

Activity中实现:

public class CaldroidActivity extends AppCompatActivity {

    private boolean undo = false;
    private CaldroidFragment caldroidFragment;
    private CaldroidFragment dialogCaldroidFragment;

    private void setCustomResourceForDates() {
        Calendar cal = Calendar.getInstance();

        // Min date is last 7 days
        cal.add(Calendar.DATE, -7);
        Date blueDate = cal.getTime();

        // Max date is next 7 days
        cal = Calendar.getInstance();
        cal.add(Calendar.DATE, 7);
        Date greenDate = cal.getTime();

        if (caldroidFragment != null) {
            ColorDrawable blue = new ColorDrawable(getResources().getColor(R.color.blue));
            ColorDrawable green = new ColorDrawable(Color.GREEN);
            caldroidFragment.setBackgroundDrawableForDate(blue, blueDate);
            caldroidFragment.setBackgroundDrawableForDate(green, greenDate);
            caldroidFragment.setTextColorForDate(R.color.white, blueDate);
            caldroidFragment.setTextColorForDate(R.color.white, greenDate);
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_caldroid);

        final SimpleDateFormat formatter = new SimpleDateFormat("dd MMM yyyy");

        // Setup caldroid fragment
        // **** If you want normal CaldroidFragment, use below line ****
        caldroidFragment = new CaldroidFragment();

        // //////////////////////////////////////////////////////////////////////
        // **** This is to show customized fragment. If you want customized
        // version, uncomment below line ****
//       caldroidFragment = new CaldroidSampleCustomFragment();

        // Setup arguments

        // If Activity is created after rotation
        if (savedInstanceState != null) {
            caldroidFragment.restoreStatesFromKey(savedInstanceState,
                    "CALDROID_SAVED_STATE");
        }
        // If activity is created from fresh
        else {
            Bundle args = new Bundle();
            Calendar cal = Calendar.getInstance();
            args.putInt(CaldroidFragment.MONTH, cal.get(Calendar.MONTH) + 1);
            args.putInt(CaldroidFragment.YEAR, cal.get(Calendar.YEAR));
            args.putBoolean(CaldroidFragment.ENABLE_SWIPE, true);
            args.putBoolean(CaldroidFragment.SIX_WEEKS_IN_CALENDAR, true);

            // Uncomment this to customize startDayOfWeek
            // args.putInt(CaldroidFragment.START_DAY_OF_WEEK,
            // CaldroidFragment.TUESDAY); // Tuesday

            // Uncomment this line to use Caldroid in compact mode
            // args.putBoolean(CaldroidFragment.SQUARE_TEXT_VIEW_CELL, false);

            // Uncomment this line to use dark theme
//            args.putInt(CaldroidFragment.THEME_RESOURCE, com.caldroid.R.style.CaldroidDefaultDark);

            caldroidFragment.setArguments(args);
        }

        setCustomResourceForDates();

        // Attach to the activity
        FragmentTransaction t = getSupportFragmentManager().beginTransaction();
        t.replace(R.id.calendar1, caldroidFragment);
        t.commit();

        // Setup listener
        final CaldroidListener listener = new CaldroidListener() {

            @Override
            public void onSelectDate(Date date, View view) {
                Toast.makeText(getApplicationContext(), formatter.format(date),
                        Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onChangeMonth(int month, int year) {
                String text = "month: " + month + " year: " + year;
                Toast.makeText(getApplicationContext(), text,
                        Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onLongClickDate(Date date, View view) {
                Toast.makeText(getApplicationContext(),
                        "Long click " + formatter.format(date),
                        Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onCaldroidViewCreated() {
                if (caldroidFragment.getLeftArrowButton() != null) {
                    Toast.makeText(getApplicationContext(),
                            "Caldroid view is created", Toast.LENGTH_SHORT)
                            .show();
                }
            }

        };

        // Setup Caldroid
        caldroidFragment.setCaldroidListener(listener);

        final TextView textView = (TextView) findViewById(R.id.textview);

        final Button customizeButton = (Button) findViewById(R.id.customize_button);

        // Customize the calendar
        assert customizeButton != null;
        customizeButton.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                if (undo) {
                    customizeButton.setText(getString(R.string.customize));
                    textView.setText("");

                    // Reset calendar
                    caldroidFragment.clearDisableDates();
                    caldroidFragment.clearSelectedDates();
                    caldroidFragment.setMinDate(null);
                    caldroidFragment.setMaxDate(null);
                    caldroidFragment.setShowNavigationArrows(true);
                    caldroidFragment.setEnableSwipe(true);
                    caldroidFragment.refreshView();
                    undo = false;
                    return;
                }

                // Else
                undo = true;
                customizeButton.setText(getString(R.string.undo));
                Calendar cal = Calendar.getInstance();

                // Min date is last 7 days
                cal.add(Calendar.DATE, -7);
                Date minDate = cal.getTime();

                // Max date is next 7 days
                cal = Calendar.getInstance();
                cal.add(Calendar.DATE, 14);
                Date maxDate = cal.getTime();

                // Set selected dates
                // From Date
                cal = Calendar.getInstance();
                cal.add(Calendar.DATE, 2);
                Date fromDate = cal.getTime();

                // To Date
                cal = Calendar.getInstance();
                cal.add(Calendar.DATE, 3);
                Date toDate = cal.getTime();

                // Set disabled dates
                ArrayList<Date> disabledDates = new ArrayList<Date>();
                for (int i = 5; i < 8; i++) {
                    cal = Calendar.getInstance();
                    cal.add(Calendar.DATE, i);
                    disabledDates.add(cal.getTime());
                }

                // Customize
                caldroidFragment.setMinDate(minDate);
                caldroidFragment.setMaxDate(maxDate);
                caldroidFragment.setDisableDates(disabledDates);
                caldroidFragment.setSelectedDates(fromDate, toDate);
                caldroidFragment.setShowNavigationArrows(false);
                caldroidFragment.setEnableSwipe(false);

                caldroidFragment.refreshView();

                // Move to date
                // cal = Calendar.getInstance();
                // cal.add(Calendar.MONTH, 12);
                // caldroidFragment.moveToDate(cal.getTime());

                String text = "Today: " + formatter.format(new Date()) + "\n";
                text += "Min Date: " + formatter.format(minDate) + "\n";
                text += "Max Date: " + formatter.format(maxDate) + "\n";
                text += "Select From Date: " + formatter.format(fromDate)
                        + "\n";
                text += "Select To Date: " + formatter.format(toDate) + "\n";
                for (Date date : disabledDates) {
                    text += "Disabled Date: " + formatter.format(date) + "\n";
                }

                textView.setText(text);
            }
        });

        Button showDialogButton = (Button) findViewById(R.id.show_dialog_button);

        final Bundle state = savedInstanceState;
        assert showDialogButton != null;
        showDialogButton.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                // Setup caldroid to use as dialog
                dialogCaldroidFragment = new CaldroidFragment();
                dialogCaldroidFragment.setCaldroidListener(listener);

                // If activity is recovered from rotation
                final String dialogTag = "CALDROID_DIALOG_FRAGMENT";
                if (state != null) {
                    dialogCaldroidFragment.restoreDialogStatesFromKey(
                            getSupportFragmentManager(), state,
                            "DIALOG_CALDROID_SAVED_STATE", dialogTag);
                    Bundle args = dialogCaldroidFragment.getArguments();
                    if (args == null) {
                        args = new Bundle();
                        dialogCaldroidFragment.setArguments(args);
                    }
                } else {
                    // Setup arguments
                    Bundle bundle = new Bundle();
                    // Setup dialogTitle
                    dialogCaldroidFragment.setArguments(bundle);
                }

                dialogCaldroidFragment.show(getSupportFragmentManager(),
                        dialogTag);
            }
        });
    }

    /**
     * Save current states of the Caldroid here
     */
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        // TODO Auto-generated method stub
        super.onSaveInstanceState(outState);

        if (caldroidFragment != null) {
            caldroidFragment.saveStatesToKey(outState, "CALDROID_SAVED_STATE");
        }

        if (dialogCaldroidFragment != null) {
            dialogCaldroidFragment.saveStatesToKey(outState,
                    "DIALOG_CALDROID_SAVED_STATE");
        }
    }
}
时间: 2024-11-03 17:26:55

Android进阶 — GitHub开源控件的使用合集的相关文章

GitHub开源控件的使用合集

Android的加载动画AVLoadingIndicatorView 项目地址: https://github.com/81813780/AVLoadingIndicatorView 首先,在 build.gradle.中添加: dependencies { compile 'com.wang.avi:library:2.1.3' } 然后在xml中使用: <com.wang.avi.AVLoadingIndicatorView android:id="@+id/avi" and

开源集锦(三)GitHub开源控件

ListViewAnimations nhaarman大神力作 地址:https://github.com/nhaarman/ListViewAnimations apk展示http://download.csdn.net/detail/wds1181977/9510476 lawloretienne/QuickReturn https://github.com/lawloretienne/QuickReturn ListView/ScrollView的header或footer,当向下滚动时消

Android常用酷炫控件(开源项目)github地址汇总

转载一个很牛逼的控件收集贴... 第一部分 个性化控件(View) 主要介绍那些不错个性化的 View,包括 ListView.ActionBar.Menu.ViewPager.Gallery.GridView.ImageView.ProgressBar.TextView.ScrollView.TimeView.TipView.FlipView.ColorPickView.GraphView.UI Style 等等. 一.ListView android-pulltorefresh一个强大的拉动

开源整理:Android App新手指引开源控件

开源整理:Android App新手指引开源控件 一个App第一次与用户接触或者发生大版本更新时,常常会用户进行新手引导,而一个好的新手指引,往往能够方便新用户快速了解操作你的应用功能.新手指引的重要性,不言而喻.本文搜集整理了Github上一些效果不错的新手指引开源控件,帮助你的应用在用户面前有更好的效果展示.当然,如果你有精力,也可以自己开发维护一套新手指引效果. GuideView https://github.com/binIoter/GuideView 国人开发者出品的一个轻量级新手指

Android之开源控件ViewFLow学习笔记【含下载地址】--(原创-20150407)

Android开源控件ViewFlow学习 这里简单介绍一点:抛出IllegalStateException: "ViewFlow can only be used in EXACTLY mode." 首先要明确ViewFlow的好处所在:(1).ViewFlow比较适合动态大小,如图片的个数由后台决定,发多少就显示多少,这是用ViewPager就不是很合适. ( 2) ViewFlow的轮播滚动效果非常平滑,过渡非常友好,而且支持循环. 使用ViewFlow的时候,注意只能用在大小确

android开发之wheel控件使用详解

出门在外生不起病呀,随便两盒药60多块钱.好吧,不废话了,今天我们来看看wheel控件的使用,这是GitHub上的一个开源控件,用起来十分方便,我们可以用它做许多事情,比如做一个自定义的datepicker,在一些电商App中,经常用它来做省市县三级联动,总之用途还是挺多的,我们今天就一起来看看怎么使用这个东东. 我们先来看看今天要做的一个效果图: 这是我们今天要做的效果图.下面就开始吧. 1.获得wheel wheel是GitHub上的一个开源控件,我们可以直接在GitHub上下载,地址htt

SlidingMenu开源控件侧拉栏无法滑动问题修复,bug解决,

slidingMenu是gitHub上比较流行的一个侧拉菜单开源控件,前几日自己写了一个开源控件,经过对比,感觉slidingMenu功能更为强大,但是同时,自己写的开源控件,侧拉栏是可以滑动的,比如这样, 手指在侧拉栏处滑动的时候,依旧可以关闭侧拉栏,这个功能很使用,尤其是如图所示,当slidingMenu比较宽的时候,占据比较大的比例,此时用户只能在左边小范围内滑动才能关闭掉, 很坑爹呀 有木有????看了大部分的应用,都有此问题,故分享出来供大家一起学习 但是问题来了,翻遍slidingM

PullToRefresh开源控件和5.0新特性SwipeRefreshLayout的对比使用

PullToRefresh开源控件可以实现下拉和上拉刷新数据,而后者SwipeRefreshLayout主要用于下拉刷新,知乎的首页刷新数据用的就是这个控件. 一,先介绍PullToRefresh开源控件的使用 PullToRefresh开源控件可以实现下拉和上拉刷新数据,在项目中首先要导入这个包,可以先从github上进行下载,之后在Android Studio中进行导入,之前试了直接导入总会报错,后来直接右键New Module,新建android library即可,按照PullToRef

Android UI-自定义日历控件

Android UI-自定义日历控件 本篇博客笔者给大家分享一个日历控件,这里有个需求:要求显示当前月的日期,左右可以切换月份来查看日期. 我们想一想会如何去实现这样的一个控件,有开源的,但可能不太满足我们的特定的需求,这里笔者自定义了一个,读者可以根据自己的需求来修改代码.下面来说一下实现的思路: 首先我们要显示当前月份,自然我们要计算出当前的日期,并且把每一天对应到具体的星期,我们会有以下效果: 我们先想一下这样的效果用什么控件可以实现?很自然可以想到用网格视图GridView,但这里笔者使