码迷,mamicode.com
首页 > 其他好文 > 详细

通用系列 —— 快速搭建设置界面

时间:2016-05-07 08:12:25      阅读:142      评论:0      收藏:0      [点我收藏+]

标签:

【关键词】

设置界面 通用系列 

【问题】

· 减少重复性代码,快速搭建设置界面(通过简单的配置,就可以达到想要的布局);


【效果图】

技术分享技术分享

【分析】

· 设置界面大同小异,无非由标题,内容,图标等元素组成; 
· 既然每一个设置项都有Title,那么就用Title的strId来作为它的唯一标识(便于点击等处理); 
· 复杂的地方在分割线的处理方式上(是整行显示,还是不要显示,又或者是在图像后面显示); 
· 继承自LinearLayout,要可以添加分割线,可以添加tips提示;

【解决方案】
  • 参考下方「用法展示」和「源代码 」

【代码】
  • 简单用法代码展示
  1. 添加字符串资源:<string name="app_name_0">用户名</string>
  2. 设置Activity的布局文件:
<?xml version="1.0" encoding="utf-8"?>
<com.lyloou.android.view.SettingLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/svg_set"
android:background="#dedede"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" />
  1. 配置Item并添加Item到SettingLayout:
// 找到SettingLayout
SettingLayout sl = (SettingLayout) findViewById(R.id.svg_set);
SettingLayout.Item item_0 = new SettingLayout.Item(int titleStrId, int iconResId, String contentStr, String unitStr, boolean hasToRight, SEP sep,IClickListener listener);
sl.addItem(item_0);
// 也可以对item_0 进行单独的设置最后通过`sl.refreshItem(item_0)`来使设置生效;
  1. Item参数对应关系: 
    技术分享技术分享

  • 效果图的具体代码 *

★ 定义文字资源(strings.xml)

<resources>
<string name="app_name">Lou</string>
 
<string name="app_name_0">用户名</string>
<string name="app_name_0_1">身高</string>
<string name="app_name_0_2">体重</string>
 
<string name="app_name_1">双卡和网络</string>
<string name="app_name_2">无线网络</string>
<string name="app_name_3">蓝牙</string>
<string name="app_name_4">其他连接方式</string>
 
<string name="app_name_5">通知栏和状态栏</string>
<string name="app_name_6">声音和振动</string>
<string name="app_name_7">免打扰</string>
 
<string name="app_name_8">系统音效</string>
<string name="app_name_9">触摸反馈</string>
<string name="app_name_10">短信铃声</string>
 
<string name="app_name_11">朋友圈</string>
<string name="app_name_12">扫一扫</string>
<string name="app_name_13">摇一摇</string>
<string name="app_name_14">购物</string>
<string name="app_name_15">游戏</string>
</resources>

★ 设置布局文件(activity_setting.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="#dedede" >
<com.lyloou.android.view.SettingLayout
android:id="@+id/svg_set"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" />
</ScrollView>

★ 引用文字资源并设置对应Item属性

public class MainActivity2 extends LouActivity {
private Activity mContext;
 
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_setting);
mContext = this;
initView();
}
 
