Android通用索引栏实现代码

偶尔看到之前写过的代码,感觉好多东西几乎在很多项目中都要用到,虽然每个项目的需求和设计都不同,不过实现的效果都是一样的,可能只是数据格式和一些颜色等的细微差距.但是有的时候因为一个小改变,就要去重复的修改代码,麻烦不说,也容易导致新的问题和BUG.

就拿忽然想到的索引栏来说,几乎写过的项目中都用到了,比如城市选择、联系人等等.这些地方全都需要用到索引栏,但是用法都是一样的.翻看了几处之前写过的代码,发现每次用到索引栏,都要重新去写方法来处理数据或者对数据的索引进行提取这些,做法也都大同小异.于是乎,尝试着重构一下这部分,也方便之后的使用.

先看一下效果图:

实现

索引栏的实现,网上有很多例子,也比较简单,就不做过多解释.因为在不同项目中可能涉及到索引栏字体颜色、大小不同等问题,所以把之前用到的代码做一下修改,提取出一些自定义属性,方便修改,就不必每次都去代码中修改,也避免影响到其他人的使用.直接看一下代码,在attr中定义一些自定义属性,如下:

attr:

<?xml version="1.0" encoding="utf-8"?> <resources> <!--SideBar相关--> <!--普通时的颜色--> <attr name="normalColor" format="color"/> <!--选中时的颜色--> <attr name="chooseColor" format="color"/> <!--普通时的背景图--> <attr name="normalBackground" format="reference"/> <!--选中时的背景图--> <attr name="chooseBackground" format="reference"/> <!--索引栏文字大小--> <attr name="sideTextSize" format="dimension"/> <declare-styleable name="SideBar"> <attr name="normalColor"/> <attr name="chooseColor"/> <attr name="normalBackground"/> <attr name="chooseBackground"/> <attr name="sideTextSize"/> </declare-styleable> </resources>

把颜色文字大小等属性提取出来方便修改.然后看一下SideBar

SideBar:

