Android的加载动画AVLoadingIndicatorView
项目地址:
https://github.com/81813780/AVLoadingIndicatorView
首先,在 build.gradle.中添加;
dependencies { compile 'com.wang.avi:library:2.1.3' }
然后在xml中使用;
也可以通过代码显示或者隐藏;
void startAnim(){ avi.show(); // or avi.smoothToShow(); } void stopAnim(){ avi.hide(); // or avi.smoothToHide(); }
QuantityView 类似购物车数量调节:
效果图:
项目在GitHub上的地址:
https://github.com/himanshu-soni/QuantityView
项目使用:
在gradle中添加
compile 'me.himanshusoni.quantityview:quantity-view:1.1.3'
在XML中添加布局:
中的使用代码:
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(); } }); } }
Justified 实现Textview和Edittext文字左右对齐。
效果图:
项目在GitHub上的地址:
https://github.com/programingjd/justified
项目使用:
在gradle中添加
compile 'com.uncopt:android.justified:1.0'
在XML中添加布局:
android-shapeLoadingView实现高仿新版58 加载动画
效果图:
项目在GitHub上的地址:
https://github.com/zzz40500/android-shapeLoadingView
项目使用:
在gradle中添加
compile 'com.github.zzz40500:android-shapeLoadingView:1.0.3.2'
在XML中添加布局:
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(); } }); } }
Labelview实现标签功能,在控件上面展示斜的文字
效果图:
项目在GitHub上的地址:
https://github.com/linger1216//labelview
项目使用:
在gradle中添加
compile 'com.github.linger1216:labelview:v1.1.0'
在XML中添加布局:
PullZoomView实现类似微信,下拉listview,顶部图片放大效果
项目在GitHub上的地址:
https://github.com/Frank-Zhu/PullZoomView
项目使用:
在gradle中添加
compile 'com.github.frank-zhu:pullzoomview:1.0.0'
在XML中添加布局:
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); ArrayAdapteradapter = new ArrayAdapter (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); } }
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 ListmAppList; 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 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 ListmAppList; 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()); } }
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. * * {@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中的布局:
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()); } }
BubbleView实现类似聊天气泡的view
效果图:
项目使用:
在gradle中添加
compile 'com.lguipeng.bubbleview:library:1.0.0'
在XML中添加布局:
MaterialFavoriteButton收藏与取消收藏
效果图:
项目在GitHub上的地址:
https://github.com/IvBaranov/MaterialFavoriteButton
项目使用:
在gradle中添加
compile 'com.github.ivbaranov:materialfavoritebutton:0.1.2'
在XML中添加布局:
content_main.xml
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)); } }); } }
Photoview 图片放大缩放功能
效果图:
项目在GitHub上的地址:
https://github.com/chrisbanes/PhotoView
项目使用:
在gradle中添加
compile 'com.github.chrisbanes:PhotoView:1.2.6'
在XML中添加布局:
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(); } }
Caldroid ,一个更好的Android日历控件
效果图:
项目在GitHub上的地址:
https://github.com/roomorama/Caldroid
项目使用:
在gradle中添加
compile 'com.roomorama:caldroid:3.0.1'
在XML中添加布局:
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 ArrayListdisabledDates = new ArrayList (); 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"); } } }