private void initView() {
SettingLayout.IClickListener listener = new SettingLayout.IClickListener() {
@Override
public void click(SettingLayout layout, SettingLayout.Item item) {
switch (item.titleStrId) {
case R.string.app_name_0:
ChangeNameActivity.startActivity(mContext, layout, item);
break;
case R.string.app_name_1:
item.contentStr = "双卡";
break;
case R.string.app_name_2:
item.contentStr = "关闭";
break;
case R.string.app_name_3:
item.contentStr = "已开启";
break;
case R.string.app_name_8:
item.contentStr = "静音";
break;
}
layout.refreshItem(item);
Utoast.show(mContext, "点击了:" + mContext.getString(item.titleStrId));
}
};
SettingLayout.Item item_0 = new SettingLayout.
Item(R.string.app_name_0, R.mipmap.ic_launcher, "楼", null, true, SettingLayout.SEP.AFTERICON, listener);
SettingLayout.Item item_0_1 = new SettingLayout.
Item(R.string.app_name_0_1, R.mipmap.ic_launcher, "177", "CM", true, SettingLayout.SEP.AFTERICON, listener);
SettingLayout.Item item_0_2 = new SettingLayout.
Item(R.string.app_name_0_2, R.mipmap.ic_launcher, "60", "KG", true, SettingLayout.SEP.NO, listener);
 
SettingLayout.Item item_1 = new SettingLayout.
Item(R.string.app_name_1, R.mipmap.ic_launcher, null, null, true, SettingLayout.SEP.AFTERICON, listener);
SettingLayout.Item item_2 = new SettingLayout.
Item(R.string.app_name_2, R.mipmap.ic_launcher, null, null, true, SettingLayout.SEP.AFTERICON, listener);
SettingLayout.Item item_3 = new SettingLayout.
Item(R.string.app_name_3, R.mipmap.ic_launcher, null, null, true, SettingLayout.SEP.AFTERICON, listener);
SettingLayout.Item item_4 = new SettingLayout.
Item(R.string.app_name_4, R.mipmap.ic_launcher, null, null, true, SettingLayout.SEP.NO, listener);
SettingLayout.Item item_5 = new SettingLayout.
Item(R.string.app_name_5, R.mipmap.ic_launcher, null, null, true, SettingLayout.SEP.AFTERICON, listener);
SettingLayout.Item item_6 = new SettingLayout.
Item(R.string.app_name_6, R.mipmap.ic_launcher, null, null, true, SettingLayout.SEP.AFTERICON, listener);
SettingLayout.Item item_7 = new SettingLayout.
Item(R.string.app_name_7, R.mipmap.ic_launcher, null, null, true, SettingLayout.SEP.NO, listener);
SettingLayout.Item item_8 = new SettingLayout.
Item(R.string.app_name_8, 0, null, null, true, SettingLayout.SEP.FILL, listener);
SettingLayout.Item item_9 = new SettingLayout.
Item(R.string.app_name_9, 0, null, null, true, SettingLayout.SEP.FILL, listener);
SettingLayout.Item item_10 = new SettingLayout.
Item(R.string.app_name_10, 0, null, null, true, SettingLayout.SEP.NO, listener);
SettingLayout.Item item_11 = new SettingLayout.
Item(R.string.app_name_11, R.mipmap.ic_launcher, null, null, false, SettingLayout.SEP.NO, listener);
SettingLayout.Item item_12 = new SettingLayout.
Item(R.string.app_name_12, R.mipmap.ic_launcher, null, null, false, SettingLayout.SEP.FILL, listener);
SettingLayout.Item item_13 = new SettingLayout.
Item(R.string.app_name_13, R.mipmap.ic_launcher, null, null, false, SettingLayout.SEP.NO, listener);
SettingLayout.Item item_14 = new SettingLayout.
Item(R.string.app_name_14, R.mipmap.ic_launcher, null, null, false, SettingLayout.SEP.FILL, listener);
SettingLayout.Item item_15 = new SettingLayout.
Item(R.string.app_name_15, R.mipmap.ic_launcher, null, null, false, SettingLayout.SEP.NO, listener);
 
SettingLayout s = (SettingLayout) findViewById(R.id.svg_set);
s.addSpace(Uscreen.dp2Px(this, 12));
s.addHeadTips("个人信息");
s.addItem(item_0);
s.addItem(item_0_1);
s.addItem(item_0_2);
 
s.addSpace(Uscreen.dp2Px(this, 12));
s.addHeadTips("无线和网络");
s.addItem(item_1);
s.addItem(item_2);
s.addItem(item_3);
s.addItem(item_4);
s.addSpace(Uscreen.dp2Px(this, 24));
 
s.addHeadTips("提示和通知");
s.addItem(item_5);
s.addItem(item_6);
s.addItem(item_7);
s.addSpace(Uscreen.dp2Px(this, 12));
 
s.addHeadTips("反馈");
s.addItem(item_8);
s.addItem(item_9);
s.addItem(item_10);
s.addSpace(Uscreen.dp2Px(this, 24));
 
s.addHeadTips("微信");
s.addItem(item_11);
s.addSpace(Uscreen.dp2Px(this, 12));
s.addItem(item_12);
s.addItem(item_13);
s.addSpace(Uscreen.dp2Px(this, 12));
s.addItem(item_14);
s.addItem(item_15);
s.addSpace(Uscreen.dp2Px(this, 48));
s.addSpace(Uscreen.dp2Px(this, 12));
}
}

