Android之Fragment静态加载

最后更新于:2022-04-01 14:27:43

### 1、Fragment知识概要 Android3.0引入了Fragment,主要目的是用在大屏幕设备上,支持更加动态和灵活的UI设计。Fragment在你的应用中应当是一个模块化和可重用的组件,因为Fragment定义了它自己的布局,以及通过使用它自己的声明周期回调回调方法定义了它自己的行为,可以将Fragment包含到多个Activity中。 (1)Fragment可以作为Activity界面的一部分组成出现; (2)可以在一个Activity中同时出现多个Fragment,并且一个Fragment也可以在多个Activity中使用; (3)在Activity运行过程中,可以添加、移除或替换Fragment; (4)Fragment可以响应自己的输入事件,并且有自己的声明周期,它们的生命周期受宿主Activity的生命周期影响; (5)Fragment在第一次绘制它的用户界面时,系统会调用onCreateView()方法,此方法返回一个View。(如果不显示UI,返回null); Fragment两种加载方式:静态加载、动态加载。 ### 2、准备阶段: 本文以及后续将使用一个APP来讲解关于Fragment的知识,大致布局如下: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-06_5704ccee90fce.jpg) values添加color.xml: ~~~ <?xml version="1.0" encoding="utf-8"?> <resources> <color name="gray">#88000000</color> <color name="white">#ffffff</color> </resources> ~~~       drawable中添加radio_pressed.xml ~~~ <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@color/gray" android:state_checked="true"></item> <item android:drawable="@color/white" android:state_pressed="true"></item> <item android:drawable="@color/white"></item> </selector> ~~~ main主布局: ~~~ <?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="match_parent" > <LinearLayout android:id="@+id/frame" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > </LinearLayout> <RadioGroup android:id="@+id/radiogroup" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:gravity="center_horizontal" android:orientation="horizontal" > <RadioButton android:id="@+id/first" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:background="@drawable/radio_pressed" android:button="@null" android:drawableTop="@drawable/ic_launcher" android:gravity="center_horizontal" android:text="静态加载" /> <RadioButton android:id="@+id/second" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:background="@drawable/radio_pressed" android:button="@null" android:drawableTop="@drawable/ic_launcher" android:gravity="center_horizontal" android:text="动态加载" /> <RadioButton android:id="@+id/thrid" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:background="@drawable/radio_pressed" android:button="@null" android:drawableTop="@drawable/ic_launcher" android:gravity="center_horizontal" android:text="生命周期" /> <RadioButton android:id="@+id/fourth" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:background="@drawable/radio_pressed" android:button="@null" android:drawableTop="@drawable/ic_launcher" android:gravity="center_horizontal" android:text="传值通信" /> </RadioGroup> </RelativeLayout> ~~~ MainActivity加载main: ~~~ package com.example.fragment; import android.os.Bundle; import android.app.Activity; import android.view.Menu; import android.widget.RadioGroup; import android.widget.RadioGroup.OnCheckedChangeListener; public class MainActivity extends Activity implements OnCheckedChangeListener { private RadioGroup group; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); group=(RadioGroup) findViewById(R.id.radiogroup); group.setOnCheckedChangeListener(this); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public void onCheckedChanged(RadioGroup group, int checkedId) { // TODO Auto-generated method stub switch (checkedId) { case R.id.first: //演示静态加载 break; case R.id.second: //演示动态加载 break; case R.id.thrid: //演示生命周期 break; case R.id.fourth: //演示传值通信 break; } } } ~~~ ### 3、静态加载 在Activity的layout文件中声明Fragment(特别注意:在<fragment>标签中的android: name属性中指定了在layout中实例化的Fragment类),标识Fragment的方法:A.android: id 属性提供一个唯一ID;B.android: tag属性提供一个唯一字符串; 添加fragment.xml: ~~~ <?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/text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="我的Fragment"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/button"/> </LinearLayout> ~~~ 添加MyFragment类,并加载fragment布局: ~~~ package com.example.fragment; import android.app.Fragment; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.Button; import android.widget.TextView; public class MyFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // layout布局文件转换成View对象 /** * inflater.inflate(resource, root, attachToRoot) * resource:Fragment需要加载的布局文件 * root:加载layout的父ViewGroup * attactToRoot:false,不返回父ViewGroup */ View view = inflater.inflate(R.layout.fragment, container, false); TextView text = (TextView) view.findViewById(R.id.text); Button button = (Button) view.findViewById(R.id.button); text.setText("静态加载Fragment"); button.setText("获取内容"); button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub // String value = getAaa(); // Toast.makeText(getActivity(), "value="+value, // Toast.LENGTH_SHORT).show(); } }); return view; } } ~~~ 添加jigntai.xml: ~~~ <?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" > <!-- android:id:静态加载必须指定一个ID --> <!-- android:name:完整包名 --> <fragment android:id="@+id/fragment" android:layout_width="wrap_content" android:layout_height="wrap_content" android:name="com.example.fragment.MyFragment" /> </LinearLayout> ~~~ 添加JingTaiActivity类: ~~~ public class JingTaiActivity extends Activity { private TextView tv; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.jingtai); Button button=(Button) findViewById(R.id.button); tv=(TextView) findViewById(R.id.text); button.setText("改变"); button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub tv.setText("TextView改变了"); } }); } } ~~~ 主MainActivity中演示静态加载部分添加: ~~~ case R.id.first: //演示静态加载 Intent jingtaiIntent=new Intent(MainActivity.this,JingTaiActivity.class); startActivity(jingtaiIntent); break; ~~~ MainActivity跳转到JingTaiActivity,里面加载了一个<fragment>,而其中android:name属性是com.example.fragment.MyFragment,在这个MyFragment中又有自己的text、button布局。再回到JingTaiActivity,在其中加载了jingtai.xml,并且可以直接通过findViewById找到MyFragment的布局文件fragment中的text、button。 也就是说,当一个布局文件中通过静态加载Fragment加载到Activity中来,Fragment中的布局文件对Activity也是共享的。
';

关于Activity回收造成View选中不对应的问题

最后更新于:2022-04-01 14:27:41

当遇到Activity被回收(横竖屏、内存不足)时,Activity会重建,而去调用onCreate()方法,在onCreate()方法中调用了设置首项透明度的方法。这样就会出现,选中的View和内容Fragment的不对应的。 ~~~ //Bundle的键,作用:自定义的VIew继承的有可能不是View,有可能是TextView、ImageView, //重写下面两个方法,以便记住原本的Bundle(不能抹掉原来的XXView的恢复和销毁的过程) private static final String INSTANCE_STATUS="instance_status"; private static final String STATUS_ALPHA="status_alpha"; //Bundle的键 //当Activity重建的时候,恢复Alpha值 @Override protected Parcelable onSaveInstanceState() { Bundle bundle=new Bundle(); bundle.putParcelable(INSTANCE_STATUS, super.onSaveInstanceState()); //把父级存储的变量放到INSTANCE_STATUS中 bundle.putFloat(STATUS_ALPHA, mAlpha); //存储自己需要保存的东西 return bundle; } @Override protected void onRestoreInstanceState(Parcelable state) { if(state instanceof Bundle){ Bundle bundle=(Bundle) state; mAlpha=bundle.getFloat(STATUS_ALPHA); //取出自己保存的东西 super.onRestoreInstanceState(bundle.getParcelable(INSTANCE_STATUS)); //取出系统保存的东西,并调用系统的恢复 return; } super.onRestoreInstanceState(state); } ~~~
';

一个自定义的Topbar模板

最后更新于:2022-04-01 14:27:39

### 1、Topbar模板功能介绍:自定义UI布局,自定义UI属性,自定义按钮监听事件,自定义左、右button的显示!效果图如下: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-06_5704ccee55776.jpg) ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-06_5704ccee682f2.jpg) ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-06_5704ccee7923a.jpg) ### 2、自定义属性:values——mytopbar.xml: ~~~ <?xml version="1.0" encoding="utf-8"?> <resources> <!-- 自定义属性 --> <declare-styleable name="MyTopBar"> <attr name="leftTextColor" format="color"/> <!-- BackGround属性可以颜色,也可以是一个资源文件 --> <!-- 所以BackGround是 format="reference|color"--> <attr name="leftBackGround" format="reference|color"/> <attr name="leftText" format="string"/> <attr name="title" format="string"/> <attr name="titleTextSize" format="dimension"/> <attr name="titleTextColor" format="color"/> <attr name="rightTextColor" format="color"/> <attr name="rightBackGround" format="reference|color"/> <attr name="rightText" format="string"/> </declare-styleable> </resources> ~~~ ### 3、自定义VIew:MyTopBar.java ~~~ //继承RelativeLayout并重写构造方法 public class MyTopBar extends RelativeLayout { // 自定义的控件和自定义的属性(values下mytopbar.xml)的声明 private Button leftButton, rightButton; private TextView tvTitle; private int leftTextColor; private Drawable leftDrawable; private String leftText; private float titleTextSize; private int titleTextColor; private String title; private int rightTextColor; private Drawable rightDrawable; private String rightText; private LayoutParams leftLayoutParams, titleLayoutParams, rightLayoutParams; private myTopbarClicklistenter clicklistenter; //自定义click的监听回调接口 public interface myTopbarClicklistenter{ public void leftClick(); public void rightClick(); } //自定义一个setOnClickListenter方法 public void setOnTopbarClickListenter(myTopbarClicklistenter clicklistenter){ this.clicklistenter=clicklistenter; //调用的时候通过一个匿名内部类映射进来 } //重写构造方法 public MyTopBar(Context context, AttributeSet attrs) { super(context, attrs); // 获取自定义的属性,并将自定义的属性映射到自定义的属性值中去 // 通过obtainStyledAttributes获取自定义属性,并存到TypedArray TypedArray ta = context.obtainStyledAttributes(attrs,R.styleable.MyTopBar); leftTextColor = ta.getColor(R.styleable.MyTopBar_leftTextColor, 0); //从TypedArray中取出来,并对应到自定义的属性值上 leftDrawable = ta.getDrawable(R.styleable.MyTopBar_leftBackGround); leftText = ta. getString(R.styleable.MyTopBar_leftText); titleTextSize = ta.getDimension(R.styleable.MyTopBar_titleTextSize, 0); titleTextColor = ta.getColor(R.styleable.MyTopBar_titleTextColor, 0); title = ta.getString(R.styleable.MyTopBar_title); rightTextColor = ta.getColor(R.styleable.MyTopBar_rightTextColor, 0); rightDrawable = ta.getDrawable(R.styleable.MyTopBar_rightBackGround); rightText = ta.getString(R.styleable.MyTopBar_rightText); ta.recycle(); //组件定义 leftButton = new Button(context); tvTitle = new TextView(context); rightButton = new Button(context); // 将自定义的属性设置到控件上 leftButton.setTextColor(leftTextColor); leftButton.setBackground(leftDrawable); leftButton.setText(leftText); tvTitle.setTextColor(titleTextColor); tvTitle.setTextSize(titleTextSize); tvTitle.setText(title); tvTitle.setGravity(Gravity.CENTER); // 设置文字居中 rightButton.setTextColor(rightTextColor); rightButton.setBackground(rightDrawable); rightButton.setText(rightText); setBackgroundColor(0xFFF59563); // 设置背景颜色 //将自定义的控件放到Layout中(以LayoutParams的形式) leftLayoutParams=new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT); leftLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT,TRUE); //设置左对齐 addView(leftButton,leftLayoutParams); //leftButton以leftLayoutParams的形式加入到ViewGroup中 titleLayoutParams=new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.MATCH_PARENT); titleLayoutParams.addRule(RelativeLayout.CENTER_IN_PARENT,TRUE); //设置居中对齐 addView(tvTitle,titleLayoutParams); //tvTitle以titleLayoutParams的形式加入到ViewGroup中 rightLayoutParams=new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT); rightLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT,TRUE); //设置右对齐 addView(rightButton,rightLayoutParams);//rightButton以rightLayoutParams的形式加入到ViewGroup中 //设置监听事件 leftButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { clicklistenter.leftClick(); } }); rightButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { clicklistenter.rightClick(); } }); } //设置左Button是否显示 public void setLeftIsVisible(boolean flag){ if(flag){ leftButton.setVisibility(View.VISIBLE); }else{ leftButton.setVisibility(View.GONE); } } // 设置右Button是否显示 public void setRightIsVisible(boolean flag) { if (flag) { rightButton.setVisibility(View.VISIBLE); } else { rightButton.setVisibility(View.GONE); } } } ~~~ ### 4、activity_main.xml引用自定义控件: ~~~ <!-- 引用自定义控件 --> <com.example.topbar.MyTopBar android:id="@+id/my_topbar" android:layout_width="match_parent" android:layout_height="40dp" app:leftBackGround="@drawable/blue" app:leftTextColor="#ffffff" app:leftText="Back" app:title="自定义标题" app:titleTextSize="10sp" app:titleTextColor="#123412" app:rightBackGround="@drawable/blue" app:rightTextColor="#ffffff" app:rightText="More"> </com.example.topbar.MyTopBar> ~~~ ### 5、MainActivity.java使用控件: ~~~ public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); MyTopBar topBar =(MyTopBar) findViewById(R.id.my_topbar); //调用自定义的Topbar的自定义的click监听事件 topBar.setOnTopbarClickListenter(new MyTopBar.myTopbarClicklistenter() { @Override public void leftClick() { // TODO Auto-generated method stub Toast.makeText(MainActivity.this, "点击了Back", Toast.LENGTH_SHORT).show(); } @Override public void rightClick() { // TODO Auto-generated method stub Toast.makeText(MainActivity.this, "点击了More", Toast.LENGTH_SHORT).show(); } }); //topBar.setLeftIsVisible(false); //topBar.setRightIsVisible(false); } } ~~~ 6、使用Topbar模板提示:正如上面MainActivity中,实例化后,可以调用TopBar里面的方法。 [**完整代码下载:https://github.com/songshimvp/AndroidStudy/tree/master/TopBar**](https://github.com/songshimvp/AndroidStudy/tree/master/TopBar)
';

