在这一节中首先学习了java的页面布局,在此基础之上来进行了编程。
图片以下:
java
代码以下:android
** * 使用代码进行登陆界面的布局 * @author yuchao */ public class CodeLayoutActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //建立一个最外层的根布局 LinearLayout rootLayout = new LinearLayout(this); rootLayout.setBackgroundColor(Color.CYAN); //设置线性布局中子View的摆放为竖直方向 rootLayout.setOrientation(LinearLayout.VERTICAL); //建立一个根部局的LayoutParams LinearLayout.LayoutParams rootParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); //设置根部局的Margin值 rootParams.setMargins(DensityUtil.dip2px(this,5),DensityUtil.dip2px(this,5),DensityUtil.dip2px(this,5),DensityUtil.dip2px(this,5)); rootParams.gravity = Gravity.CENTER_HORIZONTAL; rootLayout.setLayoutParams(rootParams); //设置最外层根部局布局的背景颜色 rootLayout.setBackgroundColor(Color.CYAN); //将当前建立的根部局设置给Activity setContentView(rootLayout); //建立一个显示用户头像的ImageView ImageView ivIco = new ImageView(this); ivIco.setImageResource(R.drawable.ico); //将建立的用于显示头像的ImageView添加到最外层的线性布局中 rootLayout.addView(ivIco); //当经过子View进行获取所在的布局的时候,rootLayout.addView(ivIco)须要写在前面,缘由想起来也很清楚,当前的ImageView都尚未添加到父View若是直接经过getLayoutParams()固然会出先空指针异常(能够查看源码) LinearLayout.LayoutParams ivParams = (LinearLayout.LayoutParams) ivIco.getLayoutParams(); //给用于显示头像的ImageView设置宽高 ivParams.width = DensityUtil.dip2px(this,100f); ivParams.height = DensityUtil.dip2px(this,100f); //设置居中的方式(子View在父View下的摆放方式为水平居中) ivParams.gravity = Gravity.CENTER_HORIZONTAL; ivParams.setMargins(0,DensityUtil.dip2px(this,100),0,0); ivIco.setLayoutParams(ivParams); //建立水平排列的线性布局,用于放置帐户相关的View LinearLayout userCountLayout = new LinearLayout(this); userCountLayout.setOrientation(LinearLayout.HORIZONTAL); //将当前的建立的线性布局添加到根View rootLayout.addView(userCountLayout); //显示用户名的TextView TextView tvShowUser = new TextView(this); tvShowUser.setText("用户名:"); userCountLayout.addView(tvShowUser); LinearLayout.LayoutParams userCountlayoutParams = (LinearLayout.LayoutParams) tvShowUser.getLayoutParams(); userCountlayoutParams.setMargins(DensityUtil.dip2px(this,20),DensityUtil.dip2px(this,20),DensityUtil.dip2px(this,20),DensityUtil.dip2px(this,20)); //建立用于填写用户帐户的EditText EditText edtUserCount = new EditText(this); userCountLayout.addView(edtUserCount); edtUserCount.setHint("请输入用户名"); LinearLayout.LayoutParams edtUserCountlayoutParams = (LinearLayout.LayoutParams) edtUserCount.getLayoutParams(); edtUserCount.setWidth(0); edtUserCountlayoutParams.weight = 1; //父View的Gravity属性,肯定子View的摆放规则 edtUserCountlayoutParams.gravity = Gravity.CENTER_VERTICAL; //View.setGravity方法至关于 android:gravity="center",该属性表示对View中内容进行的限定 // edtUserCount.setGravity(Gravity.CENTER); //建立线性布局用于容纳密码相关的View LinearLayout pwdLayout = new LinearLayout(this); pwdLayout.setGravity(LinearLayout.HORIZONTAL); LinearLayout.LayoutParams pwdLayoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.WRAP_CONTENT); pwdLayout.setLayoutParams(pwdLayoutParams); rootLayout.addView(pwdLayout); //TextView显示密码文本 TextView tvShowPwd = new TextView(this); tvShowPwd.setText("密 码:"); pwdLayout.addView(tvShowPwd); LinearLayout.LayoutParams tvShowPwdParams = (LinearLayout.LayoutParams) tvShowPwd.getLayoutParams(); tvShowPwdParams.setMargins(DensityUtil.dip2px(this,20),DensityUtil.dip2px(this,20),DensityUtil.dip2px(this,20),DensityUtil.dip2px(this,20)); tvShowPwdParams.gravity = Gravity.CENTER_VERTICAL; //EdtText用于输入密码 EditText edtPwd = new EditText(this); edtPwd.setHint("请输入密码"); pwdLayout.addView(edtPwd); //使用new的方式来获取 LayoutParams LinearLayout.LayoutParams edtPwdParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); //设置权重 edtPwdParams.weight = 1; edtPwdParams.width = 0; //将布局参数设置给EdtText edtPwd.setLayoutParams(edtPwdParams); //用于进行登陆的button Button btnLogin = new Button(this); btnLogin.setText("登录"); rootLayout.addView(btnLogin); LinearLayout.LayoutParams btnLoginParams = (LinearLayout.LayoutParams) btnLogin.getLayoutParams(); //设置Button的大小 btnLoginParams.width = LinearLayout.LayoutParams.WRAP_CONTENT; btnLoginParams.height= LinearLayout.LayoutParams.WRAP_CONTENT; btnLoginParams.gravity = Gravity.CENTER_HORIZONTAL;
全局监听器
其实只是把每一个建立的监听器添加入List里 当SDK里调用一次的时候 遍历全部的监听器 执行每一个监听器的这个方法就好了
好吧 其实就是观察者模式啦
1.首先写一个监听器的接口编程
public interface testSDKListener { public void test(String str); }
2.写这个监听器的实现方法app
public class testSDKListenerImpl { private testSDKListener m_listener; public void setListener(testSDKListener listener) { m_listener = listener; } public void test(String str) { if (m_listener != null) { m_listener.test(str); } } }
3.建立一个List
public class testSDKListenerList { private static testSDKListenerList instance; private List<testSDKListener> listeners; public static testSDKListenerList getInstance() { if (instance == null) { instance = new testSDKListenerList(); } return instance; } private testSDKListenerList() { listeners = new ArrayList<testSDKListener>(); } public void setSDKListener(testSDKListener listener) { if (!listeners.contains(listener) && listener != null) { Log.i("testSDKListenerList", "Add a listener!"); this.listeners.add(listener); } } public void test(String str) { for (testSDKListener listener : listeners) { listener.test(str); } } }
4.在主程序中建立监听器布局
public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); testSDKListenerList.getInstance().setSDKListener(new testSDKListener() { @Override public void test(String str) { Log.d("Listener.test", "str="+str); } });
5.在SDK中执行监听器的方法学习
testSDKListenerList.getInstance().test("test success!");
通常来讲,Android 默认的状态栏样式表现为黑底白字,若是咱们应用的标题栏背景色也为黑色,那就能与状态栏很好地衔接在一块儿,体验极佳。反之,若是为其余的颜色,整个界面的呈现效果就会大打折扣。优化
幸运的是,Android 4.4 版本开始,系统提供了相应的 API,支持状态栏全透明化,界面 Content View 能够延伸到状态栏上,填充状态栏背景色。而在 Android 5.0 版本开始,系统在此基础上作了进一步优化和规范,可以实现动态改变状态栏背景色,在透明度上默认呈现为半透明化,可定制化程度更高。this
在此基础上,最终要作到咱们的应用呈如今 Android 各个系统版本上的效果如图所示:
设计
关于 Android 4.4 版本开始的状态栏变化,许多人喜欢称之为“沉浸式状态栏”,但从系统提供的 API 命名上能够看出,核心词汇为 “Translucent”,故准确来说,这种效果又应该称之为“透明状态栏”。知乎上对于这两种叫法也很有争议,具体内容可参考话题:为何在国内会有不少用户把「透明栏」(Translucent Bars)称做 「沉浸式顶栏」?。可能对于设计师而言,沉浸式仍是透明式的称呼有所区别,但对于广大开发者而言,无足轻重,咱们所关注的应该是如何实现这种效果,并可以很好的兼容到各个版本中。
使用案例分析
res/values/styles 文件中定义基础主题样式:
<style name="BaseTheme" parent="Theme.AppCompat.Light.NoActionBar"/> <style name="AppTheme" parent="BaseTheme"> </style>
res/values-v19/styles 文件中定义兼容主题样式:
<style name="AppTheme" parent="BaseTheme"> <item name="android:windowTranslucentStatus">true</item> </style>
而后在 AndroidManifest.xml 文件中使用全局主题样式:
<application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="Samples" android:supportsRtl="true" android:name=".MyApplication" android:theme="@style/AppTheme">
新建一个 layout 布局文件,单独定义 toolbar 内容,在应用中的其余 Activity 界面布局中使用 include 标签潜入引用:
<?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/tb_toolbar" android:layout_width="match_parent" android:layout_height="wrap_content" android:minHeight="?actionBarSize" android:background="@color/colorPrimary" android:fitsSystemWindows="true" app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" app:popupTheme="@style/ThemeOverlay.AppCompat.Light" app:title="@string/app_name" app:titleTextColor="@android:color/white"> </android.support.v7.widget.Toolbar>
这里使用 android:fitsSystemWindows="true" 属性解决内容试图向上延伸的问题。实际上,也可使用 android:paddingTop="@dimen/toolbar_padding_top" 的方式解决,toolbar_padding_top 间距为状态栏高度,在大多数机器上状态栏高度为 25dp,固然也能够经过代码动态获取状态栏高度并设置到 Toolbar 的 paddingTop 属性上。须要注意的是,这里要作兼容判断,好比在 res/values/dimens.xml 中定义toolbar_padding_top 高度为 0dp,在 res/values-v19/dimens.xml 中为 25dp,确保兼容 Android 4.4 如下版本。
基本上,作到这些就可以实现文章开头处图中的效果。值得注意的是,有时候若是想在 Android 5.0 及以上版本的系统中也作到全透明效果,或者说状态栏与导航栏的颜色一致,还能够作进一步兼容处理,毕竟自 5.0 版本开始,系统对于状态栏背景色的定制提供了更好的 API。如 res/values-v21/styles.xml 中定义:
<?xml version="1.0" encoding="utf-8"?> <resources> <style name="AppTheme" parent="BaseTheme"> <item name="android:colorPrimary">@color/colorPrimary</item> <item name="android:colorPrimaryDark">@color/colorPrimary</item> <item name="android:colorAccent">@color/colorAccent</item> </style>
当用户长按Activity页面时,弹出的菜单咱们称为上下文菜单。咱们常常在Windows中用鼠标右键单击弹出的菜单就是上下文菜单。
ContextMenu与OptionMenu的区别:
一、OptionMenu对应的是activity,一个activity只能拥有一个选项菜单;
二、ContextMenu对应的是view,每一个view均可以设置上下文菜单;
三、通常状况下ContextMenu经常使用语ListView或者GridView
实现步骤:
(1)首先给View注册上下文菜单registerForContextMenu()
this.registerForContextMenu(contextView);
(2)添加上下文菜单的内容onCreateContextMenu()
代码:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.jiapeng.munedemo.MainActivity" tools:ignore="MergeRootFrame" > <ListView android:id="@+id/mune_list" android:layout_width="wrap_content" android:layout_height="wrap_content" > </ListView> </FrameLayout>
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); showListView(); // 注册上下文菜单 this.registerForContextMenu(listview); } /** * 加载数据 */ private void showListView() { listview = (ListView) findViewById(R.id.mune_list); ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, getDate()); listview.setAdapter(adapter); } /** * 建立数据源 * * @return list */ private ArrayList<String> getDate() { ArrayList<String> list = new ArrayList<String>(); for (int i = 0; i < 10; i++) { list.add("菜单" + i); } return list; } /** * 添加上下文菜单的菜单项 */ public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { menu.setHeaderTitle("上下文菜单"); menu.setHeaderIcon(R.drawable.ic_launcher); //加载上下文菜单内容 menu.add(1, 1, 1, "保存"); menu.add(1, 2, 1, "更改"); menu.add(1, 3, 1, "删除"); super.onCreateContextMenu(menu, v, menuInfo); } /** * 建立单击事件 */ public boolean onContextItemSelected(MenuItem item) { switch (item.getItemId()) { case 1: Toast.makeText(this, "点击了保存", Toast.LENGTH_SHORT).show(); break; case 2: Toast.makeText(this, "点击了更改", Toast.LENGTH_SHORT).show(); break; case 3: Toast.makeText(this, "点击了删除", Toast.LENGTH_SHORT).show(); break; default: break; } return super.onContextItemSelected(item); }