在APP开发的过程中,不免会遇到加载WebView的情况,一般我们都会固定WebView不能左右滑动但可以上下滑动,有时候界面加载出来之后他的格式跟原网页一模一样,那么就会带来一个问题:整体缩小。真实近视眼的悲哀啊,那么我们就需要放大倍数,但是不能左右滑动,这时候格式就会被灵活的打乱,不影响网页的阅读,这个神奇的属性就是:
webView.setInitialScale(220);
里面的参数是可以自己设置的,你可以根据计算不同手机屏幕的宽度和高度来设置不同的倍数,那么显示效果就会更加兼容了
下面我们来看一篇关于android开妇这自定义View之使用TextPaint使\n等符号生效的例子,这个是换行符号了,希望此文章对各位有帮助。同学们现在或以后自定义View画文字的时候,肯定会需要将文字换行,大家都知道\n,那么我们来画试一下:
canvas.drawText("这里是测试换行符\n第二行",300,300,mPaint);
如何解决呢?使用TextPaint:
private TextPaint mPaint;
实例化方式与Paint一致(本来就是Paint的儿子)
接下来:
StaticLayout layout = new StaticLayout("这里是测试换行符\n第二行", mPaint,
(int) mPaint.measureText("这里是测试换行符\n第二行"), Layout.Alignment.ALIGN_NORMAL, 1.0F, 0.0F, true);
canvas.translate(300,300);
layout.draw(canvas);
效果:
自定义布局的日历这个在一些注册网站用到的比较多了,下面我们来看一段小编整理的Android 自定义布局的日历代码,希望下面的内容对各位有用。
系统自带的日历虽然好用,但是不符合某些项目的需求,所以需要自定义布局,看网上许多自定义View完成自定义日历的,
自认水平不够,无法驾驭,所以采用gridview来实现。
效果
CalendarUtils:(获取当前年月对应的数据数组)
package kyle.com.zujian;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
/**
* Created by kyle on 2016/8/12 0012.
* 获取某年某月的日期,界面上第一天为周日
* 通过传的年和月,获取对应年月的日期和第一天是周几
*/
public class CalendarUtils {
private static int FIRST_DAY_OF_WEEK;//第一天
private static Calendar calendar;//日历
public static List<DateEntity> getDate(int year, int month) {
if (year <= 0 || month < 1 || month > 12) {
return new ArrayList<>();//当年和月不符合规则时,返回空list
}
List<DateEntity> dates = new ArrayList<>();
calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, year);//设置年
calendar.set(Calendar.MONTH, month - 1);//设置月
calendar.set(Calendar.DAY_OF_MONTH, 1);//设置第一天
FIRST_DAY_OF_WEEK = calendar.get(Calendar.DAY_OF_WEEK) - 1;//获得第一天是周几 0:周日 6周六
for (int i = 0; i < FIRST_DAY_OF_WEEK; i++) {//假设是周日则跳过,假设不是周日,就添加对应数目的空白item
DateEntity entity = new DateEntity();
dates.add(entity);
}
int count = checkDays(year, month);//获取当前年月的天数
for (int i = 0; i < count; i++) {
DateEntity entity2 = new DateEntity(year, month, i + 1);
dates.add(entity2);
}
return dates;
}
/***
* 判断当前年月有多少天
*
* @param year
* @param month
* @return
*/
private static int checkDays(int year, int month) {
if (year < 1 || month > 12 || month < 1) {
return 0;
}
switch (month) {
case 2:
if (year % 4 == 0) {
return 29;
} else {
return 28;
}
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
return 31;
case 4:
case 6:
case 9:
case 11:
return 30;
}
return 0;
}
}
实体类:DateEntity
package kyle.com.zujian;
/**
* Created by Administrator on 2016/8/9 0009.
*/
public class DateEntity {
private int year;
private int month;
private int day;
@Override
public String toString() {
return "DateEntity{" +
"year=" + year +
", month=" + month +
", day=" + day +
'}';
}
public DateEntity(){
}
public DateEntity( int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public int getMonth() {
return month;
}
public void setMonth(int month) {
this.month = month;
}
public int getDay() {
return day;
}
public void setDay(int day) {
this.day = day;
}
}
CalendarGridView:(自定义的gridview,把代码转移到这里面,方便调用.)
package kyle.com.zujian;
import android.content.Context;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
/**
* Created by kyle on 2016/8/15 0015.
* 自定义日历gridview
*/
public class CalendarGridView extends GridView {
private Context mContext;
private List<DateEntity> mList = new ArrayList<>();
private MyAdapter mAdapter;
private Calendar calendar;
/***
* 今天
*/
private int NOW_YEAR;//当前年
private int NOW_MONTH;//当前月
private int NOW_DAY;//当前日
public CalendarGridView(Context context) {
super(context, null);
mContext = context;
}
public CalendarGridView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
calendar = Calendar.getInstance();//获取日历实例
NOW_YEAR = calendar.get(Calendar.YEAR);//当前年
NOW_MONTH = calendar.get(Calendar.MONTH) + 1;//当前月
NOW_DAY = calendar.get(Calendar.DAY_OF_MONTH);//当前日
mAdapter = new MyAdapter();//实例化和设置适配器
setAdapter(mAdapter);
}
public void init(int year, int month) {
if (year < 1 || month < 1 || month > 12) {
Toast.makeText(mContext, "年份或月份错误!", Toast.LENGTH_SHORT).show();
return;
}
mList.clear();
for (DateEntity entity : CalendarUtils.getDate(year, month)) {
mList.add(entity);
}
mAdapter.notifyDataSetChanged();
}
private class MyAdapter extends BaseAdapter {
@Override
public int getCount() {
return mList.size();
}
@Override
public Object getItem(int position) {
return mList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
MyHolder holder;
if (convertView == null) {
convertView = View.inflate(mContext, R.layout.item_grid, null);
holder = new MyHolder();
holder.llMain = (LinearLayout) convertView.findViewById(R.id.ll_main);
holder.tvDate = (TextView) convertView.findViewById(R.id.tv_date);
holder.tvCount = (TextView) convertView.findViewById(R.id.tv_count);
convertView.setTag(holder);
} else {
holder = (MyHolder) convertView.getTag();
}
int year = mList.get(position).getYear();
int month = mList.get(position).getMonth();
int day = mList.get(position).getDay();
if (year == NOW_YEAR && month == NOW_MONTH && day == NOW_DAY) {
holder.llMain.setBackgroundResource(R.color.red);
holder.tvDate.setTextColor(ContextCompat.getColor(mContext, R.color.white));
holder.tvCount.setTextColor(ContextCompat.getColor(mContext, R.color.white));
} else {
holder.llMain.setBackgroundResource(R.color.white);
holder.tvDate.setTextColor(ContextCompat.getColor(mContext, R.color.black));
holder.tvCount.setTextColor(ContextCompat.getColor(mContext, R.color.black));
}
if (day != 0) {
holder.tvDate.setText(mList.get(position).getDay() + "");
} else {
holder.tvDate.setText("");
}
return convertView;
}
}
private class MyHolder {
private LinearLayout llMain;
private TextView tvDate;
private TextView tvCount;
}
}
在Activity里面这样调用:
CalendarGridView mGv= (CalendarGridView) findViewById(R.id.gv);
mGv.init(2016,8);
当然,布局和实体类都可以自己去根据需求写,而如果想要真正的日历功能,则可以使用viewpager+fragment实现了
下面我们一起来看一篇关于Android 用户登录 cookie 管理设计与实现例子,希望这篇文章能够帮助到各位朋友。功能需求
基本上每个社交 APP 都有其账号体系或者是允许允许用户第三方登录。用户登录成功后,APP 应该记录用户登录状态,用户退出后再登录就不再需要输入密码与账号了。
实现设计
服务端登录成功后返回注册用户信息
客户端在成功回调中将用户信息持久化记录到硬盘中
使用数据库存储用户信息,这里我使用了第三方库 ActiveAndroid
对 Bean 类进行封装,对用户敏感信息进行加密
每次登录时预先检查用户是否登录,如是,直接跳过登录界面
在 Application 类中维持一个用户登录状态的应用,便于程序动态调用
RESTful 接口
代码如下 | 复制代码 |
服务端 // local ['email', 'password', 'is_third'] // third ['uid', 'is_third'] @Table(name = "account") private final static int NO_ACCOUNT = 0; @Expose public AccountBean(User user){ public static void cacheAccountInfo(User user){ public static void logoutAccount(){ public static boolean existAccountCache(){ public static long getAccountID(){ public static List<AccountBean> getAllAccounts(){ } |
移动端Application 子类
代码如下 | 复制代码 |
public class ColorTalkApp extends Application { public static AccountBean sAccount = null; public static int getLoginedUserID(){ } |
服务端 UserRepository
代码如下 | 复制代码 |
public function loginIntoSystem($payload){ private function localAccountRegister($email, $password){ private function thirdAccountRegister($uid){ |
服务端 User 类
代码如下 | 复制代码 |
public static function isAccountRegistered($email) public static function isThirdAccountRegisted($uid){ public static function isAccountValid($email, $password) public static function isThirdAccountValid($uid) public static function getThirdUserByUid($uid){ public static function getLocalUserByEmail($email){ |
缘由
RecyclerView item可以实现滑动的监听,可以允许用户左滑动右滑动消失,也允许用户点击item。 分别需要重载onTouch与onClick方法,但两者时间会冲突,onClick会消费掉事件,导致事件不会传递到onTouch中。解决方法是将onClick的逻辑移动到onTouch中。
判定条件
参考资料1,使用了时间与移动距离两个变量要确保用户的确是想要点击item。满足这个条件将会调用onClick里的逻辑,否则滑动逻辑将被调用。时间控制在1s内, 思路是在ACTION_DOWN中记一个按下按钮的时间,在ACTION_UP判断是否ACTION_UP到ACTION_DOWN需要的时间小不小于1s;距离是衡量值是从ViewConfiguration这个类中取出来的,是安卓推荐的数据。
具体代码
private static final int MAX_CLICK_DURATION = 1000;
private int mSlop;
private long pressStartTime;
private float pressedX;
private float pressedY;
...
ViewConfiguration vc = ViewConfiguration.get(builder.mRecyclerView.getContext());
mSlop = vc.getScaledTouchSlop();
...
case MotionEvent.ACTION_DOWN: {
pressStartTime = System.currentTimeMillis();
pressedX = motionEvent.getX();
pressedY = motionEvent.getY();
...
case MotionEvent.ACTION_UP: {
long pressDuration = System.currentTimeMillis() - pressStartTime;
if (pressDuration < MAX_CLICK_DURATION && distance(pressedX, pressedY, motionEvent.getX(), motionEvent.getY()) < mSlop) {
mItemClickCallback.onClick(mRecyclerView.getChildPosition(mDownView));
return true;
}