SuperLoadingProgress
#简介
昨天在简书上看到一篇文章,介绍了一个加载动画的实现过程
[一款Loading动画的实现思路(一)](http://www.jianshu.com/p/1c6a2de68753#)
只可惜原动画是**IOS**上制作的,而看了一下,作者的实现思路比较复杂,于是趁着空闲写了一个**Android版本**,这篇文章将给大家介绍一下实现过程。
首先让我们来看一下动画效果
![这里写图片描述](http://img.blog.csdn.net/20151211230809602)
android粒子爆炸
#简介 最近在闲逛的时候,发现了一款**粒子爆炸特效**的控件,觉得比较有意思,效果也不错。 但是代码不好扩展,也就是说如果要提供不同的爆炸效果,需要修改的地方比较多。于是我对源代码进行了一些**重构**,将爆炸流程和粒子运动分离。 对于源码,大家可以参考以下链接
粒子爆炸特效
#简介 最近在闲逛的时候,发现了一款**粒子爆炸特效**的控件,觉得比较有意思,效果也不错。 但是代码不好扩展,也就是说如果要提供不同的爆炸效果,需要修改的地方比较多。于是我对源代码进行了一些**重构**,将爆炸流程和粒子运动分离。 对于源码,大家可以参考以下链接
雷达图(蜘蛛网图)
#简介
最近因为项目需求,要实现一款雷达图来表示用户的各种成就值
雷达图的绘制很简单,只要思路清晰按部就班的绘制就可以了,其中使用得最多,是**路径path类**的使用,使用这个类可以让我们更加方便地绘制出**正多边形**等效果。
效果图如下:
制作粒子爆炸特效
#简介
最近在闲逛的时候,发现了一款**粒子爆炸特效**的控件,觉得比较有意思,效果也不错。
但是代码不好扩展,也就是说如果要提供不同的爆炸效果,需要修改的地方比较多。于是我对源代码进行了一些**重构**,将爆炸流程和粒子运动分离。
对于源码,大家可以参考以下链接
模仿手机QQ红点消除功能
#简介
手机QQ红点消除的功能大家应该印象很深,我一直奇怪微信为什么不跟进这个功能,毕竟消息太多。
功能图如下:
![这里写图片描述](http://img.blog.csdn.net/20151118101649390)
简单的功能描述是这样的:**新消息到来以后,会出现红点,红点被拉扯,在短距离内出现粘连效果,到达一点距离以后,可以扯断粘连,松手消除红点。**
对于这个功能是怎么实现的呢,我一直很好奇,并且参考了一下两篇文章:
NineoldAndroids
#简介
[NineoldAndroids](https://github.com/JakeWharton/NineOldAndroids)是Github上一个著名的动画库,简单来说,**NineOldAndroids是一个向下兼容的动画库,主要是使低于API 11的系统也能够使用View的属性动画**。
网上已经有一些文章,介绍了这个库的设计,包括类结构和思想,例如
ListView的多选模式
#ListView的多选需求
需求驱动技术,最近在项目中又遇到这样一个需求,简单而言就是:**遍历某个文件夹下的所有log文件,然后将它们通过微信发送给别人。**
这个功能很容易实现,但是在实现过程中,我希望自己的产品使用起来更加的人性化,所有我添加了**多文件压缩打包功能,多选,反选,全选等功能**,这样使用者就可以更加合理选择自己需要的log了。
那么问题来了,**ListView应该怎么实现多选功能呢?**
<br><br>
TextView自适应
#TextView问题由来
TextView在中英文夹杂的时候,会出现自动断行的情况,相信许多人都碰见过。这是系统的一个Bug,在Android5.0以后被修复了,而5.0以下的还没有见到比较好的解决版本。
参考了网上的方法,有的朋友推荐使用全角和半角转换(没有解决问题),也有的推荐了JustifyTextView这个控件(效果也不理想)。
于是我决定自定义一个TextView来做这件事,勉强解决了问题,但是代价是失去了很多TextView自身拥有的特性,而且TextView自身做了很多缓存和优化的工作,Google强烈不建议我们去修改这个控件。
我们先来看看实现效果:
通用Adapter
通过对Adapter的简单封装,我们大大减少了自定义Adapter过程中的麻烦。网上实现多布局Adapter的设计,都是以单个布局Adapter为基类,然后提供一个辅助类来实现多布局。
Volley加载本地图片
volley加载网络图片
众所周知volley提供了一个ImageLoader类用于网络图片的加载,本质上也是用消息队列的那一套去进行图片请求,只是请求以后做了一些图片本地缓存、缩放、错位处理等内容。
下面我们来看一个简单的加载例子:
settings.jar
在Android Studio上快速导入Eclipse风格
接收广播的最高优先级
@SuppressLint("NewApi")
public class MainActivity extends Activity {
SmsReceiver myReceiver;
Button btn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = (Button) findViewById(R.id.btn);
btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
test();
}
});
}
public void test(){
Cursor cursor = null;
String defaultSmsApp = Telephony.Sms.getDefaultSmsPackage(this);
Intent intent = new Intent(Sms.Intents.ACTION_CHANGE_DEFAULT);
intent.putExtra(Sms.Intents.EXTRA_PACKAGE_NAME, this.getPackageName());
startActivity(intent);
try {
cursor = getContentResolver().query(Uri.parse("content://sms/inbox"), new String[] { "_id", "address", "read" }, "read = ? ", new String[] {"0" }, "date desc");
if (cursor != null) {
ContentValues values = new ContentValues();
values.put("read", "1");
for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
Log.v("cky", "" + cursor.getInt(cursor.getColumnIndex("_id")) + " , " + cursor.getString(cursor.getColumnIndex("address")));
int res = getContentResolver().update(Uri.parse("content://sms/inbox"), values, "_id=?", new String[] { "" + cursor.getInt(cursor.getColumnIndex("_id")) });
Log.i("cky","geng xin = "+res);
}
}
intent = new Intent(Sms.Intents.ACTION_CHANGE_DEFAULT);
intent.putExtra(Sms.Intents.EXTRA_PACKAGE_NAME, defaultSmsApp);
startActivity(intent);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (cursor != null) {
cursor.close();
cursor = null;
}
}
}
}
CircleIndicator
/**
* Created by kaiyi.cky on 2015/8/17.
*/
public class CircleIndicator extends LinearLayout implements ViewPager.OnPageChangeListener{
private ViewPager mViewPager;
ViewPager.OnPageChangeListener mListener;
private final static int SCROLL_WHAT = 99;
MyHandler myHandler;
/**
* 滚动间隔时间
*/
private int spentTime = 3000;
/**
* 当前显示的序号
*/
private int curIndex = 1;
/**
* 圆点半径
*/
private int circleRadiu = 10;
/**
* 圆点内边距
*/
private int circlePadding = 3;
/**
* 圆点数目
*/
private int circleCount = 0;
/**
* 滑动方向
* 1为向右,-1为向左
*/
private int direction = 1;
public CircleIndicator(Context context) {
super(context);
init();
}
public CircleIndicator(Context context, AttributeSet attrs) {
super(context, attrs);
init();
SVGPathView
/**
* PathView is an View that animate paths.
*/
public class PathView extends View {
/**
* Logging tag.
*/
public static final String LOG_TAG = "PathView";
/**
* The paint for the path.
*/
private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
/**
* Utils to catch the paths from the svg.
*/
private final SvgUtils svgUtils = new SvgUtils(paint);
/**
* All the paths provided to the view. Both from Path and Svg.
*/
private List<SvgUtils.SvgPath> paths = new ArrayList<SvgUtils.SvgPath>(0);
/**
* This is a lock before the view is redrawn
* or resided it must be synchronized with this object.
*/
private final Object mSvgLock = new Object();
/**
* Thread for working with the object above.
EventBus代码
public class EventBus {
HashMap<Class<?>,ArrayList<Subscription>> subscriptionsByEventType =
new HashMap<Class<?>,ArrayList<Subscription>>();
MainThreadHandler mainThreadHandler = new MainThreadHandler(this,Looper.getMainLooper());
AsyThreadHandler asyThreadHandler = new AsyThreadHandler(this);
private final static EventBus instance = new EventBus();
public static EventBus getInstance(){
return instance;
}
private EventBus(){};
VerticalScrollView
/**
* Created by kaiyi.cky on 2015/8/5.
* 跑马灯控件
*/
public class VerticalScrollView extends ScrollView{
private LinearLayout mLinearLayout;
/**
* 当前显示的序号
*/
private int curIndex = 1;
/**
* 滚动方向
* 1为向下,-1为向上
*/
private int direction = 1;
/**
PullScrollView
/**
* Created by kaiyi.cky on 2015/7/24.
*/
public class PullBlurScrollView extends ScrollView {
/**头部**/
private View mHeader;
/**主体**/
private View mContentView;
/** 模糊图片 **/
private BlurDrawable mBlurDrawable;
/** 阻尼系数,越小阻力就越大. */
private static final float SCROLL_RATIO = 0.5f;
/** 当前头部状态 */
private State mState = State.NORMAL;
/** 头部总高度 */
private int mHeaderHeight;
/** 头部可视高 */
private int mHeaderVisibleHeight;
/** 头部图片初始顶部和底部. */
private int mInitTop, mInitBottom;
/** 头部图片拖动时顶部和底部. */
private int mCurrentTop, mCurrentBottom;
/** 首次点击的Y坐标. */
private PointF mStartPoint = new PointF();
/** ScrollView的content view矩形,用于记录content的初始位置情况 */
private Rect mContentRect = new Rect();
/** 是否移动到顶部位置. */
private boolean isTop = false;
/** 是否关闭ScrollView的滑动. */
private boolean mEnableTouch = false;
/** 是否开始移动. */
private boolean isMoving = false;
private enum State {
/**顶部*/
UP,
/**底部*/
DOWN,
/**正常*/
NORMAL
}
public PullBlurScrollView(Context context) {
super(context);
init(context,null);
}
DrawerArrowDrawable
/** A drawable that rotates between a drawer icon and a back arrow based on parameter. */
public class DrawerArrowDrawable extends Drawable {
/**
* Joins two {@link Path}s as if they were one where the first 50% of the path is {@code
* PathFirst} and the second 50% of the path is {@code pathSecond}.
* 合并两个路径,前50%为路径1,后50%为路径2
*/
private static class JoinedPath {
private final PathMeasure measureFirst;
private final PathMeasure measureSecond;
private final float lengthFirst;
private final float lengthSecond;
private JoinedPath(Path pathFirst, Path pathSecond) {
//PathMeasure类用于提供路径上的点坐标
measureFirst = new PathMeasure(pathFirst, false);
measureSecond = new PathMeasure(pathSecond, false);
lengthFirst = measureFirst.getLength();
lengthSecond = measureSecond.getLength();
}
CircularProgressButton
package com.example.androidtest.view;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.StateListDrawable;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.util.StateSet;
import android.widget.Button;
import com.example.androidtest.R;
public class CircularProgressButton extends Button {
/**
* 状态代号
* 0为初始状态,-1失败状态,100为完成状态,50为不明确中间状态
*/
public static final int IDLE_STATE_PROGRESS = 0;
public static final int ERROR_STATE_PROGRESS = -1;
public static final int SUCCESS_STATE_PROGRESS = 100;
public static final int INDETERMINATE_STATE_PROGRESS = 50;
/**
* 背景StrokeGradientDrawable
* A Drawable with a color gradient for buttons, backgrounds, etc.
* It can be defined in an XML file with the element.
*/
private StrokeGradientDrawable background;
/**
* 环形动画背景
*/
private CircularAnimatedDrawable mAnimatedDrawable;
/**
* 环形进度背景
*/
private CircularProgressDrawable mProgressDrawable;
/**
* ColorStateList对象可以在XML中定义,像color一样使用,它能根据它应用到的View对象的状态实时改变颜色
* 当每次状态改变时,StateList都会从上到下遍历一次,第一个匹配当前状态的item将被使用——选择的过程不是基于“最佳匹配”,
* 只是符合state的最低标准的第一个item。
*/
private ColorStateList mIdleColorState;
/**
* 完成状态ColorStateList
*/
private ColorStateList mCompleteColorState;
/**
* 失败状态ColorStateList
*/
private ColorStateList mErrorColorState;
/**
* 用于根据状态改变drawable
* 初始状态背景
*/
private StateListDrawable mIdleStateDrawable;
xlistview代码
/**
* @file XListView.java
* @package me.maxwin.view
* @create Mar 18, 2012 6:28:41 PM
* @author Maxwin
* @description An ListView support (a) Pull down to refresh, (b) Pull up to load more.
* Implement IXListViewListener, and see stopRefresh() / stopLoadMore().
*/
package com.example.androidtest.view;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.view.animation.DecelerateInterpolator;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.Scroller;
import android.widget.TextView;
import com.example.androidtest.R;
public class XListView extends ListView implements OnScrollListener {
private float mLastY = -1; // save event y
/**
* 用于下拉后,滑动返回
*/
private Scroller mScroller; // used for scroll back
private OnScrollListener mScrollListener; // user's scroll listener
// the interface to trigger refresh and load more.
private IXListViewListener mListViewListener;
/**
* 下拉头部
*/
datepicker
datepicker源代码.
public class NumberPicker extends View {
//基本设置
/**
* picker宽度
*/
private int mWidth;
/**
* picker高度
*/
private int mHeight;
/**
* 声效
*/
private Sound mSound;
/**
* 是否开启声效
*/
private boolean mSoundEffectEnable = true;