Android开发之底部导航实现总结
底部导航有很多种实现方式。目前比较常用的是RadioGroup+Fragment,FragmentTabHost+Fragment,BottomNavigationBar三种方式,下面分别介绍:
一、RadioGroup+Fragment方式:这种方式是最老的实现方式,代码复杂。
1.布局:
<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<FrameLayout
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1.0"
android:background="@color/white" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/view" />
<RadioGroup
android:id="@+id/group_home"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="#4A192F"
android:gravity="center_vertical"
android:orientation="horizontal">
<RadioButton
android:id="@+id/radio_main"
style="@style/home_tab_bottom"
android:checked="true"
android:drawableTop="@drawable/home_tab_main_selector"
android:text="首页"
android:textColor="@color/titlebar_bg"
android:textSize="14sp" />
<RadioButton
android:id="@+id/radio_assortment"
style="@style/home_tab_bottom"
android:drawableTop="@drawable/home_tab_assortment_selector"
android:text="分类"
android:textColor="@color/white"
android:textSize="14sp" />
<RadioButton
android:id="@+id/radio_car"
style="@style/home_tab_bottom"
android:drawableTop="@drawable/home_tab_car_selector"
android:text="购物车"
android:textColor="@color/white"
android:textSize="14sp" />
<RadioButton
android:id="@+id/radio_recommend"
style="@style/home_tab_bottom"
android:drawableTop="@drawable/home_tab_recommend_selector"
android:text="热榜"
android:textColor="@color/white"
android:textSize="14sp" />
<RadioButton
android:id="@+id/radio_my"
style="@style/home_tab_bottom"
android:drawableTop="@drawable/home_tab_my_selector"
android:text="我的"
android:textColor="@color/white"
android:textSize="14sp" />
</RadioGroup>
</LinearLayout>
2.java代码:
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import cn.zmit.bottomnavigationdemo.R;
import cn.zmit.bottomnavigationdemo.fragment.FiveFragment;
import cn.zmit.bottomnavigationdemo.fragment.FourFragment;
import cn.zmit.bottomnavigationdemo.fragment.OneFragment;
import cn.zmit.bottomnavigationdemo.fragment.ThreeFragment;
import cn.zmit.bottomnavigationdemo.fragment.TwoFragment;
/**
* Created by Administrator on 2016/8/9.
* RadioGroup+Fragment
*/
public class OneActivity extends FragmentActivity {
private RadioGroup mRadioGroup;
private RadioButton radio_main;//主页
private RadioButton radio_my;//我的
private RadioButton radio_assortment;//分类
private RadioButton radio_car;//购物车
private RadioButton radio_recommend;//热榜
private OneFragment mOneFragment;//主页
private TwoFragment mTwoFragment;//分类
private ThreeFragment mThreeFragment;//购物车
private FourFragment mFourFragment;//热榜
private FiveFragment mFiveFragment;//我的
private FragmentManager fragmentManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_one);
fragmentManager = getSupportFragmentManager();
init();//获取ID
setTab(1);//设置首页为默认显示
}
/**
* 获取ID
*/
private RadioGroup.OnCheckedChangeListener onCheckedChangeListener;
private int checkId;
private void init() {
mRadioGroup = (RadioGroup) findViewById(R.id.group_home);
radio_main = (RadioButton) findViewById(R.id.radio_main);
radio_my = (RadioButton) findViewById(R.id.radio_my);
radio_assortment = (RadioButton) findViewById(R.id.radio_assortment);
radio_car = (RadioButton) findViewById(R.id.radio_car);
radio_recommend = (RadioButton) findViewById(R.id.radio_recommend);
onCheckedChangeListener = new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
if (checkId != checkedId) {
switch (checkedId) {
case R.id.radio_main:
setTab(1);
changeTab(1);
break;
case R.id.radio_my:
changeTab(5);
setTab(5);
break;
case R.id.radio_assortment:
changeTab(2);
setTab(2);
break;
case R.id.radio_car:
setTab(3);
changeTab(3);
break;
case R.id.radio_recommend:
setTab(4);
changeTab(4);
break;
}
}
checkId = checkedId;
}
};
mRadioGroup.setOnCheckedChangeListener(onCheckedChangeListener);
}
/***
* 切换tab时的变化
*
* @param i
*/
private void changeTab(int i) {
switch (i) {
case 1:
radio_main.setTextColor(getResources().getColor(R.color.titlebar_bg));
radio_my.setTextColor(getResources().getColor(R.color.white));
radio_assortment.setTextColor(getResources().getColor(R.color.white));
radio_recommend.setTextColor(getResources().getColor(R.color.white));
radio_car.setTextColor(getResources().getColor(R.color.white));
break;
case 2:
radio_main.setTextColor(getResources().getColor(R.color.white));
radio_assortment.setTextColor(getResources().getColor(R.color.titlebar_bg));
radio_my.setTextColor(getResources().getColor(R.color.white));
radio_recommend.setTextColor(getResources().getColor(R.color.white));
radio_car.setTextColor(getResources().getColor(R.color.white));
break;
case 3:
radio_main.setTextColor(getResources().getColor(R.color.white));
radio_my.setTextColor(getResources().getColor(R.color.white));
radio_car.setTextColor(getResources().getColor(R.color.titlebar_bg));
radio_recommend.setTextColor(getResources().getColor(R.color.white));
radio_assortment.setTextColor(getResources().getColor(R.color.white));
break;
case 4:
radio_main.setTextColor(getResources().getColor(R.color.white));
radio_my.setTextColor(getResources().getColor(R.color.white));
radio_car.setTextColor(getResources().getColor(R.color.white));
radio_recommend.setTextColor(getResources().getColor(R.color.titlebar_bg));
radio_assortment.setTextColor(getResources().getColor(R.color.white));
break;
case 5:
radio_main.setTextColor(getResources().getColor(R.color.white));
radio_my.setTextColor(getResources().getColor(R.color.titlebar_bg));
radio_car.setTextColor(getResources().getColor(R.color.white));
radio_recommend.setTextColor(getResources().getColor(R.color.white));
radio_assortment.setTextColor(getResources().getColor(R.color.white));
break;
}
}
/***
* 切换tab
*/
private void setTab(int index) {
FragmentTransaction transaction = fragmentManager.beginTransaction();
hideFragments(transaction);
switch (index) {
case 1:
if (mOneFragment == null) {
mOneFragment = new OneFragment();
transaction.add(R.id.content, mOneFragment);
} else {
transaction.show(mOneFragment);
mOneFragment.setUserVisibleHint(true);
}
break;
case 2:
if (mTwoFragment == null) {
mTwoFragment = new TwoFragment();
transaction.add(R.id.content, mTwoFragment);
} else {
transaction.show(mTwoFragment);
mTwoFragment.setUserVisibleHint(true);
}
break;
case 3:
if (mThreeFragment == null) {
mThreeFragment = new ThreeFragment();
transaction.add(R.id.content, mThreeFragment);
} else {
transaction.show(mThreeFragment);
mThreeFragment.setUserVisibleHint(true);
}
break;
case 4:
if (mFourFragment == null) {
mFourFragment = new FourFragment();
transaction.add(R.id.content, mFourFragment);
} else {
transaction.show(mFourFragment);
mFourFragment.setUserVisibleHint(true);
}
break;
case 5:
if (mFiveFragment == null) {
mFiveFragment = new FiveFragment();
transaction.add(R.id.content, mFiveFragment);
} else {
transaction.show(mFiveFragment);
mFiveFragment.setUserVisibleHint(true);
}
break;
}
transaction.commit();
}
private void hideFragments(FragmentTransaction transaction) {
if (mOneFragment != null) {
transaction.hide(mOneFragment);
}
if (mTwoFragment != null) {
transaction.hide(mTwoFragment);
}
if (mThreeFragment != null) {
transaction.hide(mThreeFragment);
}
if (mFourFragment != null) {
transaction.hide(mFourFragment);
}
if (mFiveFragment != null) {
transaction.hide(mFiveFragment);
}
}
}
效果图:
RadioGroup+Fragment方式
二、FragmentTabHost+Fragment:现在常用的实现方式,代码相对简洁一些。
1.布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<FrameLayout
android:id="@+id/realtabcontent"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1" />
<android.support.v4.app.FragmentTabHost
android:id="@android:id/tabhost"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#4A192F">
<FrameLayout
android:id="@android:id/tabcontent"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="0" />
</android.support.v4.app.FragmentTabHost>
</LinearLayout>
tab_item_view布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:id="@+id/imageview"
android:layout_marginTop="5dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:focusable="false"
android:padding="3dp"/>
<TextView
android:id="@+id/textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/tab_text"
android:textSize="14sp"/>
</LinearLayout>
2.java代码:
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTabHost;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.TabHost;
import android.widget.TextView;
import cn.zmit.bottomnavigationdemo.R;
import cn.zmit.bottomnavigationdemo.fragment.FiveFragment;
import cn.zmit.bottomnavigationdemo.fragment.FourFragment;
import cn.zmit.bottomnavigationdemo.fragment.OneFragment;
import cn.zmit.bottomnavigationdemo.fragment.ThreeFragment;
import cn.zmit.bottomnavigationdemo.fragment.TwoFragment;
/**
* Created by Administrator on 2016/8/9.
* FragmentTabHost+Fragment
*/
public class TwoActivity extends FragmentActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_two);
initView();
}
private FragmentTabHost mTabHost;
/**
* 布局填充器
*
*/
private LayoutInflater mLayoutInflater;
/**
* Fragment数组界面
*
*/
private Class mFragmentArray[] = { OneFragment.class, TwoFragment.class,
ThreeFragment.class, FourFragment.class, FiveFragment.class };
/**
* 存放图片数组
*
*/
private int mImageArray[] = { R.drawable.home_tab_main_selector,
R.drawable.home_tab_assortment_selector, R.drawable.home_tab_car_selector,
R.drawable.home_tab_recommend_selector, R.drawable.home_tab_my_selector };
/**
* 选修卡文字
*
*/
private String mTextArray[] = { "首页", "分类", "购物车", "热榜", "我的" };
/**
* 初始化组件
*/
private void initView() {
mLayoutInflater = LayoutInflater.from(this);
// 找到TabHost
mTabHost = (FragmentTabHost) findViewById(android.R.id.tabhost);
mTabHost.setup(this, getSupportFragmentManager(), R.id.realtabcontent);
// 得到fragment的个数
int count = mFragmentArray.length;
for (int i = 0; i &amp;lt; count; i++) {
// 给每个Tab按钮设置图标、文字和内容
TabHost.TabSpec tabSpec = mTabHost.newTabSpec(mTextArray[i])
.setIndicator(getTabItemView(i));
// 将Tab按钮添加进Tab选项卡中
mTabHost.addTab(tabSpec, mFragmentArray[i], null);
}
}
/**
*
* 给每个Tab按钮设置图标和文字
*/
private View getTabItemView(int index) {
View view = mLayoutInflater.inflate(R.layout.tab_item_view, null);
ImageView imageView = (ImageView) view.findViewById(R.id.imageview);
imageView.setBackgroundResource(mImageArray[index]);
TextView textView = (TextView) view.findViewById(R.id.textview);
textView.setText(mTextArray[index]);
return view;
}
}
FragmentTabHost+Fragment方式
三、BottomNavigationBar:最新的实现方式。
在使用之前,需要在Android Studio
1.布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<FrameLayout
android:id="@+id/layFrame"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<com.ashokvarma.bottomnavigation.BottomNavigationBar
android:id="@+id/bottom_navigation_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom" />
</LinearLayout>
2.java代码:
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import com.ashokvarma.bottomnavigation.BottomNavigationBar;
import com.ashokvarma.bottomnavigation.BottomNavigationItem;
import java.util.ArrayList;
import cn.zmit.bottomnavigationdemo.R;
import cn.zmit.bottomnavigationdemo.fragment.AssortmentFragment;
import cn.zmit.bottomnavigationdemo.fragment.CarFragment;
import cn.zmit.bottomnavigationdemo.fragment.MainFragment;
import cn.zmit.bottomnavigationdemo.fragment.MySpaceFragment;
import cn.zmit.bottomnavigationdemo.fragment.RecommendFragment;
/**
* Created by Administrator on 2016/8/9.
* BottomNavigationBar
*/
public class ThreeActivity extends AppCompatActivity implements BottomNavigationBar.OnTabSelectedListener {
private ArrayList<Fragment> fragments;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_three);
BottomNavigationBar bottomNavigationBar = (BottomNavigationBar) findViewById(R.id.bottom_navigation_bar);
bottomNavigationBar.setMode(BottomNavigationBar.MODE_FIXED);
bottomNavigationBar.setBackgroundStyle(BottomNavigationBar.BACKGROUND_STYLE_STATIC);
bottomNavigationBar.setBarBackgroundColor(R.color.bg);
bottomNavigationBar.addItem(new BottomNavigationItem(R.drawable.home_tab_main_selector, "首页"))
.addItem(new BottomNavigationItem(R.drawable.home_tab_assortment_selector, "分类"))
.addItem(new BottomNavigationItem(R.drawable.home_tab_car_selector, "购物车"))
.addItem(new BottomNavigationItem(R.drawable.home_tab_recommend_selector, "热榜"))
.addItem(new BottomNavigationItem(R.drawable.home_tab_my_selector, "我的"))
.setFirstSelectedPosition(0)
.initialise();
fragments = getFragments();
setDefaultFragment();
bottomNavigationBar.setTabSelectedListener(this);
}
/**
* 设置默认的
*/
private void setDefaultFragment() {
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
transaction.replace(R.id.layFrame, MainFragment.newInstance("首页"));
transaction.commit();
}
private ArrayList<Fragment> getFragments() {
ArrayList<Fragment> fragments = new ArrayList<>();
fragments.add(MainFragment.newInstance("首页"));
fragments.add(AssortmentFragment.newInstance("分类"));
fragments.add(CarFragment.newInstance("购物车"));
fragments.add(RecommendFragment.newInstance("热榜"));
fragments.add(MySpaceFragment.newInstance("我的"));
return fragments;
}
@Override
public void onTabSelected(int position) {
if (fragments != null) {
if (position < fragments.size()) {
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
Fragment fragment = fragments.get(position);
if (fragment.isAdded()) {
ft.replace(R.id.layFrame, fragment);
} else {
ft.add(R.id.layFrame, fragment);
}
ft.commitAllowingStateLoss();
}
}
}
@Override
public void onTabUnselected(int position) {
if (fragments != null) {
if (position < fragments.size()) {
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
Fragment fragment = fragments.get(position);
ft.remove(fragment);
ft.commitAllowingStateLoss();
}
}
}
@Override
public void onTabReselected(int position) {
}
}
系统自带的日历虽然好用,但是不符合某些项目的需求,所以需要自定义布局,看网上许多自定义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银行卡输入格式化程序吧,具体如下。
我们在输入银行卡号时希望能按格式显示,而不是单纯显示一堆数字,下面一段代码可实现银行卡号格式化输入。
//银行卡号码的格式
public void bankCardNumAddSpace(final EditText mEditText) {
mEditText.addTextChangedListener(new TextWatcher() {
int beforeTextLength = 0;
int onTextLength = 0;
boolean isChanged = false;
int location = 0;// 记录光标的位置
private char[] tempChar;
private StringBuffer buffer = new StringBuffer();
int konggeNumberB = 0;
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
beforeTextLength = s.length();
if (buffer.length() > 0) {
buffer.delete(0, buffer.length());
}
konggeNumberB = 0;
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == ' ') {
konggeNumberB++;
}
}
}
@Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
onTextLength = s.length();
buffer.append(s.toString());
if (onTextLength == beforeTextLength || onTextLength <= 3
|| isChanged) {
isChanged = false;
return;
}
isChanged = true;
}
@Override
public void afterTextChanged(Editable s) {
if (isChanged) {
location = mEditText.getSelectionEnd();
int index = 0;
while (index < buffer.length()) {
if (buffer.charAt(index) == ' ') {
buffer.deleteCharAt(index);
} else {
index++;
}
}
index = 0;
int konggeNumberC = 0;
while (index < buffer.length()) {
if ((index == 4 || index == 9 || index == 14 || index == 19)) {
buffer.insert(index, ' ');
konggeNumberC++;
}
index++;
}
if (konggeNumberC > konggeNumberB) {
location += (konggeNumberC - konggeNumberB);
}
tempChar = new char[buffer.length()];
buffer.getChars(0, buffer.length(), tempChar, 0);
String str = buffer.toString();
if (location > str.length()) {
location = str.length();
} else if (location < 0) {
location = 0;
}
mEditText.setText(str);
Editable etable = mEditText.getText();
Selection.setSelection(etable, location);
isChanged = false;
}
}
});
}
这里包含了一些基本的并且常用的跳转工具。
这是需要的对应的权限。
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
代码:
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore;
import android.provider.Settings;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
import java.io.File;
import frame.zmit.cn.publicutils.R;
/**
* Created by joy on 2016/7/21.
* 工具集合
*/
public class MainActivity extends AppCompatActivity {
private String mImagePath;//返回的图片路径
private final static int REQUEST_CODE_GALLERY = 0x11;
private final static int REQUEST_CODE_CAMERA = 0x12;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/**
* 打开微信
*/
findViewById(R.id.btn_open_weixin).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = getPackageManager().getLaunchIntentForPackage("com.tencent.mm");
startActivity(intent);
}
});
/**
* 跳转到QQ聊天界面
*/
findViewById(R.id.btn_open_qq).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String mQqNumber = "98*****08";
String url11 = "mqqwpa://im/chat?chat_type=wpa&uin=" + mQqNumber + "&version=10";
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url11)));
}
});
/**
* 跳转到联系人界面
*/
findViewById(R.id.btn_people_interface).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setClassName("com.android.contacts", "com.android.contacts.activities.PeopleActivity");
startActivity(intent);
}
});
/**
* 跳转到拨号界面
*/
findViewById(R.id.btn_telephone_interface).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String phone = "157*****737";
Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + phone));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
});
/**
* 直接拨打电话
*/
findViewById(R.id.btn_telephone).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String phone = "157*****737";
Intent intentPhone = new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + phone));
startActivity(intentPhone);
}
});
/**
* 跳转到短信界面
*/
findViewById(R.id.btn_message_interface).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setType("vnd.android-dir/mms-sms");
startActivity(intent);
}
});
/**
* 跳转到短信界面
* 指定号码和短信内容
*/
findViewById(R.id.btn_message).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String phone = "157*****737";
String message = "这是一个自定义的内容";
Intent intent = new Intent(Intent.ACTION_SENDTO, Uri.parse("smsto:" + phone));
intent.putExtra("sms_body", message);
startActivity(intent);
}
});
/**
* 跳转到设置界面
*/
findViewById(R.id.btn_setting_interface).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(Settings.ACTION_SETTINGS);
startActivity(intent);
}
});
/**
* 跳转到蓝牙界面
*/
findViewById(R.id.btn_bluetooth_interface).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(Settings.ACTION_BLUETOOTH_SETTINGS);
startActivity(intent);
}
});
/**
* 调用浏览器
*/
findViewById(R.id.btn_browser).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction("android.intent.action.VIEW");
Uri content_url = Uri.parse("http://www.baidu.com");
intent.setData(content_url);
startActivity(intent);
}
});
/**
* 打开照相机
*/
findViewById(R.id.btn_camera).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mImagePath = chooseImageFromCamera(MainActivity.this, REQUEST_CODE_CAMERA, "cameraImage");
}
});
/**
* 打开相册并获取图片地址
*/
findViewById(R.id.btn_gallery).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_PICK, null);
intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
startActivityForResult(intent, REQUEST_CODE_GALLERY);
}
});
}
public String chooseImageFromCamera(Activity activity, int requestCode, String imageName) {
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
File file = new File(Environment.getExternalStorageDirectory() + "/Images");
if (!file.exists()) {
file.mkdirs();
}
String savePath = Environment.getExternalStorageDirectory() + "/Images/" + imageName + String.valueOf(System.currentTimeMillis()) + ".jpg";
Uri mUri = Uri.fromFile(
new File(savePath));
cameraIntent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, mUri);
cameraIntent.putExtra("return-data", true);
activity.startActivityForResult(cameraIntent, requestCode);
return savePath;
}
public String onActivityResultForChooseImageFromGallery(
Context context, int requestCode, int resultCode, Intent data) {
String imagePath = null;
if (data != null) {
if ("file".equals(data.getData().getScheme())) {
/** 有些低版本机型返回的Uri模式为file*/
imagePath = data.getData().getPath();
} else {
Uri selectedImage = data.getData();
String[] filePathColumn = {MediaStore.Images.Media.DATA};
Cursor cursor = context.getContentResolver().query(selectedImage,
filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
imagePath = cursor.getString(columnIndex);
cursor.close();
}
return imagePath;
} else {
return null;
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case REQUEST_CODE_GALLERY:
mImagePath = onActivityResultForChooseImageFromGallery(MainActivity.this,
requestCode, resultCode, data);
if (mImagePath != null && mImagePath.length() > 0) {
Toast.makeText(MainActivity.this, mImagePath, Toast.LENGTH_SHORT).show();
}
break;
case REQUEST_CODE_CAMERA:
if (mImagePath != null && mImagePath.length() > 0) {
Toast.makeText(MainActivity.this, mImagePath, Toast.LENGTH_SHORT).show();
}
break;
}
}
}
自定义View经常会画文字,那么就可能需要获取文字的高度,这里介绍一种好用的方法:
public double getTxtHeight(Paint mPaint) {
Paint.FontMetrics fm = mPaint.getFontMetrics();
return Math.ceil(fm.descent - fm.ascent);
}
参数为Paint,就是你画文字的画笔,效果如下
canvas.drawText("测试文字", 300, 300, mPaint);
canvas.drawText("文字的高度为:" + getTxtHeight(mPaint) + "px", 300, 400, mPaint);
相关文章
- 下面我们来看一篇关于Android子控件超出父控件的范围显示出来方法,希望这篇文章能够帮助到各位朋友,有碰到此问题的朋友可以进来看看哦。 <RelativeLayout xmlns:an...2016-10-02
Android开发中findViewById()函数用法与简化
findViewById方法在android开发中是获取页面控件的值了,有没有发现我们一个页面控件多了会反复研究写findViewById呢,下面我们一起来看它的简化方法。 Android中Fin...2016-09-20- 如果我们的项目需要做来电及短信的功能,那么我们就得在Android模拟器开发这些功能,本来就来告诉我们如何在Android模拟器上模拟来电及来短信的功能。 在Android模拟...2016-09-20
- 夜神android模拟器如何设置代理呢?对于这个问题其实操作起来是非常的简单,下面小编来为各位详细介绍夜神android模拟器设置代理的方法,希望例子能够帮助到各位。 app...2016-09-20
- 为了增强android应用的用户体验,我们可以在一些Button按钮上自定义动态的设置一些样式,比如交互时改变字体、颜色、背景图等。 今天来看一个通过重写Button来动态实...2016-09-20
- 如果我们要在Android应用APP中加载html5页面,我们可以使用WebView,本文我们分享两个WebView加载html5页面实例应用。 实例一:WebView加载html5实现炫酷引导页面大多...2016-09-20
- 深入理解Android中View和ViewGroup从组成架构上看,似乎ViewGroup在View之上,View需要继承ViewGroup,但实际上不是这样的。View是基类,ViewGroup是它的子类。本教程我们深...2016-09-20
- 这篇文章主要介绍了iOS新版微信底部返回横条问题的解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-06-30
- 下面我们来看一篇关于Android自定义WebView网络视频播放控件开发例子,这个文章写得非常的不错下面给各位共享一下吧。 因为业务需要,以下代码均以Youtube网站在线视...2016-10-02
- java开发的Android应用,性能一直是一个大问题,,或许是Java语言本身比较消耗内存。本文我们来谈谈Android 性能优化之MemoryFile文件读写。 Android匿名共享内存对外A...2016-09-20
- TextView默认是横着显示了,今天我们一起来看看Android设置TextView竖着显示如何来实现吧,今天我们就一起来看看操作细节,具体的如下所示。 在开发Android程序的时候,...2016-10-02
android.os.BinderProxy cannot be cast to com解决办法
本文章来给大家介绍关于android.os.BinderProxy cannot be cast to com解决办法,希望此文章对各位有帮助呀。 Android在绑定服务的时候出现java.lang.ClassCastExc...2016-09-20- 这篇文章主要介绍了Android 实现钉钉自动打卡功能的步骤,帮助大家更好的理解和学习使用Android,感兴趣的朋友可以了解下...2021-03-15
- 下面我们来看一篇关于Android 开发之布局细节对比:RTL模式 ,希望这篇文章对各位同学会带来帮助,具体的细节如下介绍。 前言 讲真,好久没写博客了,2016都过了一半了,赶紧...2016-10-02
- 首先如果要在程序中使用sdcard进行存储,我们必须要在AndroidManifset.xml文件进行下面的权限设置: 在AndroidManifest.xml中加入访问SDCard的权限如下: <!--...2016-09-20
- 下面来给各位简单的介绍一下关于Android开发之PhoneGap打包及错误解决办法,希望碰到此类问题的同学可进入参考一下哦。 在我安装、配置好PhoneGap项目的所有依赖...2016-09-20
- 这篇文章主要介绍了iOS新版微信底部工具栏遮挡问题完美解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-06-30
- 这篇文章主要为大家详细介绍了使用jQuery.Pin垂直滚动时固定导航的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2017-05-27
用Intel HAXM给Android模拟器Emulator加速
Android 模拟器 Emulator 速度真心不给力,, 现在我们来介绍使用 Intel HAXM 技术为 Android 模拟器加速,使模拟器运行度与真机比肩。 周末试玩了一下在Eclipse中使...2016-09-20- 在安卓开发时我碰到一个问题就是需要实现全屏,但又需要我们来判断出用户是使用了全屏或非全屏了,下面我分别找了两段代码,大家可参考。 先来看一个android屏幕全屏实...2016-09-20