package com.example.junweiliu.commindexdemo.widget; import android.annotation.TargetApi; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.os.Build; import android.util.AttributeSet; import android.util.TypedValue; import android.view.MotionEvent; import android.view.View; import android.widget.TextView; import com.example.junweiliu.commindexdemo.R; /** * Created by junweiliu on 16/11/24. */ public class SideBar extends View { /** * 点击回调 */ private OnTouchingLetterChangedListener onTouchingLetterChangedListener; /** * 26字母 */ public static String[] letterStrs = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "#"}; /** * 当前是否选中 */ private int choose = -1; /** * 字母画笔 */ private Paint paint = new Paint(); /** * 显示的TextView */ private TextView mTextDialog; /** * 普通时的颜色 */ private int normalColor; /** * 选中的颜色 */ private int chooseColor; /** * 普通时的背景 */ private Drawable normalBackground; /** * 选中时的背景 */ private Drawable chooseBackground; /** * 文字大小 */ private float textSize; /** * 边框 */ private Rect mRect; public SideBar(Context context, AttributeSet attrs) { this(context, attrs, 0); } public SideBar(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); // 获取自定义属性 TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SideBar); normalColor = ta.getColor(R.styleable.SideBar_normalColor, Color.GRAY); chooseColor = ta.getColor(R.styleable.SideBar_chooseColor, Color.RED); normalBackground = ta.getDrawable(R.styleable.SideBar_normalBackground); chooseBackground = ta.getDrawable(R.styleable.SideBar_chooseBackground); textSize = ta.getDimension(R.styleable.SideBar_sideTextSize, TypedValue .applyDimension(TypedValue.COMPLEX_UNIT_SP, 13, getResources().getDisplayMetrics())); ta.recycle(); init(); } /** * 为SideBar设置显示字母的TextView * * @param mTextDialog */ public void setTextView(TextView mTextDialog) { this.mTextDialog = mTextDialog; } /** * 设置 * * @param letter */ public void setLetter(String[] letter) { this.letterStrs = letter; invalidate(); requestLayout(); } /** * 初始化参数 */ @TargetApi(Build.VERSION_CODES.JELLY_BEAN) private void init() { paint.setColor(normalColor); paint.setTypeface(Typeface.DEFAULT_BOLD); paint.setAntiAlias(true); paint.setTextSize(textSize); // 获取单个绘制的rect,用于获取单个绘制项的高度 mRect = new Rect(); paint.getTextBounds("A", 0, "A".length(), mRect); } /** * 绘制 * * @param canvas */ protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 获取焦点改变背景颜色. int height = getHeight() - getPaddingTop() - getPaddingBottom();// 获取对应高度 int width = getWidth(); // 获取对应宽度 int singleHeight = height / letterStrs.length;// 获取每一个字母的高度 for (int i = 0; i < letterStrs.length; i++) { // 选中的状态 if (i == choose) { paint.setColor(chooseColor); paint.setFakeBoldText(true); } // x坐标等于中间-字符串宽度的一半. float xPos = width / 2 - paint.measureText(letterStrs[i]) / 2; float yPos = singleHeight * i + singleHeight; canvas.drawText(letterStrs[i], xPos, yPos, paint); paint.reset();// 重置画笔 init(); } } @TargetApi(Build.VERSION_CODES.JELLY_BEAN) @Override public boolean dispatchTouchEvent(MotionEvent event) { final int action = event.getAction(); // 点击的y坐标 final float y = event.getY(); final int oldChoose = choose; final OnTouchingLetterChangedListener listener = onTouchingLetterChangedListener; // 获取当前点击的字母位置,点击位置的y坐标比上总的高度相当于点击的位置比上全部位置(c / b.length = y / getHeight()) final int currChoose = (int) (y / getHeight() * letterStrs.length); switch (action) { case MotionEvent.ACTION_UP: // 重置背景色 if (null != normalBackground) { setBackground(normalBackground); } else { setBackgroundColor(Color.argb(0, 0, 0, 0)); } // 抬起时置为-1 choose = -1; invalidate(); if (mTextDialog != null) { mTextDialog.setVisibility(View.INVISIBLE); } break; default: // 设置背景色 if (null != chooseBackground) { setBackground(chooseBackground); } if (oldChoose != currChoose) { if (currChoose >= 0 && currChoose < letterStrs.length) { if (null != listener) { listener.onTouchingLetterChanged(letterStrs[currChoose]); } if (null != mTextDialog) { mTextDialog.setText(letterStrs[currChoose]); mTextDialog.setVisibility(View.VISIBLE); } // 设置选中的位置为当前位置 choose = currChoose; invalidate(); } } break; } return true; } /** * 向外公开的方法 * * @param onTouchingLetterChangedListener */ public void setOnTouchingLetterChangedListener( OnTouchingLetterChangedListener onTouchingLetterChangedListener) { this.onTouchingLetterChangedListener = onTouchingLetterChangedListener; } /** * 回调接口 * * @author coder */ public interface OnTouchingLetterChangedListener { void onTouchingLetterChanged(String s); } /** * 测量 * * @param widthMeasureSpec * @param heightMeasureSpec */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int widthMode = MeasureSpec.getMode(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int sizeWidth = MeasureSpec.getSize(widthMeasureSpec); int sizeHeight = MeasureSpec.getSize(heightMeasureSpec); // 当高度为自适应时,高度为字母高度*字母数量*2 即间隔为单位高度 int wrapHeight = letterStrs.length * (mRect.height() * 2); // 当宽度为自适应使,宽度为字母宽度*2 int warpWidth = mRect.width() * 2; setMeasuredDimension((widthMode == MeasureSpec.EXACTLY) ? sizeWidth : warpWidth , (heightMode == MeasureSpec.EXACTLY) ? sizeHeight //wrap_content时的高度 : wrapHeight); } }