通用源代码

  1. 布局代码(item_setting_layout.xml)
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="48dp"
android:background="#ffffff"
android:paddingEnd="16dp"
android:paddingStart="16dp" >
<ImageView
android:id="@+id/iv_set_icon"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:contentDescription="@string/app_name"
android:padding="14dp"
android:visibility="gone" />
<TextView
android:id="@+id/tv_set_title"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_toEndOf="@+id/iv_set_icon"
android:ellipsize="end"
android:gravity="center_vertical"
android:maxLines="1"
android:text="标题"
android:textSize="14sp" />
<ImageView
android:id="@+id/iv_set_to_right"
android:layout_width="14dp"
android:layout_height="14dp"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_marginStart="4dp"
android:background="@mipmap/ic_go"
android:visibility="gone" />
<TextView
android:id="@+id/tv_set_unit"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_toStartOf="@id/iv_set_to_right"
android:ellipsize="end"
android:gravity="center_vertical"
android:maxLines="1"
android:text="单位"
android:textSize="14sp"
android:visibility="gone" />
<TextView
android:id="@+id/tv_set_content"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_toStartOf="@id/tv_set_unit"
android:ellipsize="end"
android:gravity="center_vertical"
android:maxLines="1"
android:text="内容"
android:textSize="14sp"
android:visibility="gone" />
<View
android:id="@+id/v_set_divider"
android:layout_width="match_parent"
android:layout_height="0.1dp"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:background="#999999"
android:visibility="gone" />
</RelativeLayout>
  1. 自定义的继承自LinearLayout的SettingLayout(SettingLayout.java)
package com.lyloou.android.view;
 
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Color;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Space;
import android.widget.TextView;
 
import com.lyloou.android.R;
import com.lyloou.android.util.Uscreen;
import com.lyloou.android.util.Uview;
 
 
public class SettingLayout extends LinearLayout {
private Context mContext;
private SparseArray<View> mItemViews;
 
public SettingLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mContext = context;
mItemViews = new SparseArray<View>();
}
 
public SettingLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
 
public SettingLayout(Context context) {
this(context, null);
}
 
 
public SettingLayout addItem(Item item) {
// 对参数进行判断()
if (item == null) {
throw new IllegalArgumentException("item为空");
}
if (mItemViews.get(item.titleStrId) != null) {
throw new IllegalArgumentException("此Item项已存在,请不要重复添加");
}
// 从布局中加载得到视图;
@SuppressLint("InflateParams")
View v = LayoutInflater.from(mContext).inflate(R.layout.item_setting_layout, null);
addView(v, new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, Uscreen.dp2Px(mContext, 48)));
// 添加到SparseArray中,便于后期进行其他操作;
mItemViews.put(item.titleStrId, v);
refreshItem(item);
return this;
}
 