不同APP通过SharedPreferences传递数据(共享数据)

最后更新于:2022-04-01 14:27:36

### 1、写入数据APP ~~~ public class MainActivity extends Activity { private SharedPreferences putPreferences; private Editor putEditor; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 将服务器信息写入serverInfo.xml findViewById(R.id.buttonPut).setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub putPreferences = getSharedPreferences("serverInfo", Context.MODE_WORLD_READABLE); putEditor = putPreferences.edit(); putEditor.putString("serverIP", "192.168.1.102"); putEditor.putString("password", "123456"); putEditor.commit(); Toast.makeText(MainActivity.this,"服务器信息成功写入serverInfo.xml", Toast.LENGTH_LONG).show(); } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } } ~~~ ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-06_5704ccedee14d.jpg) ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-06_5704ccee14e9e.jpg) ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-06_5704ccee2c0e8.jpg) ### 2、获取数据APP ~~~ public class MainActivity extends Activity { private SharedPreferences getPreferences; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //从serverInfo.xml获取服务器信息 findViewById(R.id.buttonGet).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub try { Context context=createPackageContext("com.example.putprefapp", Context.CONTEXT_IGNORE_SECURITY); getPreferences=context.getSharedPreferences("serverInfo", MODE_WORLD_READABLE); String serverIP=getPreferences.getString("serverIP",""); String serverPwd=getPreferences.getString("password", ""); Toast.makeText(MainActivity.this, "服务器信息如下:IP地址:" +serverIP+"; 密码:"+serverPwd, Toast.LENGTH_LONG).show(); } catch (NameNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } } ~~~ ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-06_5704ccee3c181.jpg) ### 3、关于android:sharedUserId 上面的两个工程中并没有对android:sharedUserId属性进行设置。这个属性是在查资料时看到的:意思是说,在manifest.xml里面将两个应用程序的android:sharedUserId属性设为相同的就可以对SharedPreferences文件进行写。(此处并没有验证)
';

Android手势识别之GestureDetector

最后更新于:2022-04-01 14:27:34

GestureDetector(手势识别器) ### (1)手势交互过程原理: A.触屏一刹那,触发 MotionEvent事件; B.上述事件被 OnTouchListenter 监听,在 nTouch() 中获得 MotionEvent对象; C.GestureDetector 转发MotionEvent对象至 OnGestureListenter; D.OnGestureListenter 获得该对象,根据该对象封装的信息作出合适的反馈; ### (2)MotionEvent: 1)、用于封装手势等动作事件; 2)、内部封装用于记录横轴和纵轴坐标的属性X和Y; GestureDetector: 1)、识别各种手势; OnGestureListenter: 1)、手势交互的监听接口,其提供多个抽象方法; 2)、根据GestureDetector的手势识别结果调用相对应的方法; ### (3)GestureDetector工作原理: 1)、GestureDetector.OnGestureListener接口 onDown(MotionEvent e):——单击 Notified when a tap occurs with the down MotionEvent that triggered it. onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY):——滑动 Notified of a fling event when it occurs with the initial on down MotionEvent and the matching up MotionEvent. onLongPress(MotionEvent e):——长按 Notified when a long press occurs with the initial on down MotionEvent that trigged it. onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY):——滚动 Notified when a scroll occurs with the initial on down MotionEvent and the current move MotionEvent. onShowPress(MotionEvent e):——短按 The user has performed a down MotionEvent and not performed a move or up yet. onSingleTapUp(MotionEvent e):——抬起 Notified when a tap occurs with the up MotionEvent that triggered it.  2)、GestureDetector.OnDoubleTapListener接口 onDoubleTap(MotionEvent e):——双击** Notified when a double-tap occurs. onDoubleTapEvent(MotionEvent e):——双击按下和抬起各触发一次 Notified when an event within a double-tap gesture occurs, including the down, move, and up events. onSingleTapConfirmed(MotionEvent e):——单击确认(即很快的按下并抬起,但并不连续点击第二下) Notified when a single-tap occurs. 3)、GestureDetector.SimpleOnGestureListener类 其实我们并不需要处理上面所有手势。问了方便起见,Android提供了另外一个类SimpleOnGestureListener。它实现了如上接口,我们只需要继承SimpleOnGestureListener类,然后重载感兴趣的手势。 implements [GestureDetector.OnGestureListener](http://developer.android.com/reference/android/view/GestureDetector.OnGestureListener.html) [GestureDetector. OnDoubleTapListener](http://developer.android.com/reference/android/view/GestureDetector.OnDoubleTapListener.html)[GestureDetector. OnContextClickListener](http://developer.android.com/reference/android/view/GestureDetector.OnContextClickListener.html)。A convenience class to extend when you only want to listen for a subset of all the gestures. This implements all methods in  the  `[GestureDetector.OnGestureListener](http://developer.android.com/reference/android/view/GestureDetector.OnGestureListener.html)`,  `[GestureDetector.OnDoubleTapListener](http://developer.android.com/reference/android/view/GestureDetector.OnDoubleTapListener.html)`, and`[GestureDetector.OnContextClickListener](http://developer.android.com/reference/android/view/GestureDetector.OnContextClickListener.html)` but does nothing and return`false` for all applicable methods. ~~~ public class MainActivity extends Activity { private ImageView imageView; private GestureDetector mygestureDetector; // 继承SimpleOnGestureListener类,然后重载感兴趣的手势。 class MyGestureListenter extends SimpleOnGestureListener { @Override // 重载滑动手势 public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { if (e1.getX() - e2.getX() > 50) { Toast.makeText(MainActivity.this, "从右往左滑动", Toast.LENGTH_SHORT) .show(); } else if (e2.getX() - e1.getX() > 50) { Toast.makeText(MainActivity.this, "从左往右滑动", Toast.LENGTH_SHORT) .show(); } return super.onFling(e1, e2, velocityX, velocityY); } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); /* * GestureDetector工作原理 * 1、当接收到用户触摸消息时,将消息交给GestureDetector加工; * 2、通过设置监听器获得GestureDetector处理后的手势; * 3、GestureDetector提供两个监听器: * A.OnGestureListenter:处理单击类消息; * B.OnDoubleTapListenter:处理双击类消息; */ imageView = (ImageView) findViewById(R.id.img); mygestureDetector = new GestureDetector(new MyGestureListenter()); // MotionEvent——》setOnTouchListener捕获 // ——》onTouch中GestureDetector对象将监听事件转发给MyGestureListenter(extends SimpleOnGestureListener) // ——》MyGestureListenter类中实现了要重载的手势 imageView.setOnTouchListener(new OnTouchListener() { @Override // 可以捕获触摸屏幕发生的Event public boolean onTouch(View v, MotionEvent event) { // TODO Auto-generated method stub mygestureDetector.onTouchEvent(event); // 转发event事件,转发给MyGestureListenter(extends SimpleOnGestureListener) return false; } }); } //消除冲突 /*@Override public boolean dispatchTouchEvent(MotionEvent ev) { // TODO Auto-generated method stub if(mygestureDetector!=null){ if(mygestureDetector.onTouchEvent(ev)){ return true; } } return super.dispatchTouchEvent(ev); }*/ //必须重写onTouchEvent方法,onFling才生效 @Override public boolean onTouchEvent(MotionEvent event) { // TODO Auto-generated method stub return mygestureDetector.onTouchEvent(event); } } ~~~ 为了让onFling才生效,必须重写onTouchEvent方法!
';

Android SharedPreferences存储数据的使用方法

最后更新于:2022-04-01 14:27:32

