EmptyAction,在请求的Action没找到的时候会调用。
<?php
class EmptyAction extends Action {
public function index()
{
echo MODULE_NAME;
}
}
?>
EmptyAction,在请求的Action没找到的时候会调用。
<?php
class EmptyAction extends Action {
public function index()
{
echo MODULE_NAME;
}
}
?>
_empty方法即空操作,当找不到请求的方法时,默认执行该方法,利用这个机制,我们可以实现错误页面和一些URL的优化。
public function _empty($name)
{
echo $name;
}
参数name,即请求的方法名。如http://localhost/waimai/index.php/Index/sdfewsdf,不存在sdfewsdf方法时,会调用_empty方法,显示sdfewsdf.
XML:
android:scrollbars="none"
JAVA:
listView.setVerticalScrollBarEnabled(true);
原理,在adapter的getView方法里根据当前选中项的索引,设置背景色。在ListView的OnItemClickListener里修改adapter中选中的索引,再notifyDataSetChanged,adapter就会再次调用getView方法,更新显示 2013.08.19更新: 看了ApiDemo,发现一个更简单的方法: 设置ListView为单选模式
<ListView
android:id="@+id/lv_category"
android:choiceMode="singleChoice"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"
android:divider="@drawable/iv_left_item_separate_line" >
</ListView>
设置Item的Layout的背景为一个Selector: bg_listview_item.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_activated="true" android:drawable="@android:drawable/list_selector_background_selected" />
<item android:drawable="@color/transparent" />
</selector>
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/bg_listview_item"
android:gravity="center"
android:minHeight="80dp"
android:textColor="@color/black"
android:textSize="26sp" />
在xml中加上:
android:listSelector="@android:color/transparent"
在做的项目中需要显示一个WIFI状态的图标,与系统通知栏里的类似,要求动态显示WIFI信号,状态. Wifi在信号改变,开关以及状态改变时都会发送广播,我们接收这几个广播即可. 需要权限:
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Wifi图标这里,我用了一个ImageView,使用level-list来在信号改变时切换显示的图片:
<?xml version="1.0" encoding="utf-8"?>
<level-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:maxLevel="0"
android:drawable="@drawable/stateitems_wifi_0"
android:minLevel="0"/>
<item
android:drawable="@drawable/stateitems_wifi_1"
android:maxLevel="1"
android:minLevel="1"/>
<item
android:drawable="@drawable/stateitems_wifi_2"
android:maxLevel="2"
android:minLevel="2"/>
<item
android:drawable="@drawable/stateitems_wifi_3"
android:maxLevel="3"
android:minLevel="3"/>
<item
android:drawable="@drawable/stateitems_wifi_4"
android:maxLevel="4"
android:minLevel="4"/>
</level-list>
但好像有个问题,在返回信号3时,显示的是4,满格信号,2的时候,显示的3格信号不知道问题出在哪,我确定图片没有弄错. 广播接收器:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.NetworkInfo;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.widget.ImageView;
public class WifiStateReceiver extends BroadcastReceiver {
ImageView wifiStateImage;
Context context;
public WifiStateReceiver(Context context, ImageView imageView) {
// TODO Auto-generated constructor stub
this.wifiStateImage=imageView;
this.context=context;
int strength=getStrength(context);
wifiStateImage.setImageLevel(strength);
}
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
System.out.println(intent.getAction());
if(intent.getAction().equals(WifiManager.RSSI_CHANGED_ACTION))
{
int strength=getStrength(context);
System.out.println("当前信号 "+strength);
wifiStateImage.setImageLevel(strength);
}else if(intent.getAction().equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)){
System.out.println("网络状态改变");
NetworkInfo info=intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
if(info.getState().equals(NetworkInfo.State.DISCONNECTED))
{//如果断开连接
wifiStateImage.setImageLevel(0);
}
}else if(intent.getAction().equals(WifiManager.WIFI_STATE_CHANGED_ACTION))
{
//WIFI开关
int wifistate=intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,WifiManager.WIFI_STATE_DISABLED);
if(wifistate==WifiManager.WIFI_STATE_DISABLED)
{//如果关闭
wifiStateImage.setImageLevel(0);
}
}
}
public int getStrength(Context context)
{
WifiManager wifiManager = (WifiManager) context
.getSystemService(Context.WIFI_SERVICE);
WifiInfo info = wifiManager.getConnectionInfo();
if (info.getBSSID() != null) {
int strength = WifiManager.calculateSignalLevel(info.getRssi(), 5);
// 链接速度
// int speed = info.getLinkSpeed();
// // 链接速度单位
// String units = WifiInfo.LINK_SPEED_UNITS;
// // Wifi源名称
// String ssid = info.getSSID();
return strength;
}
return 0;
}
}
注册广播接收器:
//WIFI状态接收器
WifiStateReceiver wifiReceiver=new WifiStateReceiver(this,wifi_state);
IntentFilter filter=new IntentFilter();
filter.addAction(WifiManager.RSSI_CHANGED_ACTION);
filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
this.registerReceiver(wifiReceiver,filter);
要加上三个Action
系统默认的AlertDialog,与项目的UI不统一,所以,改了一下,定义了一样式,最终效果如下图:
另外,为了尽量少改原来的代码,该类类名及相关方法名都与android.app.AlertDialog相同,使用时,原代码只需要修改导入的包名,在按钮的Listener上加上一句关闭对话框的方法即可. 先是对话框的XML布局文件: test.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" >
<!-- 顶部椭园边缘 -->
<ImageView
android:layout_width="400dp"
android:layout_height="22dp"
android:src="@drawable/dialog_top" >
</ImageView>
<!-- 中间白色背景,两个TextView,标题和内容,留一个LinearLayout,在代码中根据调用动态加上按钮 -->
<LinearLayout
android:layout_width="400dp"
android:layout_height="wrap_content"
android:background="@drawable/dialog_center"
android:orientation="vertical" >
<TextView android:textColor="#000000"
android:textSize="35dp"
android:gravity="center"
android:id="@+id/title"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<TextView android:layout_marginLeft="20dp"
android:layout_marginRight="10dp"
android:id="@+id/message"
android:layout_marginBottom="10dp"
android:layout_marginTop="20dp"
android:textColor="#000000"
android:textSize="25dp"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<!-- 在LinearLayout中加按钮 -->
<LinearLayout
android:id="@+id/buttonLayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center"
android:gravity="center"
android:orientation="horizontal" >
</LinearLayout>
</LinearLayout>
<!-- 底部椭园边缘 -->
<ImageView
android:layout_marginTop="-2dp"
android:layout_width="400dp"
android:layout_height="22dp"
android:src="@drawable/dialog_bottom" >
</ImageView>
</LinearLayout>
按钮背景,不同状态不同,可参考本博相关文章: alertdialog_button.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:state_pressed="true" android:drawable="@drawable/dialog_button_pressed" />
<item android:state_focused="true" android:drawable="@drawable/dialog_button_pressed" />
<item android:drawable="@drawable/dialog_button" />
</selector>
下面就是自定义的AlertDialog类的代码:
public class AlertDialog {
Context context;
android.app.AlertDialog ad;
TextView titleView;
TextView messageView;
LinearLayout buttonLayout;
public AlertDialog(Context context) {
// TODO Auto-generated constructor stub
this.context=context;
ad=new android.app.AlertDialog.Builder(context).create();
ad.show();
//关键在下面的两行,使用window.setContentView,替换整个对话框窗口的布局
Window window = ad.getWindow();
window.setContentView(R.layout.alertdialog);
titleView=(TextView)window.findViewById(R.id.title);
messageView=(TextView)window.findViewById(R.id.message);
buttonLayout=(LinearLayout)window.findViewById(R.id.buttonLayout);
}
public void setTitle(int resId)
{
titleView.setText(resId);
}
public void setTitle(String title) {
titleView.setText(title);
}
public void setMessage(int resId) {
messageView.setText(resId);
}
public void setMessage(String message)
{
messageView.setText(message);
}
/**
* 设置按钮
* @param text
* @param listener
*/
public void setPositiveButton(String text,final View.OnClickListener listener)
{
Button button=new Button(context);
LinearLayout.LayoutParams params=new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
button.setLayoutParams(params);
button.setBackgroundResource(R.drawable.alertdialog_button);
button.setText(text);
button.setTextColor(Color.WHITE);
button.setTextSize(20);
button.setOnClickListener(listener);
buttonLayout.addView(button);
}
/**
* 设置按钮
* @param text
* @param listener
*/
public void setNegativeButton(String text,final View.OnClickListener listener)
{
Button button=new Button(context);
LinearLayout.LayoutParams params=new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
button.setLayoutParams(params);
button.setBackgroundResource(R.drawable.alertdialog_button);
button.setText(text);
button.setTextColor(Color.WHITE);
button.setTextSize(20);
button.setOnClickListener(listener);
if(buttonLayout.getChildCount()>0)
{
params.setMargins(20, 0, 0, 0);
button.setLayoutParams(params);
buttonLayout.addView(button, 1);
}else{
button.setLayoutParams(params);
buttonLayout.addView(button);
}
}
/**
* 关闭对话框
*/
public void dismiss() {
ad.dismiss();
}
}
使用方法:
final AlertDialog ad=new AlertDialog(Test.this);
ad.setTitle("标题");
ad.setMessage("内容sdfsafdasf内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容");
ad.setPositiveButton("确定", new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
ad.dismiss();
Toast.makeText(Test.this, "被点到确定", Toast.LENGTH_LONG).show();
}
});
ad.setNegativeButton("取消", new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
ad.dismiss();
Toast.makeText(Test.this, "被点到取消", Toast.LENGTH_LONG).show();
}
});
网上抄的代码不太完美,总有些小问题,之前是无法更新GridView,现在又发现如果点中可点击的控件(按钮,图片等),再拖动,无法实现划屏效果.这两个问题折腾了我大半天,研究了会事件传递机制后,解决. 之所以出现上面的问题,是因为在onInterceptTouchEvent方法中,自动传递事件给相应的控件,我们重写该方法,自己判断该不该划屏即可.默认情况下,在非可点击控件上划,只会触发onTouchEvent,不会触发onInterceptTouchEvent,所以onTouchEvent里也需要判断划屏的方法.
// 按下时x座标
private float startX = 0;
// 最终x座标
private float endx = 0;
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
// TODO Auto-generated method stub
int what = ev.getAction();
System.out.println("what" + what);
switch (what) {
case MotionEvent.ACTION_DOWN:
startX = ev.getX();
break;
}
endx = ev.getX();
if (endx - startX > 150)// 距离超过150
{
// 返回true,会传给onTouchEvent方法
snapToScreen(mCurScreen - 1);
startX = endx;
} else if (endx - startX < -150) {
snapToScreen(mCurScreen + 1);
startX = endx;
}
// 默认传递,其实就是传给相应的控件
return super.onInterceptTouchEvent(ev);
}
Android中提供了ViewGroup、View、Activity三个等级的Touch事件处理。也就是说,这三个地方都有事件回调方法。至于三者之间的执行顺序,将在下面详细阐述: 整体上看,事件传递顺序为ViewGroup::onInterceptTouchEvent() –> ViewGroup或View的onTouchEvent() –> Activity::onTouchEvent() 由于上面每个事件回调方法的返回值不同,导致事件本身及顺序发生微妙变化。下面以返回值为主线来详细阐述: 需要注意以下两点: 1、onInterceptTouchEvent()返回true,那么这个方法只会拦截动作ACTION_DOWN。 2、onInterceptTouchEvent()负责事件分发(事件传递方向),onTouchEvent()负责事件处理(消费)。 转自:http://orgcent.com/android-touch-event-mechanism/
在网上找了一份模仿系统Launcher的代码,是一个继承看碟ViewGroup的自定义组件,可以左右划屏,效果与QQ,微信之类的软件第一次启动时欢迎帮助效果类似.但是发现一问题,我在上面加了GridView,数据只有在程序启动时才能载入,启动后无法动态更新了,费了几个小时,终于找到解决方法:
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// TODO Auto-generated method stub
// if (changed) {
int childLeft = 0;
final int childCount = getChildCount();
for (int i=0; i
把if(change)注释掉即可.