public SettingLayout refreshItem(final Item item) {
if (item == null) {
throw new NullPointerException("Item为空");
}
 
View v = mItemViews.get(item.titleStrId);
if (v == null) {
throw new IllegalArgumentException("尚未添加此Item, 请先通过addItem方法添加");
}
 
ImageView ivIcon = (ImageView) v.findViewById(R.id.iv_set_icon);
TextView tvTitle = (TextView) v.findViewById(R.id.tv_set_title);
TextView tvContent = (TextView) v.findViewById(R.id.tv_set_content);
TextView tvUnit = (TextView) v.findViewById(R.id.tv_set_unit);
ImageView ivToRight = (ImageView) v.findViewById(R.id.iv_set_to_right);
View vDivider = v.findViewById(R.id.v_set_divider);
// 根据数据初始化视图
if (item.iconResId != 0) {
ivIcon.setVisibility(View.VISIBLE);
ivIcon.setImageResource(item.iconResId);
}
tvTitle.setText(item.titleStrId);
if (!TextUtils.isEmpty(item.contentStr)) {
tvContent.setVisibility(View.VISIBLE);
tvContent.setText(item.contentStr);
}
if (!TextUtils.isEmpty(item.unitStr)) {
tvUnit.setVisibility(View.VISIBLE);
tvUnit.setText(item.unitStr);
}
if (item.hasToRight) {
ivToRight.setVisibility(View.VISIBLE);
}
if (item.sep == SEP.FILL) {
vDivider.setVisibility(View.VISIBLE);
} else if (item.sep == SEP.AFTERICON) {
vDivider.setVisibility(View.VISIBLE);
ViewGroup.MarginLayoutParams mp = ((ViewGroup.MarginLayoutParams) vDivider.getLayoutParams());
mp.leftMargin = Uscreen.dp2Px(mContext, 48);
}
if (item.listener != null) {
Uview.clickEffectByAlphaWithBg(new OnClickListener() {
@Override
public void onClick(View v) {
item.listener.click(SettingLayout.this, item);
}
}, v);
}
return this;
}
 
public SettingLayout addCustomView(View view) {
addView(view);
return this;
}
 
public SettingLayout addSpace(int spaceHeight) {
Space space = new Space(mContext);
space.setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, spaceHeight));
addView(space);
return this;
}
 
public SettingLayout addHeadTips(int strId) {
return addHeadTips(mContext.getResources().getString(strId));
}
 
public SettingLayout addHeadTips(String tips) {
TextView tvTips = new TextView(mContext);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT);
params.leftMargin = Uscreen.dp2Px(mContext, 16);
params.bottomMargin = Uscreen.dp2Px(mContext, 8);
tvTips.setLayoutParams(params);
tvTips.setText(tips);
tvTips.setTextColor(Color.DKGRAY);
tvTips.setTextSize(12);
addView(tvTips);
return this;
}
 
public interface IClickListener {
void click(SettingLayout layout, Item item);
}
 
/**
* NO 表示不显示底部分割线
* FILL 表示占满整个底部的分割线
* AFTERICON 表示紧随图像的分割线
*/
public static enum SEP {
NO, FILL, AFTERICON;
}
 
public static class Item {
public int titleStrId;
public int iconResId;
public String contentStr;
public String unitStr;
public boolean hasToRight;
public SEP sep;
public IClickListener listener;
 
public Item(int titleStrId) {
this.titleStrId = titleStrId;
}
 
/**
* @param titleStrId 字符串ID,用来标识Item(不允许重复,且必须有效)
* @param iconResId 最左边的Icon图标(当等于0时,不显示图标)
* @param contentStr 内容字符串
* @param unitStr 单位字符串(之所以没有和内容字符串合并,目的是更灵活地获取内容)
* @param hasToRight 是否显示向右的图标
* @param sep 分割线样式
* @param listener 给Item添加点击事件
*/
public Item(int titleStrId, int iconResId, String contentStr, String unitStr, boolean hasToRight, SEP sep,
IClickListener listener) {
super();
this.iconResId = iconResId;
this.titleStrId = titleStrId;
this.contentStr = contentStr;
this.unitStr = unitStr;
this.hasToRight = hasToRight;
this.sep = sep;
this.listener = listener;
}
}
}
【参考资料】
    *

通用系列 —— 快速搭建设置界面

标签:

原文地址:http://blog.csdn.net/ly1414725328/article/details/51335430

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!