### 1、SharedPreferences类的介绍 对于软件配置参数的保存,如果是window软件通常我们会采用ini文件进行保存;如果是j2se应用,我们会采用properties属性文件或者xml进行保存。如果是Android应用,我们最适合采用什么方式保存软件配置参数呢?Android平台给我们提供了一个SharedPreferences类,它是一个轻量级的存储类,特别适合用于保存软件配置参数。使用SharedPreferences保存数据,其背后是用xml文件存放数据,文件存放在 /data/data/<package name>/shared_prefs 目录下(下面会对实际案例进行截图证明)。SharedPreferences是Android中最容易理解的数据存储技术,实际上SharedPreferences处理的就是一个key-value(键值对),SharedPreferences常用来存储一些轻量级的数据。 ### 2、SharedPreferences类的说明及简单分析 (1)获取SharedPreferences的两种方式: 1 调用Context对象的getSharedPreferences()方法; 2 调用Activity对象的getPreferences()方法; 两种方式的区别: 调用Context对象的getSharedPreferences()方法获得的SharedPreferences对象可以被同一应用程序下的其他组件共享; 调用Activity对象的getPreferences()方法获得的SharedPreferences对象只能在该Activity中使用;  (2)SharedPreferences的四种操作模式: Context.MODE_PRIVATE:为默认操作模式,代表该文件是私有数据,只能被应用本身访问,在该模式下,写入的内容会覆盖原文件的内容; Context.MODE_APPEND:模式会检查文件是否存在,存在就往文件追加内容,否则就创建新文件; Context.MODE_WORLD_READABLE:表示当前文件可以被其他应用读取; Context.MODE_WORLD_WRITEABLE:表示当前文件可以被其他应用写入; (3)将数据保存至SharedPreferences: ~~~ SharedPreferences preferences = getSharedPreferences("user",Context.MODE_PRIVATE); Editor editor=preferences.edit(); String name="xixi"; String age="22"; editor.putString("name", name); editor.putString("age", age); editor.commit(); ~~~ (4)从SharedPreferences获取数据: ~~~ SharedPreferences preferences=getSharedPreferences("user", Context.MODE_PRIVATE); String name=preferences.getString("name", "defaultname"); String age=preferences.getString("age", "0"); ~~~ ### 3、简单案例展示: ~~~ findViewById(R.id.button1).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub SharedPreferences sharedPreferences=getSharedPreferences("user", Context.MODE_PRIVATE); // 实例化SharedPreferences对象 Editor editor=sharedPreferences.edit(); // 实例化SharedPreferences.Editor对象 editor.putString("name", "张三"); // 用putString的方法保存数据 editor.putString("IP", "192.168.1.102"); editor.putString("password", "123456"); editor.commit(); // 提交当前数据 Toast.makeText(MainActivity.this, "写入数据成功!", Toast.LENGTH_SHORT).show(); } }); findViewById(R.id.button2).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 在读取SharedPreferences数据前要实例化出一个SharedPreferences对象 SharedPreferences preferences=getSharedPreferences("user", Context.MODE_PRIVATE); String nameStr=preferences.getString("name", "dafultName"); // 使用getString方法获得value,注意第2个参数是value的默认值 String ipStr=preferences.getString("IP", ""); // getString()第二个参数为缺省值,如果preference中不存在该key,将返回缺省值 String pwStr=preferences.getString("password", ""); Toast.makeText(MainActivity.this, "用户信息:姓名:"+nameStr+",IP:"+ipStr+",密码:"+pwStr, Toast.LENGTH_LONG).show(); } }); ~~~ 关于SharedPreferences背后是使用xml文件保存数据,getSharedPreferences(name,mode)方法的第一个参数用于指定该文件的名称,名称不用带后缀,后缀会由Android自动加上。方法的第二个参数指定文件的操作模式,共有四种操作模式,这四种模式前面介绍使用文件方式保存数据时已经讲解过。如果希望SharedPreferences背后使用的xml文件能被其他应用读和写,可以指定Context.MODE_WORLD_READABLE和Context.MODE_WORLD_WRITEABLE权限。 数据文件图示: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-06_5704cceda7349.jpg) ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-06_5704ccedbcc77.jpg) ### 4、关于“记住用户登录信息”的案例: xml: ~~~ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:text="用户名:" /> <EditText android:id="@+id/name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginRight="10dp" android:layout_weight="1" android:hint="请输入登录名" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:text="IP地址:" /> <EditText android:id="@+id/ip" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginRight="10dp" android:layout_weight="1" android:hint="请输入IP地址" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:text="密 码:" /> <EditText android:id="@+id/password" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginRight="10dp" android:layout_weight="1" android:hint="请输入密码" android:inputType="textPassword" /> </LinearLayout> <CheckBox android:id="@+id/check" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="记住用户名" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <Button android:id="@+id/login" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:text="登录" /> <Button android:id="@+id/cancel" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:text="取消" /> </LinearLayout> </LinearLayout> ~~~ Main.java ~~~ public class MainActivity extends Activity implements OnClickListener { private EditText etName,etIP,etPw; private CheckBox checkBox; private Button btnLogin,btnCancel; SharedPreferences sharedPreferences; Editor editor; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); etName=(EditText) findViewById(R.id.name); etIP=(EditText) findViewById(R.id.ip); etPw=(EditText) findViewById(R.id.password); checkBox=(CheckBox) findViewById(R.id.check); btnLogin=(Button) findViewById(R.id.login); btnCancel=(Button) findViewById(R.id.cancel); btnLogin.setOnClickListener(this); btnCancel.setOnClickListener(this); sharedPreferences = getSharedPreferences("UserInfo", MODE_PRIVATE); editor = sharedPreferences.edit(); String getName = sharedPreferences.getString("name", ""); //此处是关于“记住登录信息”的操作 String getIP=sharedPreferences.getString("IP", ""); String getPassword=sharedPreferences.getString("password", ""); if(getName==null){ checkBox.setChecked(false); } else{ checkBox.setChecked(true); etName.setText(getName); } } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public void onClick(View v) { // TODO Auto-generated method stub switch (v.getId()) { case R.id.login: String name = etName.getText().toString().trim(); String IP = etIP.getText().toString().trim(); String password=etPw.getText().toString().trim(); if(name.equals("admin") /*&& IP.equals("192.168.1.102")*/ && password.equals("GO")){ if(checkBox.isChecked()){ editor.putString("name", name); //只记住登录名 //editor.putString("IP", IP); //editor.putString("password", password); editor.commit(); Toast.makeText(MainActivity.this, "登录名已保存", Toast.LENGTH_SHORT).show(); } else{ editor.remove("name"); //如果没有勾选“记住登录信息” //editor.remove("IP"); //editor.remove("password"); editor.commit(); Toast.makeText(MainActivity.this, "登录名未保存", Toast.LENGTH_SHORT).show(); } Toast.makeText(MainActivity.this, "登陆成功", Toast.LENGTH_SHORT).show(); }else{ Toast.makeText(MainActivity.this, "登录失败", Toast.LENGTH_SHORT).show(); } break; case R.id.cancel: break; } } } ~~~ 效果图: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-06_5704ccedcb91d.jpg) 登陆成功以后,返回退出,重新进入该应用程序,用户名已经存在!(勾掉“记住用户名”,则不会自动填写用户名一栏) ### 4、不同APP通过SharedPreferences传递数据(共享数据) 具体案例见:[http://blog.csdn.net/songshimvp1/article/details/50300521](http://blog.csdn.net/songshimvp1/article/details/50300521)
';

Android Menu中android:showAsAction属性

最后更新于:2022-04-01 14:27:30