很简单,只是提取出来了一些自定义属性,没什么可说的,接下来分析一下如何让索引栏变得通用,先来想一下索引栏一般的写法.首先拿到一个数据源,然后对这个数据源进行处理,从数据源中提取出首字母当做索引(当然数据源中可能已经含有首字母或者索引等字段),有了索引之后,再在适配器中进行判断来控制是否显示索引标题(我的做法是判断第一次出现当前索引的数据源位置和当前位置是否相同,如果相同则显示索引标题),处理完索引标题的显示和隐藏,最后就是跟索引栏进行绑定(实现索引栏的回调方法并做相关处理).大体步骤就是这样,接下来就是找一下处理不同的地方,比对了一下,发现问题基本都是出现在数据格式不同上,有的数据的索引字段可能叫Letter,有的可能叫LetterName,这就导致了每次对这些数据进行处理时,都要重新写方法或者修改方法,使得这些方法不共用.那怎么解决一下这个问题呢,最开始想到的是写一个抽象类,然后用一个抽象方法getLetterName()来约束索引.每个需要用到索引栏的Bean都去继承这个抽象类,重写这个抽象方法,从而达到统一约束索引值的效果,也就解决了索引值字段不同的问题,这样就可以用一个公共的方法来处理不同的数据源.后来又考虑了一下,这个地方其实用接口会更加合适一点,接口灵活性更大,而且也是面向接口编程的一种体现.分析了这么多,来具体代码实现一下,提出一个接口,之后所有需要用到索引的数据Bean去实现这个接口中的getLetterName()方法并且重写这个方法来返回索引值即可.

接口SideBase:

package com.example.junweiliu.commindexdemo.bean; /** * Created by junweiliu on 16/11/21. */ public interface SideBase { String getLetterName(); }

然后数据Bean去实现这个接口,例如比较常见的CityBean:

package com.example.junweiliu.commindexdemo.bean; public class CityBean implements SideBase { /** * 城市名 */ private String cityName; /** * 首字母 */ private String cityHeader; /** * 城市信息 */ private String cityMes; public CityBean(String cityName, String cityHeader, String cityMes) { this.cityName = cityName; this.cityHeader = cityHeader; this.cityMes = cityMes; } public String getCityName() { return cityName; } public void setCityName(String cityName) { this.cityName = cityName; } public String getCityHeader() { return cityHeader; } public void setCityHeader(String cityHeader) { this.cityHeader = cityHeader; } public String getCityMes() { return cityMes; } public void setCityMes(String cityMes) { this.cityMes = cityMes; } /** * 获取索引 * * @return */ @Override public String getLetterName() { return cityHeader; } }

在getLetterName()方法中去返回索引值.

接下来就可以去写一些公共的处理方法.比如

