起始页+fragment底部导航栏+ViewPager滑动切换+个人信息界面示例安卓app
上篇写了起始页、底部导航栏和滑动切换界面,这篇写的是个人信息界面的一个小示例。
如果想看上篇笔记,传送门在这里~~
android app安卓应用实例:起始页+fragment底部导航栏+ViewPager滑动切换+个人信息界面(一)
来!
先上效果图~
参考了网上一些大佬的代码和界面,简单地做了一个安卓app的个人信息的基本界面,基于Android studio。
这里先感谢写Android菜鸟教程的那位大哥,在他的教程里我学到了很多东西,我把这篇写下来,一来想写个笔记,二来希望能和大家一起交流学习,如有错误,还请多多指教~
=============================
个人信息这里包括 昵称、性别、年龄、身高、体重
需要自己准备的图片:一张你喜欢的头像,一张箭头符号图片
先来个布局界面~
fg_info.xml
<?xml version=\"1.0\" encoding=\"utf-8\"?><ScrollView xmlns:android=\"http://schemas.android.com/apk/res/android\"android:layout_width=\"match_parent\"android:layout_height=\"match_parent\"android:background=\"@color/bg_white\"><LinearLayoutxmlns:app=\"http://schemas.android.com/apk/res-auto\"android:orientation=\"vertical\"android:layout_width=\"match_parent\"android:layout_height=\"match_parent\"android:background=\"@color/bg_white\"android:weightSum=\"1\"><com.example.asus.huadong.CircleImageViewandroid:layout_width=\"80dp\"android:layout_height=\"120dp\"android:src=\"@mipmap/myprofile\"app:type=\"circle\"android:layout_gravity=\"center\"android:layout_marginBottom=\"10dp\"android:layout_marginTop=\"10dp\" /><Viewstyle=\"@style/BigDivider\"/><FrameLayoutandroid:layout_width=\"match_parent\"android:layout_height=\"wrap_content\"><TextViewstyle=\"@style/text_item\"android:text=\"佛性人生c\"android:layout_gravity=\"center_vertical|right\"android:layout_marginRight=\"40dp\"android:id=\"@+id/my_name\" /><ImageViewandroid:layout_width=\"wrap_content\"android:layout_height=\"wrap_content\"android:src=\"@mipmap/setting_arrow\"android:layout_gravity=\"center_vertical|right\"android:layout_marginRight=\"20dp\" /><Buttonstyle=\"@style/info_item\"android:text=\"昵称\"android:id=\"@+id/myname\" /></FrameLayout><Viewstyle=\"@style/BigDivider\"/><FrameLayoutandroid:layout_width=\"match_parent\"android:layout_height=\"wrap_content\"><TextViewstyle=\"@style/text_item\"android:text=\"男\"android:layout_gravity=\"center_vertical|right\"android:layout_marginRight=\"40dp\"android:id=\"@+id/my_gender\" /><ImageViewandroid:layout_width=\"wrap_content\"android:layout_height=\"wrap_content\"android:src=\"@mipmap/setting_arrow\"android:layout_gravity=\"center_vertical|right\"android:layout_marginRight=\"20dp\" /><Buttonstyle=\"@style/info_item\"android:text=\"性别\"android:id=\"@+id/mygender\" /></FrameLayout><Viewstyle=\"@style/HorizonTalDivider\"/><FrameLayoutandroid:layout_width=\"match_parent\"android:layout_height=\"wrap_content\"><TextViewstyle=\"@style/text_item\"android:text=\"0 岁\"android:layout_gravity=\"center_vertical|right\"android:layout_marginRight=\"40dp\"android:id=\"@+id/my_old\" /><ImageViewandroid:layout_width=\"wrap_content\"android:layout_height=\"wrap_content\"android:src=\"@mipmap/setting_arrow\"android:layout_gravity=\"center_vertical|right\"android:layout_marginRight=\"20dp\" /><Buttonstyle=\"@style/info_item\"android:text=\"年龄\"android:id=\"@+id/myold\" /></FrameLayout><Viewstyle=\"@style/HorizonTalDivider\"/><FrameLayoutandroid:layout_width=\"match_parent\"android:layout_height=\"wrap_content\"><TextViewstyle=\"@style/text_item\"android:text=\"50 厘米\"android:layout_gravity=\"center_vertical|right\"android:layout_marginRight=\"40dp\"android:id=\"@+id/my_tall\" /><ImageViewandroid:layout_width=\"wrap_content\"android:layout_height=\"wrap_content\"android:src=\"@mipmap/setting_arrow\"android:layout_gravity=\"center_vertical|right\"android:layout_marginRight=\"20dp\" /><Buttonstyle=\"@style/info_item\"android:text=\"身高\"android:id=\"@+id/mytall\" /></FrameLayout><Viewstyle=\"@style/HorizonTalDivider\"/><FrameLayoutandroid:layout_width=\"match_parent\"android:layout_height=\"wrap_content\"><TextViewstyle=\"@style/text_item\"android:text=\"10 公斤\"android:layout_gravity=\"center_vertical|right\"android:layout_marginRight=\"40dp\"android:id=\"@+id/my_weight\" /><ImageViewandroid:layout_width=\"wrap_content\"android:layout_height=\"wrap_content\"android:src=\"@mipmap/setting_arrow\"android:layout_gravity=\"center_vertical|right\"android:layout_marginRight=\"20dp\" /><Buttonstyle=\"@style/info_item\"android:text=\"体重\"android:id=\"@+id/myweight\"/></FrameLayout></LinearLayout></ScrollView>
上面用到的CircleImageView的代码,就是一个圆形图像,作为头像会比较好看,感谢写Android菜鸟教程的大哥给的示例,他是这么写的:
CircleImageView.java
package com.example.asus.huadong;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Bitmap;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.PorterDuff;import android.graphics.PorterDuffXfermode;import android.graphics.RectF;import android.graphics.Xfermode;import android.graphics.drawable.Drawable;import android.util.AttributeSet;import android.widget.ImageView;import java.lang.ref.WeakReference;public class CircleImageView extends ImageView {private Paint mPaint;private Xfermode mXfermode = new PorterDuffXfermode(PorterDuff.Mode.DST_IN);private Bitmap mMaskBitmap;private WeakReference<Bitmap> mWeakBitmap;//图片相关的属性private int type; //类型,圆形或者圆角public static final int TYPE_CIRCLE = 0;public static final int TYPE_ROUND = 1;private static final int BODER_RADIUS_DEFAULT = 10; //圆角默认大小值private int mBorderRadius; //圆角大小public CircleImageView(Context context) {this(context, null);}public CircleImageView(Context context, AttributeSet attrs) {super(context, attrs);mPaint = new Paint();mPaint.setAntiAlias(true);//取出attrs中我们为View设置的相关值TypedArray tArray = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView);mBorderRadius = tArray.getDimensionPixelSize(R.styleable.CircleImageView_Radius, BODER_RADIUS_DEFAULT);type = tArray.getInt(R.styleable.CircleImageView_type, TYPE_CIRCLE);tArray.recycle();}public CircleImageView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);if (type == TYPE_CIRCLE) {int width = Math.min(getMeasuredWidth(), getMeasuredHeight());setMeasuredDimension(width, width); //设置当前View的大小}}@Overrideprotected void onDraw(Canvas canvas) {//在缓存中取出bitmapBitmap bitmap = mWeakBitmap == null ? null : mWeakBitmap.get();if (bitmap == null || bitmap.isRecycled()) {//获取图片宽高Drawable drawable = getDrawable();int width = drawable.getIntrinsicWidth();int height = drawable.getIntrinsicHeight();if (drawable != null) {bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);Canvas drawCanvas = new Canvas(bitmap);float scale = 1.0f;if (type == TYPE_ROUND) {scale = Math.max(getWidth() * 1.0f / width, getHeight()* 1.0f / height);} else {scale = getWidth() * 1.0F / Math.min(width, height);}//根据缩放比例,设置bounds,相当于缩放图片了drawable.setBounds(0, 0, (int) (scale * width),(int) (scale * height));drawable.draw(drawCanvas);if (mMaskBitmap == null || mMaskBitmap.isRecycled()) {mMaskBitmap = getBitmap();}mPaint.reset();mPaint.setFilterBitmap(false);mPaint.setXfermode(mXfermode);//绘制形状drawCanvas.drawBitmap(mMaskBitmap, 0, 0, mPaint);//bitmap缓存起来,避免每次调用onDraw,分配内存mWeakBitmap = new WeakReference<Bitmap>(bitmap);//绘制图片canvas.drawBitmap(bitmap, 0, 0, null);mPaint.setXfermode(null);}}if (bitmap != null) {mPaint.setXfermode(null);canvas.drawBitmap(bitmap, 0.0f, 0.0f, mPaint);return;}}//缓存Bitmap,避免每次OnDraw都重新分配内存与绘图@Overridepublic void invalidate() {mWeakBitmap = null;if (mWeakBitmap != null) {mMaskBitmap.recycle();mMaskBitmap = null;}super.invalidate();}//定义一个绘制形状的方法private Bitmap getBitmap() {Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(),Bitmap.Config.ARGB_8888);Canvas canvas = new Canvas(bitmap);Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); //抗锯齿paint.setColor(Color.BLACK);if (type == TYPE_ROUND) {canvas.drawRoundRect(new RectF(0, 0, getWidth(), getHeight()),mBorderRadius, mBorderRadius, paint);} else {canvas.drawCircle(getWidth() / 2, getWidth() / 2, getWidth() / 2, paint);}return bitmap;}}
fg_info.xml里还用到了一些图片,自己找照片放到mipmap里就ok,color也自定义加到values里的color里就ok,然后用到的styles的代码我贴一下,大家也可以自定义,加到styles文件里就行。
<style name=\"HorizonTalDivider\"><item name=\"android:layout_width\">match_parent</item><item name=\"android:layout_height\">1dp</item><item name=\"android:layout_marginLeft\">10dp</item><item name=\"android:layout_marginRight\">10dp</item><item name=\"android:background\">@color/div_white</item></style><style name=\"BigDivider\"><item name=\"android:layout_width\">match_parent</item><item name=\"android:layout_height\">8dp</item><item name=\"android:background\">@color/div_white</item></style>
重点来咯
MyInfo.java
package com.example.asus.huadong;import android.app.AlertDialog;import android.support.v4.app.Fragment;import android.content.Context;import android.content.DialogInterface;import android.os.Bundle;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.Button;import android.widget.EditText;import android.widget.ScrollView;import android.widget.TextView;public class MyInfo extends Fragment {@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {View view = inflater.inflate(R.layout.fg_info,null);return view;}private ScrollView myscroll;private Button changename;private Button chosegender;private Button choseold;private Button chosetall;private Button choseweight;private String strname;private SPUtils shh;private Context mContext;private Context myContext;private AlertDialog alert = null;private AlertDialog.Builder builder = null;@Overridepublic void onActivityCreated(Bundle savedInstanceState) {super.onActivityCreated(savedInstanceState);myContext = getActivity();mContext = getActivity().getApplicationContext();bindViews();}private void bindViews() {myscroll = (ScrollView) getActivity().findViewById(R.id.myscroll);//mname= (EditText)getActivity().findViewById(R.id.edname);changename = (Button)getActivity().findViewById(R.id.myname);changename.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {AlertDialog.Builder builder = new AlertDialog.Builder(myContext,AlertDialog.THEME_DEVICE_DEFAULT_LIGHT);builder.setTitle(\"昵称\");// 通过LayoutInflater来加载一个xml的布局文件作为一个View对象View view = LayoutInflater.from(myContext).inflate(R.layout.dialog, null);// 设置我们自己定义的布局文件作为弹出框的Contentbuilder.setView(view);final EditText mname = (EditText) view.findViewById(R.id.edname);builder.setPositiveButton(\"确定\",new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {//确定操作的内容strname=mname.getText().toString();shh.put(mContext, \"name\", strname);TextView myn=(TextView) getActivity().findViewById(R.id.my_name);myn.setText(\"\" + shh.get(mContext, \"name\", \"佛系人生c\"));}});builder.setNegativeButton(\"取消\",new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {// TODO Auto-generated method stub}});builder.show();}});chosegender = (Button)getActivity().findViewById(R.id.mygender);chosegender.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {final String[] gender = new String[]{\"男\", \"女\"};alert = null;builder = new AlertDialog.Builder(myContext,AlertDialog.THEME_DEVICE_DEFAULT_LIGHT);int i;if(shh.get(mContext, \"gender\", \"男\")==\"男\"){i=0;}else{i=1;}alert = builder.setTitle(\"性别\").setSingleChoiceItems(gender, i, new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {//Toast.makeText(getActivity(), \"你的性别是\" + gender[which], Toast.LENGTH_SHORT).show();shh.put(mContext, \"gender\", gender[which]);TextView myg = (TextView) getActivity().findViewById(R.id.my_gender);myg.setText(\"\" + shh.get(mContext, \"gender\", \"男\"));alert.dismiss();}}).create();alert.show();}});choseold = (Button)getActivity().findViewById(R.id.myold);choseold.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {int size = 151;// 定义数组final String[] old = new String[size];for(int x = 0; x < 151; x = x+1) {old[x]=x+\" 岁\";}int o= (int)(shh.get(mContext, \"oldwhich\", 0));alert = null;builder = new AlertDialog.Builder(myContext,AlertDialog.THEME_DEVICE_DEFAULT_LIGHT);builder.setView(myscroll);alert = builder.setTitle(\"年龄\").setSingleChoiceItems(old, o, new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {shh.put(mContext, \"old\", old[which]);shh.put(mContext, \"oldwhich\", which);TextView myo = (TextView) getActivity().findViewById(R.id.my_old);myo.setText(\"\" + shh.get(mContext, \"old\", \"0 岁\"));alert.dismiss();}}).create();alert.show();}});chosetall = (Button)getActivity().findViewById(R.id.mytall);chosetall.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {int size = 201;// 定义数组final String[] tall = new String[size];for(int x = 50; x < 251; x = x+1) {tall[x-50]=x+\" 厘米\";}int j= (int)(shh.get(mContext, \"tallwhich\", 0));alert = null;builder = new AlertDialog.Builder(myContext,AlertDialog.THEME_DEVICE_DEFAULT_LIGHT);builder.setView(myscroll);alert = builder.setTitle(\"身高\").setSingleChoiceItems(tall, j, new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {// Toast.makeText(getActivity(), \"你的身高是\" + tall[which], Toast.LENGTH_SHORT).show();shh.put(mContext, \"tall\", tall[which]);shh.put(mContext, \"tallwhich\", which);TextView myt = (TextView) getActivity().findViewById(R.id.my_tall);myt.setText(\"\" + shh.get(mContext, \"tall\", \"50 厘米\"));alert.dismiss();}}).create();alert.show();}});choseweight = (Button)getActivity().findViewById(R.id.myweight);choseweight.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {int size = 241;// 定义数组int k= (int)(shh.get(mContext, \"weightwhich\", 0));final String[] weight = new String[size];for (int x = 10; x < 251; x = x + 1) {weight[x - 10] = x + \" 公斤\";}alert = null;builder = new AlertDialog.Builder(myContext,AlertDialog.THEME_DEVICE_DEFAULT_LIGHT);builder.setView(myscroll);alert = builder.setTitle(\"体重\").setSingleChoiceItems(weight, k, new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {// Toast.makeText(getActivity(), \"你的体重是\" + weight[which], Toast.LENGTH_SHORT).show();shh.put(mContext, \"weight\", weight[which]);shh.put(mContext, \"weightwhich\", which);TextView myw = (TextView) getActivity().findViewById(R.id.my_weight);myw.setText(\"\" + shh.get(mContext, \"weight\", \"10 公斤\"));alert.dismiss();}}).create();alert.show();}});}@Overridepublic void onStart() {super.onStart();TextView myn=(TextView) getActivity().findViewById(R.id.my_name);myn.setText(\"\" + shh.get(mContext, \"name\", \"佛系人生c\"));TextView myo = (TextView) getActivity().findViewById(R.id.my_old);myo.setText(\"\" + shh.get(mContext, \"old\", \"0 岁\"));TextView myg=(TextView) getActivity().findViewById(R.id.my_gender);TextView myt=(TextView) getActivity().findViewById(R.id.my_tall);TextView myw=(TextView) getActivity().findViewById(R.id.my_weight);myg.setText(\"\"+shh.get(mContext, \"gender\",\"男\"));myt.setText(\"\"+shh.get(mContext, \"tall\",\"50 厘米\"));myw.setText(\"\"+shh.get(mContext, \"weight\",\"10 公斤\"));}}
上面用到了SharedPreference工具类是那位写Android入门教程的大哥在教程里提供的,详细可以看一下他的讲解,百度一下Android菜鸟教程就有啦,是这样的:
SPUtils.java
package com.example.asus.huadong;import android.content.Context;import android.content.SharedPreferences;import java.util.Map;public class SPUtils {public static final String FILE_NAME = \"my_sp\";public static void put(Context context, String key, Object obj) {SharedPreferences sp = context.getSharedPreferences(FILE_NAME, context.MODE_PRIVATE);SharedPreferences.Editor editor = sp.edit();if (obj instanceof Boolean) {editor.putBoolean(key, (Boolean) obj);} else if (obj instanceof Float) {editor.putFloat(key, (Float) obj);} else if (obj instanceof Integer) {editor.putInt(key, (Integer) obj);} else if (obj instanceof Long) {editor.putLong(key, (Long) obj);} else {editor.putString(key, (String) obj);}editor.commit();}/*** 获取指定数据*/public static Object get(Context context, String key, Object defaultObj) {SharedPreferences sp = context.getSharedPreferences(FILE_NAME, context.MODE_PRIVATE);if (defaultObj instanceof Boolean) {return sp.getBoolean(key, (Boolean) defaultObj);} else if (defaultObj instanceof Float) {return sp.getFloat(key, (Float) defaultObj);} else if (defaultObj instanceof Integer) {return sp.getInt(key, (Integer) defaultObj);} else if (defaultObj instanceof Long) {return sp.getLong(key, (Long) defaultObj);} else if (defaultObj instanceof String) {return sp.getString(key, (String) defaultObj);}return null;}/*** 删除指定数据*/public static void remove(Context context, String key) {SharedPreferences sp = context.getSharedPreferences(FILE_NAME, context.MODE_PRIVATE);SharedPreferences.Editor editor = sp.edit();editor.remove(key);editor.commit();}/*** 返回所有键值对*/public static Map<String, ?> getAll(Context context) {SharedPreferences sp = context.getSharedPreferences(FILE_NAME, context.MODE_PRIVATE);Map<String, ?> map = sp.getAll();return map;}/*** 删除所有数据*/public static void clear(Context context) {SharedPreferences sp = context.getSharedPreferences(FILE_NAME, context.MODE_PRIVATE);SharedPreferences.Editor editor = sp.edit();editor.clear();editor.commit();}/*** 检查key对应的数据是否存在*/public static boolean contains(Context context, String key) {SharedPreferences sp = context.getSharedPreferences(FILE_NAME, context.MODE_PRIVATE);return sp.contains(key);}}
对话框示例效果图,可以修改昵称,性别、年龄、体重。
第一次使用默认值,第一次修改后的数据将保存在共享偏好中,下次打开就可以默认读取共享偏好里的数据啦~
适合用于个人信息,那种基本不变的信息存储,应该就像默认登陆一样的感觉吧哈哈
emmmmm大概就是这样吧,如果有哪里写错了,请多多指教,我这边运行是ok的,笔记完成!!!