1、android:showAsAction属性说明: 当你的应用程序目标设为[蜂巢](http://cpro.baidu.com/cpro/ui/uijs.php?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=18&is_app=0&jk=9423f21eda7fae36&k=%B7%E4%B3%B2&k0=%B7%E4%B3%B2&kdi0=0&luki=2&mcpm=0&n=10&p=baidu&q=65035100_cpr&rb=0&rs=1&seller_id=1&sid=36ae7fda1ef22394&ssp2=1&stid=9&t=tpclicked3_hc&td=1836545&tu=u1836545&u=http%3A%2F%2Fwww%2Ebubuko%2Ecom%2Finfodetail%2D784691%2Ehtml&urlid=0)平台(即 Android 3.0)时,你可以利用Action Bar部件提供的全部功能,将你的选项菜单项放在Action Bar的右上角,对用户来说使用更方便,控制该行为的主菜单项属性是android:showAsAction。 这个属性可接受的值有: 1).alaways:这个值会使菜单项一直显示在ActionBar上。 2).ifRoom:如果有足够的空间,这个值会使菜单显示在ActionBar上。 3).never:这个值菜单永远不会出现在ActionBar是。 4).withText:这个值使菜单和它的图标,菜单文本一起显示。 2、实际案例展示: res ——》 menu ——》main.xml ~~~ <menu xmlns:android="http://schemas.android.com/apk/res/android" > <item android:showAsAction="always" android:title="文件(F)"> <menu > <item android:id="@+id/new_file" android:title="新建"/> <item android:id="@+id/open_file" android:title="打开"/> <item android:id="@+id/save_file" android:title="保存"/> <item android:id="@+id/rename_file" android:title="重命名"/> </menu> </item> <item android:showAsAction="never" android:title="编辑(E)"> <menu > <item android:id="@+id/v_file" android:title="粘贴"/> <item android:id="@+id/c_edit" android:title="复制"/> <item android:id="@+id/x_edit" android:title="剪切"/> <item android:id="@+id/rename_edit" android:title="重命名"/> </menu> </item> </menu> ~~~ 如上面代码所示:“文件(F)”的android:showAsAction属性是“always”;“编辑(E)”的android:showAsAction属性是“never”; 产生的效果图如下面所示: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-06_5704cced5ff47.jpg) ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-06_5704cced7aef3.jpg) ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-06_5704cced8eba4.jpg)
';

Android之Menu

最后更新于:2022-04-01 14:27:27

### 1、选项菜单(OptionsMenu): (1)创建选项菜单:重写onCreateOptionsMenu(Menu menu):     1)通过xml设置MenuInflater.inflate();      2)动态设置; (2)设置菜单项点击事件:onOptionsItemSelected(); (3)通过xml设置MenuInflater.inflate();          res ——> menu ——>main.xml ~~~ <menu xmlns:android="http://schemas.android.com/apk/res/android" > <item android:id="@+id/action_settings1" android:orderInCategory="100" android:showAsAction="never" android:title="菜单一"/> <item android:id="@+id/action_settings2" android:orderInCategory="100" android:showAsAction="never" android:title="菜单二"/> </menu> ~~~            MainActivity.java ~~~ @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. // 创建选项菜单 // (1)通过xml设置MenuInflater.inflate(); getMenuInflater().inflate(R.menu.main, menu); return true; } // 设置菜单项点击事件:onOptionsItemSelected(); @Override public boolean onOptionsItemSelected(MenuItem item) { // TODO Auto-generated method stub switch (item.getItemId()) { case R.id.action_settings1: Toast.makeText(this, "点击了菜单项一", Toast.LENGTH_SHORT).show(); break; case R.id.action_settings2: Toast.makeText(this, "点击了菜单项二", Toast.LENGTH_SHORT).show(); break; } return super.onOptionsItemSelected(item); } ~~~ (4)动态添加菜单项          MainActivity.java ~~~ @Override public boolean onCreateOptionsMenu(Menu menu) { //menu.add(groupId, itemId, order, title):返回值是MenuItem //(2)动态设置 MenuItem menuItem = menu.add(1, 100, 1, "菜单一"); menuItem.setTitle("Menu一"); menuItem.setIcon(R.drawable.ic_launcher); //API>=11时不显示图标 menu.add(1, 101, 2, "菜单二"); menu.add(1, 102, 3, "菜单三"); menu.add(1, 103, 4, "菜单四"); return super.onCreateOptionsMenu(menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { // TODO Auto-generated method stub switch (item.getItemId()) { case 100: Intent intent=new Intent(MainActivity.this,Menu1.class); item.setIntent(intent); //设置点击跳转页面 Toast.makeText(this, "点击了菜单项一", Toast.LENGTH_SHORT).show(); break; case 101: Toast.makeText(this, "点击了菜单项二", Toast.LENGTH_SHORT).show(); break; case 102: Toast.makeText(this, "点击了菜单项三", Toast.LENGTH_SHORT).show(); break; case 103: Toast.makeText(this, "点击了菜单项四", Toast.LENGTH_SHORT).show(); break; } return super.onOptionsItemSelected(item); } ~~~ ### 2、上下文菜单(ContextMenu) 在一个Activity里面只有一个“选项菜单”,它是针对整个Activity的。如果长按Activity里面的某个View(ListView、GridView等),也会弹出一个菜单操作,这个就是上下文菜单。 (1)创建方法: 1)首先给View(ListView、GridView等)注册上下文菜单registerForContextMenu(); 2)添加上下文菜单内容onCreateContextMenu();  A.通过加载xml文件中的菜单项;   B.通过代码动态添加; 3)设置菜单点击后的响应事件:onContextItemSelected(); ~~~ public class MainActivity extends Activity { private ListView listView; private SimpleAdapter simpleAdapter; private List<Map<String, Object>> data; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); listView = (ListView) findViewById(R.id.listView); data = new ArrayList<Map<String, Object>>(); simpleAdapter = new SimpleAdapter(this, getData(), R.layout.item, new String[] { "image", "text" }, new int[] { R.id.imageView, R.id.textView }); listView.setAdapter(simpleAdapter); // 为ListVIew注册上下文菜单 this.registerForContextMenu(listView); } private List<Map<String, Object>> getData() { Map<String, Object> map1 = new HashMap<String, Object>(); map1.put("image", R.drawable.calendar); map1.put("text", "日历"); data.add(map1); Map<String, Object> map2 = new HashMap<String, Object>(); map2.put("image", R.drawable.camera); map2.put("text", "照相机"); data.add(map2); Map<String, Object> map3 = new HashMap<String, Object>(); map3.put("image", R.drawable.clock); map3.put("text", "时钟"); data.add(map3); Map<String, Object> map4 = new HashMap<String, Object>(); map4.put("image", R.drawable.games_control); map4.put("text", "游戏"); data.add(map4); Map<String, Object> map5 = new HashMap<String, Object>(); map5.put("image", R.drawable.world); map5.put("text", "地图"); data.add(map5); return data; } //选项菜单 @Override public boolean onCreateOptionsMenu(Menu menu) { // TODO Auto-generated method stub return super.onCreateOptionsMenu(menu); } // 重写上下文菜单 @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { menu.setHeaderTitle("应用程序扩展操作"); menu.setHeaderIcon(R.drawable.ic_launcher); //动态添加菜单项 //menu.add(1, 100, 1, "粘贴"); //menu.add(1, 101, 1, "复制"); //menu.add(1, 102, 1, "剪切"); //menu.add(1, 103, 1, "重命名"); //通过XML加载菜单项 MenuInflater inflater=getMenuInflater(); inflater.inflate(R.menu.main_context, menu); } // 设置上下文菜单的点击事件 @Override public boolean onContextItemSelected(MenuItem item) { // TODO Auto-generated method stub /*switch (item.getItemId()) { case 100: Toast.makeText(MainActivity.this, "点击了粘贴", Toast.LENGTH_SHORT).show(); break; case 101: Toast.makeText(MainActivity.this, "点击了复制", Toast.LENGTH_SHORT).show(); break; case 102: Toast.makeText(MainActivity.this, "点击了剪切", Toast.LENGTH_SHORT).show(); break; case 103: Toast.makeText(MainActivity.this, "点击了重命名", Toast.LENGTH_SHORT).show(); break; }*/ switch (item.getItemId()) { case R.id.action_settings1: Toast.makeText(MainActivity.this, "点击了粘贴", Toast.LENGTH_SHORT).show(); break; case R.id.action_settings2: Toast.makeText(MainActivity.this, "点击了复制", Toast.LENGTH_SHORT).show(); break; case R.id.action_settings3: Toast.makeText(MainActivity.this, "点击了剪切", Toast.LENGTH_SHORT).show(); break; case R.id.action_settings4: Toast.makeText(MainActivity.this, "点击了重命名", Toast.LENGTH_SHORT).show(); break; } return super.onContextItemSelected(item); } } ~~~ ### 3、子菜单(SubMenu) res——》menu——》main.xml(子菜单的布局方法) ~~~ <menu xmlns:android="http://schemas.android.com/apk/res/android" > <item android:showAsAction="never" android:title="文件"> <menu > <item android:id="@+id/new_file" android:showAsAction="never" android:title="新建"/> <item android:id="@+id/open_file" android:showAsAction="never" android:title="打开"/> <item android:id="@+id/save_file" android:showAsAction="never" android:title="保存"/> <item android:id="@+id/rename_file" android:showAsAction="never" android:title="重命名"/> </menu> </item> <item android:showAsAction="never" android:title="编辑"> <menu > <item android:id="@+id/v_file" android:showAsAction="never" android:title="粘贴"/> <item android:id="@+id/c_edit" android:showAsAction="never" android:title="复制"/> <item android:id="@+id/x_edit" android:showAsAction="never" android:title="剪切"/> <item android:id="@+id/rename_edit" android:showAsAction="never" android:title="重命名"/> </menu> </item> </menu> ~~~ MainActivity.java(以下代码将动态添加子菜单注释起来了) ~~~ package com.example.testsubmenu; import android.os.Bundle; import android.app.Activity; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.SubMenu; import android.widget.Toast; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. // getMenuInflater().inflate(R.menu.main, menu); //动态添加子菜单项 /*SubMenu subMenu1 = menu.addSubMenu("文件"); SubMenu subMenu2 = menu.addSubMenu("编辑"); subMenu1.setHeaderTitle("文件操作"); subMenu1.setHeaderIcon(R.drawable.ic_launcher); subMenu1.add(1, 100, 1, "新建"); subMenu1.add(1, 101, 1, "打开"); subMenu1.add(1, 102, 1, "保存"); subMenu1.add(1, 103, 1, "重命名"); subMenu2.setHeaderTitle("编辑操作"); subMenu2.setHeaderIcon(R.drawable.ic_launcher); subMenu2.add(2, 100, 1, "粘贴"); subMenu2.add(2, 101, 1, "复制"); subMenu2.add(2, 102, 1, "剪切"); subMenu2.add(2, 103, 1, "重命名");*/ //通过加载XML静态加载子菜单 MenuInflater menuInflater=getMenuInflater(); menuInflater.inflate(R.menu.main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // TODO Auto-generated method stub //动态的点击事件 /*if (item.getGroupId()==1) { switch (item.getItemId()) { case 100: Toast.makeText(this, "点击了新建", Toast.LENGTH_SHORT).show(); break; case 101: Toast.makeText(this, "点击了打开", Toast.LENGTH_SHORT).show(); break; case 102: Toast.makeText(this, "点击了保存", Toast.LENGTH_SHORT).show(); break; case 103: Toast.makeText(this, "点击了重命名", Toast.LENGTH_SHORT).show(); break; } } else { switch (item.getItemId()) { case 100: Toast.makeText(this, "点击了粘贴", Toast.LENGTH_SHORT).show(); break; case 101: Toast.makeText(this, "点击了复制", Toast.LENGTH_SHORT).show(); break; case 102: Toast.makeText(this, "点击了剪切", Toast.LENGTH_SHORT).show(); break; case 103: Toast.makeText(this, "点击了重命名", Toast.LENGTH_SHORT).show(); break; } }*/ //静态的点击事件 switch (item.getItemId()) { case R.id.new_file: Toast.makeText(this, "点击了新建", Toast.LENGTH_SHORT).show(); break; case R.id.open_file: Toast.makeText(this, "点击了打开", Toast.LENGTH_SHORT).show(); break; case R.id.save_file: Toast.makeText(this, "点击了保存", Toast.LENGTH_SHORT).show(); break; case R.id.rename_file: Toast.makeText(this, "点击了重命名", Toast.LENGTH_SHORT).show(); break; case R.id.v_file: Toast.makeText(this, "点击了粘贴", Toast.LENGTH_SHORT).show(); break; case R.id.c_edit: Toast.makeText(this, "点击了复制", Toast.LENGTH_SHORT).show(); break; case R.id.x_edit: Toast.makeText(this, "点击了剪切", Toast.LENGTH_SHORT).show(); break; case R.id.rename_edit: Toast.makeText(this, "点击了重命名", Toast.LENGTH_SHORT).show(); break; } return super.onOptionsItemSelected(item); } } ~~~
';

Android之Notification

最后更新于:2022-04-01 14:27:25

Android之Notification案例展示: ~~~ public class MainActivity extends Activity implements OnClickListener{ NotificationManager manager; //通知栏控制类 int notification_ID; //通知ID @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); manager=(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); //获取系统通知服务 findViewById(R.id.btnSend).setOnClickListener(this); findViewById(R.id.btnCancle).setOnClickListener(this); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public void onClick(View v) { // TODO Auto-generated method stub switch (v.getId()) { case R.id.btnSend: sendNotification(); break; case R.id.btnCancle: cancleNotification(); break; } } private void sendNotification() { Builder builder=new Notification.Builder(this); builder.setTicker("Hello"); // 设置手机状态栏的提示 builder.setSmallIcon(R.drawable.ic_launcher); // 设置手机状态栏的图标 builder.setWhen(System.currentTimeMillis()); // 设置时间 builder.setContentTitle("通知栏通知"); // 设置标题 builder.setContentText("通知栏提示的内容"); // 设置通知内容 Intent intent=new Intent(this,MainActivity.class); //设置点击后跳转到MainActivity PendingIntent pendingIntent=PendingIntent.getActivity(this, 0, intent, 0); builder.setContentIntent(pendingIntent); //设置点击后的意图 builder.setDefaults(Notification.DEFAULT_ALL); //直接设置成默认,就全部包含了以下设置 /* 添加权限 * <uses-permission android:name="android.permission.VIBRATE"/> * <uses-permission android:name="android.permission.FLASHLIGHT"/> * */ //builder.setDefaults(Notification.DEFAULT_SOUND); //设置提示音 //builder.setDefaults(Notification.DEFAULT_LIGHTS); //设置指示灯 //builder.setDefaults(Notification.DEFAULT_VIBRATE); //设置震动 Notification notification=builder.build(); //获取Notification // 4.1以上 //Notification notification2=builder.getNotification(); // 4.1以下 manager.notify(notification_ID, notification); //通过通知栏控制类显示通知 } private void cancleNotification() { // TODO Auto-generated method stub manager.cancel(notification_ID); //取消通知 } } ~~~ 效果图: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-06_5704cced08f15.jpg) ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-06_5704cced1d85c.jpg) ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-06_5704cced33bca.jpg) ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-06_5704cced46dca.jpg)
';

Android之Dialog

最后更新于:2022-04-01 14:27:23

### 1、Dialog种类: (1)确认对话框;    (2)单选按钮对话框;   (3)多选按钮对话框;      (4)列表对话框; ### 2、Dialog常用方法: (1)创建AlertDialog:AlertDialog.Builder中的create()方法; (2)setTitle:设置对话框标题; (3)setIcon:设置对话框图标; (4)setMessage:设置对话框内容; (5)setView:给对话框设置自定义样式; (6)setItems:设置对话框要显示的一个list,一般用于显示几个命令时; (7)setMultiChoiceItems:用来设置对话框显示一系列的复选框; (8)setSingleChoiceItems:设置单选按钮; (9)setNeutralButton:设置普通按钮; (10)setPositiveButton:给对话框添加“确认”按钮 (11)setNegativeButton:给对话框添加“取消”按钮 ### 3、确认对话框 ~~~ findViewById(R.id.btnOK).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub AlertDialog.Builder builder = new AlertDialog.Builder( MainActivity.this); builder.setTitle("确认对话框"); builder.setIcon(R.drawable.ic_launcher); builder.setMessage("这是“确认对话框”的提示内容部分!"); builder.setPositiveButton("确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // TODO Auto-generated method stub Toast.makeText(MainActivity.this, "点击了确定按钮", Toast.LENGTH_LONG).show(); } }); builder.setNegativeButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // TODO Auto-generated method stub Toast.makeText(MainActivity.this, "点击了取消按钮", Toast.LENGTH_LONG).show(); } }); AlertDialog dialog = builder.create(); dialog.show(); } }); ~~~ 效果图: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-06_5704ccec87874.jpg) ### 4、单选对话框 ~~~ <span style="white-space:pre"> </span>private String[] single_list={"男","女","未知"}; //设置选项 findViewById(R.id.btnSingle).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub AlertDialog.Builder builder = new AlertDialog.Builder( MainActivity.this); builder.setTitle("单选对话框"); builder.setIcon(R.drawable.ic_launcher); builder.setSingleChoiceItems(single_list, 0, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // TODO Auto-generated method stub String str=single_list[which]; //which参数 Toast.makeText(MainActivity.this, "您选择的性别是:"+str , Toast.LENGTH_LONG).show(); } }); AlertDialog dialog = builder.create(); dialog.show(); } }); } ~~~ 效果图: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-06_5704ccec9cb71.jpg) ### 5、多选对话框 ~~~ <span style="white-space:pre"> </span>private String[] multi_list={"篮球","足球","排球","乒乓球","羽毛球"}; private String like=""; findViewById(R.id.btnMulti).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub AlertDialog.Builder builder = new AlertDialog.Builder( MainActivity.this); builder.setTitle("多选对话框——爱好"); builder.setIcon(R.drawable.ic_launcher); builder.setMultiChoiceItems(multi_list,null,new DialogInterface.OnMultiChoiceClickListener() { @Override public void onClick(DialogInterface dialog, int which, boolean isChecked) { // TODO Auto-generated method stub if(isChecked){ like+=multi_list[which]; like+=","; Toast.makeText(MainActivity.this, "您选择了"+multi_list[which], Toast.LENGTH_SHORT).show(); } else{ Toast.makeText(MainActivity.this, "您取消了"+multi_list[which], Toast.LENGTH_SHORT).show(); } } }); builder.setPositiveButton("确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // TODO Auto-generated method stub Toast.makeText(MainActivity.this, "您的爱好有:"+like, Toast.LENGTH_SHORT).show(); } }); builder.setNegativeButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // TODO Auto-generated method stub dialog.dismiss(); } }); AlertDialog dialog = builder.create(); dialog.show(); } }); ~~~ 效果图: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-06_5704ccecb3991.jpg) ### 6、列表对话框 ~~~ private String[] item_list={"项目经理","技术工程师","测试","美工"}; findViewById(R.id.btnList).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub AlertDialog.Builder builder = new AlertDialog.Builder( MainActivity.this); builder.setTitle("列表对话框——部门"); builder.setIcon(R.drawable.ic_launcher); builder.setItems(item_list, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // TODO Auto-generated method stub Toast.makeText(MainActivity.this, "您是:"+item_list[which], Toast.LENGTH_SHORT).show(); } }); AlertDialog dialog = builder.create(); dialog.show(); } }); ~~~ 效果图: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-06_5704ccecc8757.jpg) ### 7、自定义对话框: (1)先去自定义一个dialog布局——dialog_layout.xml ~~~ <?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" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <EditText android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:hint="请输入内容" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:text="提交" /> </LinearLayout> <ImageView android:layout_width="match_parent" android:layout_height="wrap_content" android:src="@drawable/item11" android:layout_marginTop="5dp" android:layout_gravity="center" /> </LinearLayout> ~~~ (2)主代码: ~~~ findViewById(R.id.btnSelf).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //获取自定义的对话框布局,并转换成View对象 LayoutInflater inflater=LayoutInflater.from(MainActivity.this); View view_dialog=inflater.inflate(R.layout.dialog_layout, null); AlertDialog.Builder builder = new AlertDialog.Builder( MainActivity.this); builder.setTitle("自定义对话框"); builder.setIcon(R.drawable.ic_launcher); builder.setView(view_dialog); //设置布局,把获取的自定义布局传进去 AlertDialog dialog = builder.create(); dialog.show(); } }); ~~~ 效果图: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-06_5704ccecdf2df.jpg) 全部代码见:主页——我的GitHub——AndroidStudy。
';

Android之Toast

最后更新于:2022-04-01 14:27:21

### 1、Toast常用方法: (1)Toast.makeText(context, text, duration);                           //返回值是Toast (2)toast.setText(str);                                                              //设置提示内容 (3)toast.setDuration(duration);                                              //设置持续时间(可以使用默认常量,也可以自己定义) (4)toast.setGravity(gravity, xOffset, yOffset)                         //设置toast位置 (5)toast.show();                                                                     //显示 ### 2、显示带图片的Toast ~~~ Toast toast=Toast.makeText(this, "click", Toast.LENGTH_LONG); toast.setGravity(Gravity.CENTER, 0, 0); LinearLayout toast_Layout=(LinearLayout) toast.getView(); ImageView imageView =new ImageView(this); imageView.setBackgroundResource(R.drawable.ic_launcher); toast_Layout.addView(imageView,0); //0是设置图片在toast_Layout中的位置 toast.show(); ~~~ ### 3、自定义Toast toast.xml ~~~ <?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:layout_width="wrap_content" android:layout_height="30dp" android:gravity="center" android:text="这个是自定义的Toast"/> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_launcher"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:text="这是Toast的内容部分!"/> </LinearLayout> ~~~ 主代码: ~~~ LayoutInflater layoutInflater=LayoutInflater.from(this); View toast_view=layoutInflater.inflate(R.layout.toast, null); Toast toast=new Toast(this); toast.setView(toast_view); toast.show(); ~~~
';

Gallery和ImageSwitcher

最后更新于:2022-04-01 14:27:18

activity_main.xml: ~~~ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity" > <Gallery android:id="@+id/gallery" android:layout_width="match_parent" android:layout_height="wrap_content" /> <ImageSwitcher android:id="@+id/imageSwitcher" android:layout_marginTop="150dp" android:layout_width="match_parent" android:layout_height="wrap_content" > </ImageSwitcher> </LinearLayout> ~~~ 自定义的ImageAdapter: ~~~ public class ImageAdapter extends BaseAdapter { private int[] res; private Context context; public ImageAdapter(int[] res,Context context) { super(); this.res = res; this.context=context; } @Override public int getCount() { // TODO Auto-generated method stub return Integer.MAX_VALUE; //以便“无限”循环显示(一般情况下滚动不到这个最大值) } @Override public Object getItem(int position) { // TODO Auto-generated method stub return res[position]; } @Override public long getItemId(int position) { // TODO Auto-generated method stub return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { // TODO Auto-generated method stub ImageView imageView=new ImageView(context); imageView.setBackgroundResource(res[position%res.length]); //无限“循环”显示 imageView.setLayoutParams(new Gallery.LayoutParams(200, 150)); // imageView.setScaleType(ScaleType.FIT_XY); //设置拉伸效果 return imageView; } } ~~~ MainActivity.java ~~~ public class MainActivity extends Activity implements OnItemSelectedListener,ViewFactory{ //准备数据源 private int[] resIcon = { R.drawable.item1, R.drawable.item2, R.drawable.item3, R.drawable.item4, R.drawable.item5, R.drawable.item6, R.drawable.item7, R.drawable.item8, R.drawable.item9, R.drawable.item10, R.drawable.item11, R.drawable.item12 }; private Gallery gallery; private ImageAdapter adapter; private ImageSwitcher imageSwitcher; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); gallery=(Gallery) findViewById(R.id.gallery); imageSwitcher=(ImageSwitcher) findViewById(R.id.imageSwitcher); //gallery加载适配器 adapter=new ImageAdapter(resIcon, this); gallery.setAdapter(adapter); //设置监听器 gallery.setOnItemSelectedListener(this); //ImageSwitcher imageSwitcher.setFactory(this); imageSwitcher.setInAnimation(AnimationUtils.loadAnimation(this, android.R.anim.fade_in)); imageSwitcher.setOutAnimation(AnimationUtils.loadAnimation(this, android.R.anim.fade_out)); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { // imageView.setBackgroundResource(res[position%res.length]); //无限“循环”显示 imageSwitcher.setBackgroundResource(resIcon[position%resIcon.length]); } @Override public View makeView() { // TODO Auto-generated method stub ImageView imageView=new ImageView(this); imageView.setScaleType(ScaleType.FIT_CENTER); return imageView; } @Override public void onNothingSelected(AdapterView<?> parent) { // TODO Auto-generated method stub } } ~~~ 效果图: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-06_5704ccec53210.jpg)
';

Android重要控件概览(下)

最后更新于:2022-04-01 14:27:16

### 1、ViewFlipper——多页面管理控件,实现子界面的自动切换 (1)为ViewFlipper加入View:A.静态导入(在Layout布局文件中直接添加View控件); B.动态导入(addView()) (2)设置进入动画:setInAnimation(); 设置退出动画:setOutAnimation(); 设置视图切换自动播放时间间隔:setFlipInterval(); 开始播放:startFlipping(); (3)设置支持手势活动: ~~~ @Override public boolean onTouchEvent(MotionEvent event) { // TODO Auto-generated method stub switch (event.getAction()) { //手指落下 case MotionEvent.ACTION_DOWN: { startX=event.getX(); break; } //手指滑动 case MotionEvent.ACTION_UP: { //向右滑动 if(event.getX()-startX>50) { flipper.setInAnimation(this, R.anim.left_in); flipper.setOutAnimation(this, R.anim.left_out); flipper.showNext(); } //向左滑动 if(startX-event.getX()>50) { flipper.setInAnimation(this, R.anim.right_in); flipper.setOutAnimation(this, R.anim.right_out); flipper.showPrevious(); } break; } } //手指离开 case MotionEvent.ACTION_UP: { break; } return super.onTouchEvent(event); } ~~~ ### 2、ScrollView——内容很多,屏幕显示不完,通过滚动来显示完整的视图 (1)ScrollView种类:A. HorizontalScrollView:水平滚动视图;B.ScrollView:垂直滚动视图; (2)属性:设置不显示滚动条:Android:scrollbars="none"; (3)代码设置隐藏滚动条:setHorizontalScrollBarEnabled(false);setVerticalScrollBarEnabled(false); (4)监听器:setOnTouchListenter() ~~~ scroll.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { // TODO Auto-generated method stub switch (event.getAction()) { case MotionEvent.ACTION_MOVE: { /** * (1)getScrollY()————滚动条滑动的距离 * (2)getMeasuredHeight() * (3)getHeight() */ // 顶部状态 if (scroll.getScrollY() <= 0) { Log.i("Main", "滑动到顶部"); } // 底部状态 // TextView的总高度<=一屏幕的高度+滚动条的滚动距离 if (scroll.getChildAt(0).getMeasuredHeight() <= scroll.getHeight() + scroll.getScrollY()) { Log.i("Main", "滑动到底部"); Log.i("Main", "scroll.getChildAt(0).getMeasuredHeight()=" + scroll.getChildAt(0) .getMeasuredHeight() + "scroll,getHeight()=" + scroll.getHeight() + "scroll.getScrollY()=" + scroll.getScrollY()); tv.append(getResources().getString(R.string.content)); // 刷新、追加 } break; } } return false; } }); } ~~~ (5)scrollTo和scrollBy scrollTo:以滚动视图起始位置开始计算; scrollBy:相对前一次的位置,去滚动相应距离 ### 3、Gallery——缩略图浏览器 [http://blog.csdn.net/songshimvp1/article/details/50233727](http://blog.csdn.net/songshimvp1/article/details/50233727)——实际案例 ### 4、SeekBar——拖动条 (1)方法:setMax:设置最大数值; (2)事件监听:OnSeekBarChangeListenter监听三个事件: A. onProgressChanged();      //数值改变 B. onStartTrackingTouch();    //开始拖动 C. onStopTrackingTouch();    //停止拖动 (3)自定义SeekBar 看不到源码时,可以在G:\AndroidWork\adt-bundle-windows-x86-20130917\sdk\platforms\android-18\data\res\drawable中查找!     
';

Android重要控件概览(中)

最后更新于:2022-04-01 14:27:14

### 1、ProgressBar (1)属性:         android:max="100"   ;  ——最大显示进度         android:progress="50"  ;  ——第一显示进度         android:secondaryProgress="80"  ;  ——第二显示进度         android:indeterminate="true"   ;  ——设置是否精确显示(true表示不精确显示) (2)方法:         setProgress(int) ; ——设置第一进度         setSecondaryProgress(int)  ; ——设置第二进度         getProgress( ) ; ——获取第一进度         getSecondaryProgress( )  ;  ——获取第二进度         incrementProgressBy( int )  ;  ——增加或者减少第一进度         incrementSecondaryProgressBy (int )  ; ——增加或者减少第二进度         getMax( )  :获取最大进度 (3)在标题栏上上设置 ~~~ protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //启用窗口特征,启用带进度和不带进度的进度条 requestWindowFeature(Window.FEATURE_PROGRESS); requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); setContentView(R.layout.activity_main); //显示两种进度条 setProgressBarVisibility(true); setProgressBarIndeterminateVisibility(true); //MAX=10000 setProgress(6000); } ~~~ (4)对话框式进度条 ~~~ btnDia=(Button) findViewById(R.id.btnDia); btnDia.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { /*设置页面显示风格*/ //新建ProgressDialog对象 progressDialog=new ProgressDialog(MainActivity.this); //设置显示风格(横向) progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); //设置标题 progressDialog.setTitle("对话框式进度条"); //设置图标 progressDialog.setIcon(R.drawable.ic_launcher); //设置对话框里的文字信息 progressDialog.setMessage("欢迎你!"); //设置"确定"按钮 progressDialog.setButton(DialogInterface.BUTTON_POSITIVE,"确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Toast.makeText(MainActivity.this, "这是对话框式进度条!", Toast.LENGTH_LONG).show(); } }); //设置是否通过返回按钮退出对话框 progressDialog.setCancelable(true); /*设置关于ProgressBar的属性*/ //设置最大进度 progressDialog.setMax(100); //设置初始化已经增长到的进度 progressDialog.incrementProgressBy(20); //进度条是明确显示进度的 progressDialog.setIndeterminate(false); //显示对话框 progressDialog.show(); } }); ~~~ (5)自定义ProgressBar ~~~ style="@android:style/Widget.ProgressBar.Horizontal" //Ctrl+左键 查看 <style name="Widget.ProgressBar.Horizontal"> <item name="android:indeterminateOnly">false</item> <item name="android:progressDrawable">@android:drawable/progress_horizontal</item> <item name="android:indeterminateDrawable">@android:drawable/progress_indeterminate_horizontal</item> <item name="android:minHeight">20dip</item> <item name="android:maxHeight">20dip</item> <item name="android:mirrorForRtl">true</item> </style> //继续查看@android:drawable ~~~ 新建一个自己的progress_horizontal.xml文件,去覆盖系统的。(复制原来的,在原来的基础上进行修改)然后在ProgressBar属性中添加: ~~~ android:progressDrawable="@drawable/progress_horizontal" ~~~ ### 2、WebView显示网页 (引言:可以通过Intent调用系统浏览器,直接实现跳转) (1)权限:    <uses-permission android:name="android.permission.INTERNET"/> (2)加载:A.本地文件:webView.loadUrl( "file:///android_asset/example.html")       //本地文件存放在assets目录下 B.加载Web资源:webView.loadUrl("http://www.baidu.com")      C.覆盖WebView默认通过第三方或者系统浏览器打开网页的行为,使得网页可以在WebView中打开 ~~~ webView.setWebViewClient(new WebViewClient(){ //WebViewClient帮助WebView去处理一些页面控制和请求通知 ...... return true ...... }); ~~~ D.获得当前WebView的URL:webView.getUrl( ); (3)在WebView中使用Javascript ~~~ WebSettings webSettings = webView.getSettings(); //获取WebSettings的值 webSettings.setJavaScriptEnabled(true); //启用JavaScript ~~~ (4)改写物理按键——返回的逻辑 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-06_5704ccec0c6c4.jpg) (5) ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-06_5704ccec2b984.jpg) (6)WebView缓存的运用 A.优先使用缓存:webView.getSettings( ).setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); B. 不使用缓存   :webView.getSettings( ).setCacheMode(WebSettings.LOAD_NO_CACHE); ### 3、Fragment——主要目的是用在大屏幕设备上,支持更加动态和灵活的UI设计。 Fragment在应用中应当是一个模块化和可重用的组件,因为Fragment定义了自己的布局,以及通过使用它自己的生命周期回调方法定义了它自己的行为,所以可以将Fragment包含到多个Activity中。 (1)Fragment可以作为Activity界面的一部分组成出现;可以在一个Activity中同时出现多个Fragment,并且一个Fragment也可以在多个Activity中使用;在Activity运行过程中,可以添加、移除或者替换Fragment;Fragment可以相应自己的输入事件,并且有自己的声明周期,它们的生命周期会受宿主Activity的生命周期的影响。 (2)静态加载——在Activity的Layout文件中声明Fragment A.android:name属性:指定了在layout中实例化的Fragment类 B.android:id属性:提供了一个唯一ID 来标识 C.android:tag属性:提供了一个唯一的字符串 来标识 (3)动态加载——撰写代码将Fragment添加到一个Activity layout中(处理Fragment事务) A.开启事务:FragmentManager fragmentManager = getFragmentManager();  FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); B.执行的操作:add();  remove();  replace();  addToBackStack();  commit();   (4)声明周期: A. onCreateView:每次创建都会绘制Fragment的View组件时回调该方法 B. onAttach:当Fragment被添加到Activity时候会回调这个方法,并且只调用一次 C. onCreate:创建Fragment时会回调,只会调用一次 D. onActivityCreated:当Fragment所在的Activty启动完成后调用 E. onStart:启动Fragment F. onResume:恢复Fragment时会被回调,调用onStart()方法后面一定会调用onResume()方法 G. onPause:暂停Fragment H. onStop:停止Fragment I.  onDestroyView:销毁Fragment所包含的View组件时 J. onDestroy:销毁Fragment时会被回调 K. onDetach:Fragment从Activity中删除时会回调该方法,并且这个方法只会调用一次 (5)与Activity传值通信: A. Fragment调用getActivity()方法获取它所在的Activity; Activity调用FragmentManager的findFragmentById()或者findFragmentByTag()方法获取Fragment; B. Activity——》Fragment:在Activity中创建Bundle数据包,并调用Fragment的setArguments(Bundle bundle)方法; Fragment——》Activity:需要在Fragment中定义一个内部回调接口,让包含该Fragment的Activity实现该回调接口。这样Fragment可调用回调方法将数据传递给Activity。 ### 4、ViewPager使视图左右滑动(类似微信界面) (1)加载显示的页卡: A. layoutInflater if = getLayoutInflater().from(this); if.inflate(resource,root); B. View.inflate(context,resource,root); (2)配置Adapter: A. PagerAdapter   数据源:List<View>; B. FragmentPagerAdapter   数据源:List<Fragment>; C. FragmentStatePagerAdapter   数据源:List<Fragment>; (3)监听器 OnPageChangeListener 简单粘一下实现代码: ~~~ <android.support.v4.view.ViewPager android:id="@+id/pager" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" > <android.support.v4.view.PagerTabStrip android:id="@+id/pagerTab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="top" > </android.support.v4.view.PagerTabStrip> </android.support.v4.view.ViewPager> ~~~ 数据适配器: ~~~ public class MyPagerAdapter extends PagerAdapter { private List<View> viewList; private List<String> titleList; public MyPagerAdapter(List<View> viewList, List<String> titleList) { this.viewList = viewList; this.titleList = titleList; } // 返回的是页卡的数量 @Override public int getCount() { // TODO Auto-generated method stub return viewList.size(); } // View是否来自与对象 @Override public boolean isViewFromObject(View arg0, Object arg1) { // TODO Auto-generated method stub return arg0 == arg1; } // 实例化一个页卡 @Override public Object instantiateItem(ViewGroup container, int position) { container.addView(viewList.get(position)); return viewList.get(position); } // 销毁页卡 @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView(viewList.get(position)); } //设置ViewPager页卡的标题 @Override public CharSequence getPageTitle(int position) { // TODO Auto-generated method stub return titleList.get(position); } } ~~~ MainActivity : ~~~ public class MainActivity extends Activity { private List<View> viewList; private ViewPager viewPager; private List<String> titleList; private PagerTabStrip tabStrip; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); viewList=new ArrayList<View>(); //通过View对象作为ViewPager的数据源 View view1=View.inflate(this, R.layout.view1, null); View view2=View.inflate(this, R.layout.view2, null); View view3=View.inflate(this, R.layout.view3, null); View view4=View.inflate(this, R.layout.view4, null); viewList.add(view1); viewList.add(view2); viewList.add(view3); viewList.add(view4); //初始化ViewPager viewPager=(ViewPager) findViewById(R.id.pager); //为ViewPager设置标题 titleList=new ArrayList<String>(); titleList.add("第一页"); titleList.add("第二页"); titleList.add("第三页"); titleList.add("第四页"); //为PagerTabStrip设置一些属性 tabStrip=(PagerTabStrip) findViewById(R.id.pagerTab); tabStrip.setBackgroundColor(Color.BLUE); tabStrip.setTextColor(Color.RED); tabStrip.setDrawFullUnderline(false); tabStrip.setTabIndicatorColor(Color.GREEN); //创建PagerAdapter的适配器 MyPagerAdapter adapter=new MyPagerAdapter(viewList,titleList); //ViewPager加载适配器 viewPager.setAdapter(adapter); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } } ~~~
';

动态引用APK文件

最后更新于:2022-04-01 14:27:11

不安装APK,仍然可以调用APK文件中的Java类,这种访问Java类的方式称为“动态引用APK文件”,——相当于传统的java程序动态调用jar文件。 APK文件本质上是ZIP格式的压缩文件,要想动态调用APK文件,在APK文件中必须包含一个classes.dex文件(classes.dex文件是Android应用中所有的Java源代码编译生成的Davlik虚拟机格式的二进制文件)。每一个编译过的Android工程目录的bin目录下都有一个classes.dex文件和一个相应的APK文件。 动态调用的APK文件的扩展名并不重要,也可以使用任何的扩展名,还甚至可以没有扩展名。比如XXXX.apk,XXXX.jar,XXXX.abcd,XXXX都没问题。 下面演示一个动态调用APK文件中的Java类的完整案例: (1)编写Remote工程——新建一个Remote项目,并在其中添加一个如下类: ~~~ package songshi.remote; public class ServiceClass { public String addService(){ return "MyProject调用Remote工程的AddService方法成功"; } } ~~~ 运行Remote工程,生成Remote.apk(在bin目录下),将此APK文件push到Android模拟器DDMS的/mnt/sdcard/下。 (2)编写MyProject工程,布局文件添加一个按钮 ~~~ package com.songshi.myproject; import java.lang.reflect.Method; import dalvik.system.DexClassLoader; import android.media.RemoteControlClient.MetadataEditor; import android.os.Bundle; import android.os.Environment; import android.app.Activity; import android.view.Menu; import android.view.View; import android.widget.Button; import android.widget.Toast; public class MainActivity extends Activity { /* * 使用DexClassLoader类动态装载APK文件 * public DexClassLoader(String dexPath, String optimizedDirectory, String libraryPath, ClassLoader parent); * dexPath参数:表示APK文件的路径; * optimizedDirectory参数:表示一个用于写入优化后的APK文件的目录,通常为程序的私有数据目录; * parent参数:通常为ClassLoader.getSystemClassLoader() * */ private DexClassLoader dexClassLoader; private Button btnAdd; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //第 1 步:装载APK文件 //定义优化目录:/data/data/com.songshi.myproject String optimizedDirectory= Environment.getDataDirectory().toString() + "/data/" + getPackageName(); dexClassLoader=new DexClassLoader("/mnt/sdcard/Remote.apk", optimizedDirectory, null, ClassLoader.getSystemClassLoader()); btnAdd=(Button) findViewById(R.id.btnAdd); btnAdd.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub try{ //第 2 步:装载要访问的类 Class c=dexClassLoader.loadClass("songshi.remote.ServiceClass"); //Call requires API level 14 (current min is 8) //第 3 步:创建类的对象 Object obj=c.newInstance(); //第 4 步:用Java反射技术调用ServiceClass类中的addService方法 Method method = obj.getClass().getMethod("addService", null); String add =String.valueOf(method.invoke(obj, null)); Toast.makeText(MainActivity.this, add, Toast.LENGTH_LONG).show(); } catch(Exception e){ Toast.makeText(MainActivity.this, "error:"+e.getMessage(), Toast.LENGTH_LONG).show(); } } }); } /* * APK文件并不是什么类都可以调用。例如,有Context类型参数的方法就不能动态访问,因为只有已经安装的APK程序才能获得Context对象。 * 还有四大组件类也不可以使用,例如,由于窗口类是由系统自动创建和维护的,所以 Activity的子类自然就不能通过动态访问的方式当做窗口类来使用。 * */ @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } } ~~~ 运行 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-06_5704ccebe3592.jpg) 特别注意:APK文件并不是什么类都可以调用。例如,有Context类型参数的方法就不能动态访问,因为只有已经安装的APK程序才能获得Context对象。还有四大组件类也不可以使用,例如,由于窗口类是由系统自动创建和维护的,所以 Activity的子类自然就不能通过动态访问的方式当做窗口类来使用。
';

Android布局概览

最后更新于:2022-04-01 14:27:09

### 一、LinearLayout(线性布局) 常用属性: A. android:orientation="vertical"   或者  android:orientation="horizontal" ——决定子类控件垂直或者水平排布 B. android:gravity  =  "center_horizontal  |  bottom" ——决定子类控件的X、Y位置 center:垂直水平都居中right(右)、left(左)、bottom(下面) center_vertical:垂直(Y轴)居中 center_horizontal:水平(X轴)居中 C. android:layout_gravity="bottom"     ——指的是子控件本身在当前父容器的X、Y位置 android:layout_weight="1" ——指的是子控件本身占当前父容器的一个比例(wrap_content正比、match_parent反比) 注意:即使设置了也不一定起作用。比如:水平的LinearLayout要从左边开始依次放置布局,所以设置TextView的layout_gravity属性为right也不起作用。 ### 二、RelativeLayout(相对布局) 常用属性:(align 系列、margin系列、center系列) (1)以下属性是 子类控件 相对于 父类(RelativeLayout)的) ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-06_5704cceb27f4f.jpg) (2)以下属性是 子类控件 相对于 子类控件的 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-06_5704cceb5c442.jpg) ### 三、FrameLayout(帧布局) 在这个布局中,所有的子元素都不能被指定防止的位置,它们统统放于这块区域的左上角,并且后面的子元素直接覆盖在前面的子元素之上,将前面的子元素部分和全部遮挡。 A.使用android:foreground——设置前景图,在所有子图的前面; B.使用android:background——设置背景 C.使用android:keepScreenOn——保持屏幕唤醒 D.使用android:foregroundGravity——设置前景图的位置 ### 四、AbsoluteLayout(绝对布局) 又可以称为坐标布局,可以直接指定子元素的 绝对位置(X、Y)。——由于手机屏幕尺寸差别较大,在屏幕的适配上有缺陷。所以很少用到。 android:layout_x="30dp"    ——控制当前子控件的X位置 android:layout_y="29dp"    ——控制当前子控件的Y位置 ### 五、TableLayout(表格布局) 表格布局模型以行列的形式管理子控件,每一行为一个 TableRow 的对象,当然也可以是一个 View 的对象。索引从 0 开始。 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-06_5704cceb90ce9.jpg) ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-06_5704ccebbec5f.jpg)
';

Installation error: INSTALL_PARSE_FAILED_MANIFEST_MALFORMED

最后更新于:2022-04-01 14:27:07

**尝试下面三种解决方法:** 1. 有可能你的客户端已经安装过了,需要移调才能安装; 2. 你的清单文件AndroidManifest.xml写的有问题,检查一下; 3. 包名首字母不能大写;
';

Android重要控件概览(上)

最后更新于:2022-04-01 14:27:05

### 1、TextView android:singleLine="true"   //设置单行显示(默认可折行显示) android:gravity= "right|center_vertical"   //设置文本的位置(居右且居中) ### 2、EditView android:hint="请输入姓名"      //设置阴影提示属性 android:editable=“false”         //设置不可编辑 另外,在ADT控件下的Text Fields中,有各种各样的EditView(也就是指定了输入格式,比如android:inputType="textPassword")。 ### 3、ImageView (1)属性:android:src = "@drawable/   "   ——ImageView控件的内容图片; android:background = "@drawable/   "   ——ImageView控件的背景图片; android:background = "#f0f0f0"   ——ImageView控件的背景的RGB颜色; (2) .setBackgroundResource(R.drawable.XXX); ### 4、Button 和 ImageButton (1)Button有text属性,而ImageButton没有; (2)ImageButton有 src属性,而Button没有;(可以做一个有文本内容的图片) (3)两者都有background属性; (4)两者都有点击效果;.setOnClickListenter()   ——  A.匿名内部类的实现(new View.OnClickListener(){  ...onClick()...   }; ); —— B.独立类的实现*( 自定义 MyOnClicklistener 点击事件监听类,让该类实现implements OnClickListener接口,重写onClick方法);这种做法的好处是:如果有很多个按钮,它们要执行一个共同的事件,还要执行自己特定的事件。 ~~~ protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.button1).setOnClickListener(new MyOnClickListener(){ //自定义的监听类 @Override public void onClick(View v) { // 调用父类的onClick事件 super.onClick(v); // 执行自己特定的任务 Toast.makeText(MainActivity.this, "这是子类的事件逻辑执行", 1).show(); } }); } //自定义监听点击事件的外部类 class MyOnClickListener implements OnClickListener{ @Override public void onClick(View v) { // 这是父类的onClick方法——公有的操作,减少代码的冗余 Log.i("parent", "这是父类的事件逻辑执行"); v.setAlpha(0.5); //设置透明度 } } ........ } ~~~ ——  C.还可以是 本类(this) 直接实现implements OnClickListener接口,重写onClick方法。 ### 5、多个TextView实现跑马灯——自定义个性化控件 (1)设置TextView属性 ~~~ android:singleLine="true" android:ellipsize="marquee" android:focusable="true" android:focusableInTouchMode="true" ~~~ (2)实现继承自TextView的自定义类 ~~~ public class Marquee extends TextView { public Marquee(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); // TODO Auto-generated constructor stub } public Marquee(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub } public Marquee(Context context) { super(context); // TODO Auto-generated constructor stub } @Override @ExportedProperty(category = "focus") public boolean isFocused() { // TODO Auto-generated method stub return true; //设置return true。不断变换焦点 } } ~~~ (3)使用自定义控件——com.example.testlongtext.Marquee ~~~ <!-- 多个控件跑马灯 --> <com.example.testlongtext.Marquee android:id="@+id/te1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:singleLine="true" android:ellipsize="marquee" android:focusable="true" android:focusableInTouchMode="true" android:text="@string/hello_world" /> <com.example.testlongtext.Marquee android:id="@+id/te2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:singleLine="true" android:ellipsize="marquee" android:focusable="true" android:focusableInTouchMode="true" android:text="@string/hello_world" /> ~~~ ### 6、AutoCompleteTextView  (1)属性 android:hint = "请输入关键字" android:completionThreshold = "2"          //设置输入多少字符时自动匹配 (2)数据源:匹配文本框输入内容的数据源 ~~~ private String[] resourceData={"C","C++","C#","C-Object","java SE","java EE","java-android"}; //初始化数据源 ~~~ (3)适配器:适配下拉列表的内容(数据源) ~~~ private AutoCompleteTextView MyAutoCompleteTextView ; ArrayAdapter<String> adapter = new ArrayAdapter<String> (this,android.R.layout.simple_list_item_1,resourceData); //数据源填充到适配器 ~~~ (4)将适配器adapter 与 当前 AutoCompleteTextView 进行绑定 ~~~ MyAutoCompleteTextView .setAdapter(adapter); //绑定 ~~~ ### 7、MultiAutoCompleteTextView 基本类似上面,但是因为可以匹配多个字符串,所以可以设置分隔符(以提醒什么时候开始下一次匹配) ~~~ myMultiAutoCompleteTextView.setTokenizer( new MultiAutoCompleteTextView.CommaTokenizer()); //设置以逗号为分隔符 ~~~ ### 8、ToggleButton (1)属性:android:checked="true" android:textOn="开启"     //设置开、关的文本 android:textOff="关闭" (2)监听器:ToggleButton.setOnCheckedChangeListener(this); ### 9、CheckBox android:checked="false"        //是否被选中 监听器:.setOnCheckedChangeListener(listener);     //监听是否被选中 CheckBox.isChecked()——CheckBox.getText().toString() ### 10、RadioButton 和 RadioGroup(多选一机制) android:checked="false"        //是否被选中 RadioGroup..setOnCheckedChangeListener(listener);     //监听是否被选中   (此时,如果是本类实现,implements OnCheckedChangeListener) ### 11、ListView显示信息列表 (1)数据适配器(ArrayAdapter、SimpleAdapter);  ——把复杂数据(数组、列表、数据库等)填充到指定视图界面上;连接数据源和视图界面的桥梁; 过程:新建适配器(声明、配置)——>添加数据源到适配器——>视图加载适配器; ArrayAdapter(上下文,当前ListView加载每一个列表项所对应的布局文件,数据源);——数组适配器 SimpleAdapter(上下文,数据源 List<? extends Map<String, ?>> data(一个Map所组成的List集合)、列表项布局文件ID、Map的键名、绑定数据视图中的ID(与from成对应关系)); (2)监听器(OnScrollListenter、OnItemClickListenter);        (3)适配器数据的刷新; notifyDataSetChanged();  ——动态更新视图中所包含的数据 ### 12、DatePicker 和 TimePicker 显示当前日期和时间 ~~~ //获取日历的一个对象 calendar=Calendar.getInstance(); //获取年月日时分的信息 year=calendar.get(Calendar.YEAR); month=calendar.get(Calendar.MONTH)+1; //注意:Calendar类的月份是按0开始计算的 day=calendar.get(Calendar.DAY_OF_MONTH); hour=calendar.get(Calendar.HOUR_OF_DAY); minute=calendar.get(Calendar.MINUTE); //datePicker初始化并设置监听器(以init方法) datePicker.init(year, calendar.get(Calendar.MONTH), day, new OnDateChangedListener() { @Override public void onDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth) { // TODO Auto-generated method stub setTitle(year+"-"+(monthOfYear+1)+"-"+dayOfMonth); } }); //timePicker设置监听器(直接设置) timePicker.setOnTimeChangedListener(new OnTimeChangedListener() { @Override public void onTimeChanged(TimePicker view, int hourOfDay, int minute) { // TODO Auto-generated method stub setTitle(hourOfDay+":"+minute); } }); //用对话框形式展示日期、时间 /*new DatePickerDialog(this, new OnDateSetListener() { @Override public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) { // TODO Auto-generated method stub setTitle(year+"-"+(monthOfYear+1)+"-"+dayOfMonth); } }, year, calendar.get(Calendar.MONTH), day).show();*/ new TimePickerDialog(this, new OnTimeSetListener() { @Override public void onTimeSet(TimePicker view, int hourOfDay, int minute) { // TODO Auto-generated method stub setTitle(hourOfDay+":"+minute); } }, hour, minute, true).show(); ~~~ ### 13、GridView表格形式显示多个组件 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-06_5704cceabae66.jpg) 属性: ~~~ android:numColumns="3" //每行显示三列 android:horizontalSpacing="10dp" //设置列间距 android:verticalSpacing="10dp" //设置行间距 ~~~ 实现代码: ~~~ public class MainActivity extends Activity implements OnItemClickListener{ private GridView gridView; private List<Map<String, Object>> dataList; private int[] icon = { R.drawable.a, R.drawable.b, R.drawable.c, R.drawable.d, R.drawable.e, R.drawable.f, R.drawable.erttre, R.drawable.erwrw, R.drawable.lanqiu, R.drawable.niubi, R.drawable.psb, R.drawable.qqq }; private String[] iconName = { "格1", "格2", "格3", "格4", "格5", "格6", "格7", "格8", "格9", "格10", "格11", "格12", }; private SimpleAdapter simpleAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); gridView = (GridView) findViewById(R.id.gridView); // 1、准备数据源 // 2、新建适配器 // 3、GridView加载适配器 // 4、GridView配置时间监听器(OnItemClickListenter) dataList = new ArrayList<Map<String, Object>>(); //getData(); simpleAdapter = new SimpleAdapter(this, getData(), R.layout.gridview_item, new String[] { "image", "text" }, new int[] { R.id.image, R.id.text }); gridView.setAdapter(simpleAdapter); gridView.setOnItemClickListener(this); } private List<Map<String, Object>> getData() { // TODO Auto-generated method stub for (int i = 0; i < icon.length; i++) { Map<String, Object> map = new HashMap<String, Object>(); map.put("image", icon[i]); map.put("text", iconName[i]); dataList.add(map); } return dataList; } @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { // TODO Auto-generated method stub Toast.makeText(this, "我是"+iconName[position], Toast.LENGTH_LONG).show(); } } ~~~ ### 14、Spinner实现下拉列表 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-06_5704cceacfd9f.jpg) ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-06_5704cceaef917.jpg) (1)系统默认 ~~~ public class MainActivity extends Activity implements OnItemSelectedListener{ private TextView textView; private Spinner spinner; private List<String> list; private ArrayAdapter<String> arrayAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView=(TextView) findViewById(R.id.text); spinner=(Spinner) findViewById(R.id.spinner); textView.setText("您选择城市是北京"); //1、设置数据源 list=new ArrayList<String>(); list.add("北京"); list.add("上海"); list.add("广州"); list.add("深圳"); //2、新建ArrayAdapter(数组适配器) arrayAdapter=new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, list); //3、arrayAdapter设置一个下拉列表样式 arrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); //4、spinner加载适配器 spinner.setAdapter(arrayAdapter); //5、设置spinner监听器 spinner.setOnItemSelectedListener(this); } @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { // TODO Auto-generated method stub String cityName=arrayAdapter.getItem(position); //String cityName=list.get(position) textView.setText("您选择的城市是"+cityName); } } ~~~ (2)自定义下拉样式 利用SimpleAdapter。
';

Android工程A依赖B,B依赖C

最后更新于:2022-04-01 14:27:02

闲来无事,做了个实验。大致思路:A、B、C是三个较为庞大的工程。A工程(开源)需要用到B工程(开源),而又希望在B工程(开源)中引用C工程(开源)。也就是A是真个项目框架,B是其中一个模块,而在B中又希望集成C开源工程。 先看效果图: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-06_5704ccea0c923.jpg) ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-06_5704ccea228a7.jpg) ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-06_5704ccea36980.jpg) ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-06_5704ccea46b39.jpg) 在开始之前,请先参照[http://blog.csdn.net/songshimvp1/article/details/50015887](http://blog.csdn.net/songshimvp1/article/details/50015887)——[Android 中一个工程引用另一个工程](http://blog.csdn.net/songshimvp1/article/details/50015887) 完成B和C的连接。 C工程很简单,直接创建CMainActivity,然后改一下textView中的文字即可。 B工程,创建BMainActivity,然后设置textView和button。再设置BMainActivity主文件: ~~~ public class BMainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_b_main); findViewById(R.id.buttonBC).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View arg0) { // TODO Auto-generated method stub Intent cIntent=new Intent(BMainActivity.this,CMainActivity.class); startActivity(cIntent); } }); } ........ ~~~ 参照上述网址[http://blog.csdn.net/songshimvp1/article/details/50015887](http://blog.csdn.net/songshimvp1/article/details/50015887)连通B和C。 接下来是A。仍然是直接创建AMainActivity,然后设置textView和button。再设置AMainActivity主文件: ~~~ public class AMainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_amain); findViewById(R.id.buttonAB).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View arg0) { // TODO Auto-generated method stub Intent bIntent=new Intent(AMainActivity.this,BMainActivity.class); startActivity(bIntent); } }); } .......... ~~~ 设置依赖项时,是单层依赖,A中不去设置C,单层设置,单层依赖 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-06_5704ccea619e1.jpg) 设置清单文件时,A中要包含B和C中的所有清单文件: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-06_5704ccea89b5b.jpg) 在工程中如果出现错误,可能是资源id出现冲突,所以最好是每个项目的资源ID要个性化单独设置。还要记得clean这一招。总之,尝试一下吧,快速集成开源项目像上面这个demo一样,还是很让人愉快的。
';

Android 与 SQLite

最后更新于:2022-04-01 14:27:00

SQLite官网:sqlite.org。 ### 一、SQLiteOpenHelper类 与 数据库创建、自动升级 该类是一个抽象类。为了数据库的升级需要以及使用方便,往往使用该类的子类进行创建、打开、操作数据库。子类必须实现以下两个方法。 ~~~ public class UesrDB extends SQLiteOpenHelper { public UesrDB(Context context, String name, CursorFactory factory, int version) { super(context, name, factory, version); // TODO Auto-generated constructor stub } /* * 如果数据库不存在,SQLiteOpenHelper根据上述构造函数的name, * 在自动创建数据库之后自动执行OnCreate方法(也仅是在第一次被创建时被调用)。 * 在该方法中一般创建数据库中的表、视图等组件。 */ @Override public void onCreate(SQLiteDatabase db) { // TODO Auto-generated method stub } /* * 如果数据库存在,在上述构造函数中的version表示:数据库的版本号。 * 如果当前传递的版本号比上次创建或升级的数据库版本号高,就调用onUpgrade方法。 * 在该方法中,首先要删除原来数据库的组件,然后创建数据库中的表、视图等组件。 */ @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // TODO Auto-generated method stub } } ~~~ ### 二、SimpleCursorAdapter类 与 数据绑定 该类专门用于数据绑定,数据源是Cursor对象。在数据库的操作中进程会使用到Cursor对象,该对象封装了查询表和查询视图返回的结果集。 ~~~ SimpleCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to) ~~~ 特别注意(1): 在绑定数据时,Cursor对象返回的记录集中必须包含一个名为“_id”的字段,否则,将无法完成数据绑定。如果没有“_id”字段,可以将某个唯一索引字段或者主键的别名设为"_id"。 特别注意(2): SQLiteOpenHelper.getReadableDatabase() 和 SQLiteOpenHelper.getWritableDatabase() 这两个方法获得的 SQLiteDatabase 对象,系统会在也只能在 手机内存 的/data/data/<package name>/database目录中创建或者查找数据库文件。 ### 三、操作SD卡上的数据库 ~~~ public SQLiteDatabase openOrCreateDatabase( String path, SQLiteDatabase.CursorFactory factory ) ~~~ ~~~ public void onClick_SDCard_Database(View view){ String filename=android.os.Environment.getExternalStorageDirectory()+"/sdcard_test.db"; //数据库文件的存储路径 String createTableSQL="create table testUser(" + "_id autoinc PRIMERY KEY," + "name varchar(20), " + "sex TEXT)"; File file=new File(filename); if(file.exists()){ file.delete(); } SQLiteDatabase database=SQLiteDatabase.openOrCreateDatabase(filename, null); //打开数据库 database.execSQL(createTableSQL); ContentValues values=new ContentValues(); values.put("name","LI"); values.put("sex", "male"); database.insert("testUser", null, values); //(1)SQLiteDatabase的相应方法来操作 String insertSQL="insert into testUser (name,sex) values(?,?)"; database.execSQL(insertSQL,new Object[]{"song","female"}); String selectSQL="select name,sex from testUser where name=?"; Cursor c=database.rawQuery(selectSQL, new String[]{"song"}); //(2)rawQuery直接执行SQL语句 c.moveToFirst(); Toast.makeText(this, c.getString(0)+" "+c.getString(1), Toast.LENGTH_LONG).show(); database.close(); } ~~~ ### 四、将数据库随应用程序一起发布 ### 五、手机ARM中的数据库 这是内存数据库。该数据库只存在于手机ARM中,当程序退出以后,数据库中的数据会自动释放。
';