/** * 根据当前选中的项获取其第一次出现该项首字母的位置 * * @param position 当前选中的位置 * @param datas 数据源 * @return */ public static int getPositionForSection(int position, List<? extends SideBase> datas) { // 当前选中的项 SideBase sideBase = datas.get(position); for (int i = 0; i < datas.size(); i++) { String firstStr = datas.get(i).getLetterName().toUpperCase(); // 返回第一次出现该项首字母的位置 if (firstStr.equals(sideBase.getLetterName())) { return i; } } return -1; }

因为使用的接口,这里就可以用通配符?的方式来对数据进行处理,只关心和处理getLetterName()方法即可.还可以做其他处理:

/** * 获取所选中的索引在列表中的位置 * * @param list * @param letter * @return */ public static int getLetterPosition(List<? extends SideBase> list, String letter) { int position = -1; if (list != null && !list.isEmpty() && !"".equals(letter)) { for (int i = 0; i < list.size(); i++) { SideBase bean = list.get(i); if (bean.getLetterName().equals(letter)) { position = i; break; } } } return position; } /** * 筛选出数据源中所包含的全部索引值 * * @param list * @return */ public static String[] getLetters(List<? extends SideBase> list) { List<String> letters = new ArrayList<>(); if (list != null && !list.isEmpty()) { for (int i = 0; i < list.size(); i++) { if (!letters.contains(list.get(i).getLetterName())) { letters.add(list.get(i).getLetterName()); } } } return (String[]) letters.toArray(new String[letters.size()]); }

通过分析和重构之后,这些之前不能公用的方法就变得通用起来,很方便,之后用起来也会特别简单、舒心.

完整代码

公共处理类

CommUtil:

package com.example.junweiliu.commindexdemo.util; import com.example.junweiliu.commindexdemo.bean.SideBase; import java.util.ArrayList; import java.util.List; /** * Created by junweiliu on 16/11/24. */ public class CommUtil { /** * 根据当前选中的项获取其第一次出现该项首字母的位置 * * @param position 当前选中的位置 * @param datas 数据源 * @return */ public static int getPositionForSection(int position, List<? extends SideBase> datas) { // 当前选中的项 SideBase sideBase = datas.get(position); for (int i = 0; i < datas.size(); i++) { String firstStr = datas.get(i).getLetterName().toUpperCase(); // 返回第一次出现该项首字母的位置 if (firstStr.equals(sideBase.getLetterName())) { return i; } } return -1; } /** * 获取所选中的索引在列表中的位置 * * @param list * @param letter * @return */ public static int getLetterPosition(List<? extends SideBase> list, String letter) { int position = -1; if (list != null && !list.isEmpty() && !"".equals(letter)) { for (int i = 0; i < list.size(); i++) { SideBase bean = list.get(i); if (bean.getLetterName().equals(letter)) { position = i; break; } } } return position; } /** * 筛选出数据源中所包含的全部索引值 * * @param list * @return */ public static String[] getLetters(List<? extends SideBase> list) { List<String> letters = new ArrayList<>(); if (list != null && !list.isEmpty()) { for (int i = 0; i < list.size(); i++) { if (!letters.contains(list.get(i).getLetterName())) { letters.add(list.get(i).getLetterName()); } } } return (String[]) letters.toArray(new String[letters.size()]); } }

适配器CityAdapter:

package com.example.junweiliu.commindexdemo.adapter; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.TextView; import com.example.junweiliu.commindexdemo.R; import com.example.junweiliu.commindexdemo.bean.CityBean; import com.example.junweiliu.commindexdemo.util.CommUtil; import java.util.List; /** * Created by junweiliu on 16/11/24. */ public class CityAdapter extends BaseAdapter { /** * 上下文 */ private Context context; /** * 布局加载器 */ private LayoutInflater mInflater; /** * 数据源 */ private List<CityBean> cityBeanList; /** * 构造方法 * * @param context * @param cityBeanList */ public CityAdapter(Context context, List<CityBean> cityBeanList) { this.context = context; this.cityBeanList = cityBeanList; } @Override public int getCount() { return cityBeanList.size(); } @Override public Object getItem(int i) { return cityBeanList.get(i); } @Override public long getItemId(int i) { return i; } @Override public View getView(int position, View convertView, ViewGroup viewGroup) { ViewHolder viewHolder = null; CityBean bean = cityBeanList.get(position); if (convertView == null) { convertView = mInflater.from(context).inflate(R.layout.item_city, null); viewHolder = new ViewHolder(); viewHolder.headerTv = (TextView) convertView.findViewById(R.id.tv_item_citys_header); viewHolder.contentTv = (TextView) convertView.findViewById(R.id.tv_item_citys_context); convertView.setTag(viewHolder); } else { viewHolder = (ViewHolder) convertView.getTag(); } // 如果当前位置为第一次出现该类首字母的位置,则显示headerTv if (position == CommUtil.getPositionForSection(position, cityBeanList)) { viewHolder.contentTv.setVisibility(View.VISIBLE); viewHolder.headerTv.setVisibility(View.VISIBLE); viewHolder.headerTv.setText(bean.getLetterName()); } else { viewHolder.headerTv.setVisibility(View.GONE); viewHolder.contentTv.setVisibility(View.VISIBLE); } viewHolder.contentTv.setText(bean.getCityName()); return convertView; } /** * vh */ class ViewHolder { TextView headerTv; TextView contentTv; } }

MainActivity:

package com.example.junweiliu.commindexdemo; import android.app.Activity; import android.os.Bundle; import android.widget.ListView; import android.widget.TextView; import com.example.junweiliu.commindexdemo.adapter.CityAdapter; import com.example.junweiliu.commindexdemo.bean.CityBean; import com.example.junweiliu.commindexdemo.util.CommUtil; import com.example.junweiliu.commindexdemo.widget.SideBar; import java.util.ArrayList; import java.util.List; public class MainActivity extends Activity { /** * 城市列表数据 */ private List<CityBean> cityBeanList = new ArrayList<>(); /** * 城市lv */ private ListView cityList; /** * 索引栏 */ private SideBar mSideBar; /** * 显示的tv */ private TextView mShowTv; /** * 适配器 */ private CityAdapter mCityAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initData(); initView(); } /** * 初始化数据 */ private void initData() { CityBean bean1 = new CityBean("安徽", "A", "安徽故事"); CityBean bean2 = new CityBean("安徽1", "A", "安徽1故事"); CityBean bean3 = new CityBean("安徽2", "A", "安徽2故事"); CityBean bean4 = new CityBean("北京", "B", "北京故事"); CityBean bean5 = new CityBean("北京1", "B", "北京1故事"); CityBean bean6 = new CityBean("北京2", "B", "北京2故事"); CityBean bean7 = new CityBean("重庆", "C", "重庆故事"); CityBean bean8 = new CityBean("重庆1", "C", "重庆1故事"); CityBean bean9 = new CityBean("重庆2", "C", "重庆2故事"); CityBean bean10 = new CityBean("贵州", "G", "贵州故事"); CityBean bean11 = new CityBean("贵州1", "G", "贵州2故事"); CityBean bean12 = new CityBean("贵州2", "G", "贵州3故事"); CityBean bean13 = new CityBean("天津", "T", "天津故事"); CityBean bean14 = new CityBean("天津1", "T", "天津1故事"); CityBean bean15 = new CityBean("天津2", "T", "天津2故事"); cityBeanList.add(bean1); cityBeanList.add(bean2); cityBeanList.add(bean3); cityBeanList.add(bean1); cityBeanList.add(bean2); cityBeanList.add(bean3); cityBeanList.add(bean4); cityBeanList.add(bean5); cityBeanList.add(bean6); cityBeanList.add(bean4); cityBeanList.add(bean5); cityBeanList.add(bean6); cityBeanList.add(bean7); cityBeanList.add(bean8); cityBeanList.add(bean9); cityBeanList.add(bean7); cityBeanList.add(bean8); cityBeanList.add(bean9); cityBeanList.add(bean10); cityBeanList.add(bean11); cityBeanList.add(bean12); cityBeanList.add(bean10); cityBeanList.add(bean11); cityBeanList.add(bean12); cityBeanList.add(bean13); cityBeanList.add(bean14); cityBeanList.add(bean15); cityBeanList.add(bean13); cityBeanList.add(bean14); cityBeanList.add(bean15); } /** * 初始化控件 */ private void initView() { cityList = (ListView) findViewById(R.id.lv_city); mSideBar = (SideBar) findViewById(R.id.sb_city); mShowTv = (TextView) findViewById(R.id.tv_city_show); mCityAdapter = new CityAdapter(MainActivity.this, cityBeanList); cityList.setAdapter(mCityAdapter); // 设置需要显示的索引栏内容 mSideBar.setLetter(CommUtil.getLetters(cityBeanList)); // 设置需要显示的提示框 mSideBar.setTextView(mShowTv); mSideBar.setOnTouchingLetterChangedListener(new SideBar.OnTouchingLetterChangedListener() { @Override public void onTouchingLetterChanged(String s) { int position = CommUtil.getLetterPosition(cityBeanList, s); if (position != -1) { cityList.setSelection(position); } } }); } }

布局文件activity_main:

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout 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" tools:context="com.example.junweiliu.commindexdemo.MainActivity"> <!--城市列表--> <ListView android:id="@+id/lv_city" android:layout_width="match_parent" android:layout_height="match_parent"> </ListView> <!--索引栏--> <com.example.junweiliu.commindexdemo.widget.SideBar android:id="@+id/sb_city" android:layout_width="wrap_content" android:layout_height="200dp" android:layout_alignParentRight="true" android:layout_centerVertical="true" app:sideTextSize="13sp"/> <!--显示的字母--> <TextView android:id="@+id/tv_city_show" android:layout_width="80dp" android:layout_height="80dp" android:layout_centerInParent="true" android:background="#3F51B5" android:gravity="center" android:textColor="#ffffff" android:textSize="25sp" android:visibility="gone" /> </RelativeLayout>

适配器布局item_city:

<?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"> <!-- 索引头 --> <TextView android:id="@+id/tv_item_citys_header" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#E3E3E3" android:padding="15dp" android:text="A" android:textColor="#666666" android:textSize="14sp" android:visibility="gone"/> <!-- 内容 --> <TextView android:id="@+id/tv_item_citys_context" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#ffffff" android:padding="15dp" android:textColor="#000000" android:textSize="14sp" android:visibility="gone"/> </LinearLayout>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

时间: 2024-08-03 10:05:01

Android通用索引栏实现代码的相关文章

Android通用索引栏实现代码_Android

偶尔看到之前写过的代码,感觉好多东西几乎在很多项目中都要用到,虽然每个项目的需求和设计都不同,不过实现的效果都是一样的,可能只是数据格式和一些颜色等的细微差距.但是有的时候因为一个小改变,就要去重复的修改代码,麻烦不说,也容易导致新的问题和BUG. 就拿忽然想到的索引栏来说,几乎写过的项目中都用到了,比如城市选择.联系人等等.这些地方全都需要用到索引栏,但是用法都是一样的.翻看了几处之前写过的代码,发现每次用到索引栏,都要重新去写方法来处理数据或者对数据的索引进行提取这些,做法也都大同小异.于是

老猪带你玩转android自定义控件二——自定义索引栏listview

带索引栏的listview,在android开发非常普遍,方便用户进行字母索引,就像微信通讯录这样:   今天,我们就从零到一实现这个具有索引栏的listview. 怎么实现这个控件了,我们应当梳理出一个思路. ①首先应当将字母的索引栏继承与一个控件,通过ondraw方法将字母画出来. ②然后我们应该监听这个字母控件的ontouch事件,来判断用户到底是按了那个字母. ③就是实现这个索引栏与listview的联动,就是将listview滑动到按下字母的位置. 大体流程图如下:   有了前面铺垫,

Android自定义View实现字母导航栏的代码_Android

思路分析: 1.自定义View实现字母导航栏 2.ListView实现联系人列表 3.字母导航栏滑动事件处理 4.字母导航栏与中间字母的联动 5.字母导航栏与ListView的联动 效果图: 首先,我们先甩出主布局文件,方便后面代码的说明 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/re

Android实现listview滑动时渐隐渐现顶部栏实例代码_Android

我在开发的时候遇到了这样的需求,就是在listview的滑动中,需要对顶部的栏目由透明慢慢的变为不透明的状态,就是以下的效果 最先开始的时候想的很简单,无非就是监听listview的滑动距离,然后根据距离算出透明度的比值,就可以了,但是事实上呢也的确是这样做的 只是在获取listview的滑动距离上可能没法直接获取,需要动态的去计算 下面贴出全部代码吧,不想码字了,最近感冒了,脑袋晕乎乎的,还疼,代码更直观一些 private void initListener() { lvList.setOn

Android 通用型手电筒代码_Android

前几天这边一个小区断电,黑麻麻的,一只猫闯进寝室,把我吓哭,然后就果断写了个手电筒,下次断电,再来,我要吓死它. 我之前看到很多人都是直接调用闪光灯,其实大部分机型都不支持,我这个是用相机功能来实现的,大部分机型都支持. MainActivity.class public class MainActivity extends FragmentActivity { @Override protected void onCreate(Bundle savedInstanceState) { supe

Android程序开发之Fragment实现底部导航栏实例代码_Android

流行的应用的导航一般分为两种,一种是底部导航,一种是侧边栏. 说明 IDE:AS,Android studio; 模拟器:genymotion; 实现的效果,见下图. 具体实现 为了讲明白这个实现过程,我们贴出来的代码多一写,这样更方便理解 [最后还会放出完整的代码实现] .看上图的界面做的比较粗糙,但实现过程的骨架都具有了,想要更完美的设计,之后自行完善吧 ^0^. 布局 通过观察上述效果图,发现任意一个选项页面都有三部分组成: 顶部去除ActionBar后的标题栏: 中间一个Fragment

Android实现沉浸式导航栏实例代码_Android

废话不多说了,直接给大家贴代码了,具体代码如下所示: private SystemBarTintManager tintManager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // getWindow().addFlags(WindowManager.Layo

Android实现沉浸式导航栏实例代码

废话不多说了,直接给大家贴代码了,具体代码如下所示: private SystemBarTintManager tintManager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // getWindow().addFlags(WindowManager.Layo

Android程序开发之Fragment实现底部导航栏实例代码

流行的应用的导航一般分为两种,一种是底部导航,一种是侧边栏. 说明 IDE:AS,Android studio; 模拟器:genymotion; 实现的效果,见下图. 具体实现 为了讲明白这个实现过程,我们贴出来的代码多一写,这样更方便理解 [最后还会放出完整的代码实现] .看上图的界面做的比较粗糙,但实现过程的骨架都具有了,想要更完美的设计,之后自行完善吧 ^0^. 布局 通过观察上述效果图,发现任意一个选项页面都有三部分组成: 顶部去除ActionBar后的标题栏: 中间一个Fragment