首页 文章 精选 留言 我的

精选列表

搜索[网站开发],共10000篇文章
优秀的个人博客,低调大师

在IOS开发中根据(id)sender获取UIButton的信息

-(IBAction) buttonClick:(id)sender//sender参数,表示接受哪个按钮消息 { UIButton *button = (UIButton *)sender;//参数id是一个通用内型,此处将其强制转换成UIButton内型 //每个button都有唯一的tag,系统默认陪标示用的,是一个整数 NSString *title =[NSString stringWithFormat:@"Button tag %d",button.tag];//将button tag 转换成字符串输出 NSString *mesage = [button currentTitle];//取得button名称 } 网上搜的,记录一下 本文转自 驿落黄昏 51CTO博客,原文链接:http://blog.51cto.com/yiluohuanghun/1153314,如需转载请自行联系原作者

优秀的个人博客,低调大师

Android UI开发第八篇——ViewFlipper 左右滑动效果

怎么实现Android主页面的左右拖动效果。其实实现起来很简单,就是使用ViewFlipper来将您要来回拖动的View装在一起,然后与GestureDetector手势识别类来联动,确定要显示哪个View,加上一点点动画效果即可。 java code: public class TestFlip extends Activity implements OnGestureListener { private ViewFlipper flipper; private GestureDetector detector; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); detector = new GestureDetector(this); flipper = (ViewFlipper) this.findViewById(R.id.ViewFlipper01); flipper.addView(addView(R.layout.layout1)); flipper.addView(addView(R.layout.layout2)); flipper.addView(addView(R.layout.layout3)); flipper.addView(addView(R.layout.layout4)); } private View addView(int layout) { LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); View view = inflater.inflate(layout, null); return view; } @Override public boolean onTouchEvent(MotionEvent event) { return this.detector.onTouchEvent(event); } @Override public boolean onDown(MotionEvent e) { // TODO Auto-generated method stub return false; } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { if (e1.getX() - e2.getX() > 120) { this.flipper.setInAnimation(AnimationUtils.loadAnimation(this, R.anim.push_left_in)); this.flipper.setOutAnimation(AnimationUtils.loadAnimation(this, R.anim.push_left_out)); this.flipper.showNext(); return true; } else if (e1.getX() - e2.getX() < -120) { this.flipper.setInAnimation(AnimationUtils.loadAnimation(this, R.anim.push_right_in)); this.flipper.setOutAnimation(AnimationUtils.loadAnimation(this, R.anim.push_right_out)); this.flipper.showPrevious(); return true; } return false; } @Override public void onLongPress(MotionEvent e) { // TODO Auto-generated method stub } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { // TODO Auto-generated method stub return false; } @Override public void onShowPress(MotionEvent e) { // TODO Auto-generated method stub } @Override public boolean onSingleTapUp(MotionEvent e) { // TODO Auto-generated method stub return false; } } xml code: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <ViewFlipper android:id="@+id/ViewFlipper01" android:layout_width="fill_parent" android:layout_height="fill_parent"> </ViewFlipper> </LinearLayout> http://www.devdiv.com/home.php?mod=space&uid=14682&do=blog&id=3869 本文转自xyz_lmn51CTO博客,原文链接:http://blog.51cto.com/xyzlmn/817361 ,如需转载请自行联系原作者

优秀的个人博客,低调大师

android开发教程之使用线程实现视图平滑滚动示例

最近一直想做下拉刷新的效果,琢磨了好久,才走到通过onTouch方法把整个视图往下拉的步骤,接下来就是能拉下来,松开手要能滑回去啊。网上看了好久,没有找到详细的下拉刷新的例子,只有自己慢慢琢磨了。昨天和今天,研究了两天,下拉之后回滚回去的效果终于今天做出来了!开心。现在来分享下我的实现方法和一些心得体会吧。 我看了网上一个大神的例子,发现是在onTouch里面使用View的scrollTo(int, int)方法,来使整个视图往下滚动的,我尝试了使用setTranslationY()来对视图进行回滚,第一次是没问题的,但多滚动几次之后,整个视图实际上已经到了非常“高”的地方了,要拉很长的距离才能看到内容。所以回滚也必须使用scrollTo(int, int)方法来操作。 但scrollTo(int, int)执行是瞬间的,方法名讲是滚动到,实际上就是“瞬移到”某个位置,因此需要一步一步的去瞬移它,让它看上去是滚过去的…… 因为等下要去跑步了,还有就是也没有什么很多的要点需要讲解,我就直接上代码给大家看,注释都写好了,要点会单独提一下,更详细的讲解与心得就等着我哪天把下拉刷新实现了吧。 复制代码代码如下: /** * @desc 平滑滚动 * @param v 需要操控的视图 * @param fromY 起始Y坐标 * @param toY 终止Y坐标 * @param fps 帧率 * @param durtion 动画完成时间(毫秒) * */ private void smoothScroll(View v, int fromY, int toY, int fps, long durtion) { smoothScrollThread = new SmoothScrollThread(v, fromY, toY, durtion, fps); smoothScrollThread.run(); } /** * @desc 平滑滚动线程,用于递归调用自己来实现某个视图的平滑滚动 * */ class SmoothScrollThread implements Runnable { //需要操控的视图 private View v = null; //原Y坐标 private int fromY = 0; //目标Y坐标 private int toY = 0; //动画执行时间(毫秒) private long durtion = 0; //帧率 private int fps = 60; //间隔时间(毫秒),间隔时间 = 1000 / 帧率 private int interval = 0; //启动时间,-1 表示尚未启动 private long startTime = -1; /减速插值器 private DecelerateInterpolator decelerateInterpolator = null; /** * @desc 构造方法,做好第一次配置 * */ public SmoothScrollThread(View v, int fromY, int toY, long durtion, int fps) { this.v = v; this.fromY = fromY; this.toY = toY; this.durtion = durtion; this.fps = fps; this.interval = 1000 / this.fps; decelerateInterpolator = new DecelerateInterpolator(); } @Override public void run() { //先判断是否是第一次启动,是第一次启动就记录下启动的时间戳,该值仅此一次赋值 if (startTime == -1) { startTime = System.currentTimeMillis(); } //得到当前这个瞬间的时间戳 long currentTime = System.currentTimeMillis(); //放大倍数,为了扩大除法计算的浮点精度 int enlargement = 1000; //算出当前这个瞬间运行到整个动画时间的百分之多少 float rate = (currentTime - startTime) * enlargement / durtion; //这个比率不可能在 0 - 1 之间,放大了之后即是 0 - 1000 之间 rate = Math.min(rate, 1000); //将动画的进度通过插值器得出响应的比率,乘以起始与目标坐标得出当前这个瞬间,视图应该滚动的距离。 int changeDistance = (int) ((fromY - toY) * decelerateInterpolator.getInterpolation(rate / enlargement)); int currentY = fromY - changeDistance; v.scrollTo(0, currentY); if (currentY != toY) { postDelayed(this, this.interval); } else { return; } } public void stop() { removeCallbacks(this); } } 一些要点: 1.使用线程的目的是可以递归的调用自己,在每个run()方法里只滚动一点点,这个一点点根据帧率和插值器来决定。 2.插值器实际上就是一个函数(数学里的函数),输入0-1之间的浮点数,输出0-1之间的浮点数,输出的曲线是什么样的,就看是什么插值器了,decelerate就是减速插值器了,在平面直角坐标系里面,x值均匀变化,y轴的变化越来越慢。 3.放大倍数(就是那里乘以1000)是为了提高精度,因为通过实践发现用已经过的毫秒数除以整个动画周期得出的结果是0.0 -> 0.0 -> 0.0 -> 0.0 -> 1.0 -> 1.0 -> 1.0 -> 1.0 -> 1.0 -> 2.0 -> 2.0 -> 2.0,虽然是浮点数,但精度却莫名的保持在个位数上,乘以1000后,便会出现0-1000的均匀变化,这个时候去除以1000,便可得到0.000 - 1.000之间的均匀变化的数。 4.还有个很奇葩的是MotionEvent.getY()的值和scrollTo(int,int)的值貌似不是在同一个坐标系里面的。这个还有待进一步的分析和研究啊。 本文转自 一点点征服 博客园博客,原文链接:http://www.cnblogs.com/ldq2016/p/6802339.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

【移动开发】Android中图片的多点触控和缩放

前几天做项目用到相机拍照,之后能对图片进行缩放,拖拽,在此我将其单独抽取出来,后面用到时直接拿来用就行了! 效果图: 注:这里不仅能按钮缩放,还能多点触摸缩放和拖拽功能! 1.布局: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 <? xml version = "1.0" encoding = "UTF-8" ?> < FrameLayout xmlns:android = "http://schemas.android.com/apk/res/android" android:id = "@+id/flayout_img_display" android:layout_width = "fill_parent" android:layout_height = "fill_parent" android:orientation = "vertical" > < LinearLayout android:id = "@+id/linearLayout_img_display" android:layout_width = "fill_parent" android:layout_height = "fill_parent" android:layout_gravity = "center" android:gravity = "center" > < ImageView android:id = "@+id/img_display" android:layout_width = "fill_parent" android:layout_height = "wrap_content" android:paddingBottom = "5.0dip" android:paddingTop = "5.0dip" android:scaleType = "matrix" /> </ LinearLayout > < RelativeLayout android:id = "@+id/relativeLayout1" android:layout_width = "fill_parent" android:layout_height = "wrap_content" > < Button android:id = "@+id/btn_min" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:layout_alignParentBottom = "true" android:layout_alignParentLeft = "true" android:enabled = "false" android:text = "缩小" /> < Button android:id = "@+id/btn_out" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:layout_alignParentBottom = "true" android:layout_alignParentRight = "true" android:text = "放大" /> </ RelativeLayout > </ FrameLayout > 2.就一个类: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 import android.app.Activity; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Matrix; import android.graphics.PointF; import android.os.Bundle; import android.util.FloatMath; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnTouchListener; import android.widget.Button; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; /** * 缩放图片界面 * @author ZHF * */ public class MainActivity extends Activity { public static final String TAG = "ImgDisplayActivity" ; //控件声明 private Button btnZoomin, btnZoomout; private ImageView imgDisPlay; private LinearLayout lLayoutDisplay; private FrameLayout fLayoutDisplay; private Bitmap bitmap; private int imgId = 0 ; private double scale_in = 0.8 ; //缩小比例 private double scale_out = 1.25 ; //放大比例 private float scaleWidth = 1 ; private float scaleHeight = 1 ; //模式:0:什么都不干;1:拖拽; 2:缩放 public static final int NONE = 0 ; public static final int DRAG = 1 ; public static final int ZOOM = 2 ; //声明触发的事件模式 private int mode = NONE; private Matrix matrix; //矩阵 private Matrix currMatrix; //当前矩阵 private PointF starPoint; private PointF midPoint; private float startDistance; @Override protected void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); //初始化 fLayoutDisplay = (FrameLayout) findViewById(R.id.flayout_img_display); lLayoutDisplay = (LinearLayout) findViewById(R.id.linearLayout_img_display); imgDisPlay = (ImageView) findViewById(R.id.img_display); btnZoomin = (Button) findViewById(R.id.btn_min); btnZoomout = (Button) findViewById(R.id.btn_out); matrix = new Matrix(); //保存拖拽变化 currMatrix = new Matrix(); // 当前的 starPoint = new PointF(); //开始点的位置 btnZoomin.setOnClickListener( new OnClickListener() { @Override public void onClick(View v) { zoomIn(); } }); btnZoomout.setOnClickListener( new OnClickListener() { @Override public void onClick(View v) { zoomOut(); //放大 } }); imgDisPlay.setImageResource(R.drawable.img); //给图片绑定监听器哦 imgDisPlay.setOnTouchListener( new ImageViewOnTouchListener()); } /**放大操作**/ private void zoomOut() { reSizeBmp(scale_out); btnZoomin.setEnabled( true ); } /**缩小操作**/ private void zoomIn() { reSizeBmp(scale_in); } /**接收传入的缩放比例实现缩放**/ private void reSizeBmp( double scale) { //缩放比例 scaleWidth = ( float ) (scaleWidth * scale); scaleHeight = ( float ) (scaleHeight * scale); Matrix matrix = new Matrix(); matrix.postScale(scaleWidth, scaleHeight); //设计缩放比例 imgDisPlay.setImageMatrix(matrix); } /**计算触摸实现缩放**/ final class ImageViewOnTouchListener implements OnTouchListener{ @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: //一只手指按下 Log.i(TAG, "一只手指按下" ); currMatrix.set(matrix); starPoint.set(event.getX(), event.getY()); mode = DRAG; break ; case MotionEvent.ACTION_POINTER_DOWN: //如果有一只手指按下屏幕,后续又有一个手指按下 // 两只手指按下 Log.i(TAG, "又有一只手指按下" ); startDistance = distance(event); //记下两点的距离 Log.i(TAG, startDistance+ "" ); if (startDistance > 5f) { //两个手指之间的最小距离像素大于5,认为是多点触摸 mode = ZOOM; currMatrix.set(matrix); midPoint = getMidPoint(event); //记下两个点之间的中心点 } break ; case MotionEvent.ACTION_MOVE: if (mode == DRAG) { //拖拽模式 Log.i(TAG, "一只手指在拖拽" ); //开始--》结束点的距离 float dx = event.getX() - starPoint.x; float dy = event.getY() - starPoint.y; matrix.set(currMatrix); matrix.postTranslate(dx, dy); //移动到指定点:矩阵移动比例;eg:缩放有缩放比例 } else if (mode == ZOOM) { //缩放模式 Log.i(TAG, "正在缩放" ); float distance = distance(event); //两点之间的距离 if (distance > 5f) { matrix.set(currMatrix); float cale = distance / startDistance; matrix.preScale(cale, cale, midPoint.x, midPoint.y); //进行比例缩放 } } break ; case MotionEvent.ACTION_UP: //最后一只手指离开屏幕后触发此事件 case MotionEvent.ACTION_POINTER_UP: //一只手指离开屏幕,但还有一只手指在上面会触此事件 //什么都没做 mode = NONE; break ; default : break ; } imgDisPlay.setImageMatrix(matrix); //两只手指的缩放 return true ; } } /**计算两点之间的距离像素**/ private float distance(MotionEvent e) { float eX = e.getX( 1 ) - e.getX( 0 ); //后面的点坐标 - 前面点的坐标 float eY = e.getY( 1 ) - e.getY( 0 ); return FloatMath.sqrt(eX * eX + eY * eY); } /**计算两点之间的中心点**/ private PointF getMidPoint(MotionEvent event) { float x = (event.getX( 1 ) - event.getX( 0 )) / 2 ; float y = (event.getY( 1 ) - event.getY( 0 )) / 2 ; return new PointF(x,y); } } ok!主要的算法就在ImageViewOnTouchListener监听器当中,要考虑那三种情况(缩放、拖拽、什么都不干),另外需要注意的就是,单个手指和两个以上手指的情况。 源码下载:http://down.51cto.com/data/876165 本文转自zhf651555765 51CTO博客,原文链接:http://blog.51cto.com/smallwoniu/1252191,如需转载请自行联系原作者

优秀的个人博客,低调大师

【Android开发—智能家居系列】(四):UDP通信发送指令

思路回顾 【1】手机连接WIFI模块 【2】UDP通信对WIFI模块发送指令,以和WIFI模块保持连接状态 【3】UDP通信对WIFI模块发送指令,让其搜索可用的无线网,返回WIFI列表 【4】发送指令,让WIFI模块接入指定路由 【5】手机连接路由 【6】发送指令,获得WIFI模块的动态IP地址 UDP通信线程类 package com.jczb.smartlife.common; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketException; import java.net.UnknownHostException; import android.os.Handler; import android.os.Message; import com.jczb.smartlife.common.Tool; public class GetInfoThread extends Thread { private Handler handler; private DatagramSocket socket; private int msgType; private final String IP = "255.255.255.255";//广播地址 private int PORT = 26000; /** * 48899端口:C32x系列的端口,用户可以用AT指令更改 * 49000端口:除C32x系列,其他WIFI模块的端口 * 1902端口:有人掌控宝系列产品的端口 */ private int targetPort = 49000 ; private boolean receive = true; /** * * @param handler 传入监听此线程的Handler * @param intMsg 传入监听的消息类型 */ public GetInfoThread(Handler handler,int msgType) { this.handler = handler; this.msgType=msgType; init(); } public void init(){ try { socket = new DatagramSocket(null); socket.setBroadcast(true); socket.setReuseAddress(true); socket.bind(new InetSocketAddress(PORT)); } catch (SocketException e) { e.printStackTrace(); sendErrorMsg("Search Thread init fail"); return; } } public void run() { if (socket == null) { return; } try { byte[] data = new byte[1024]; //创建一个空的DatagramPacket对象 DatagramPacket revPacket = new DatagramPacket(data, data.length); while (receive) { //服务端接收数据 socket.receive(revPacket); if(null!=handler){ byte[] realData = new byte[revPacket.getLength()]; System.arraycopy(data, 0, realData,0, realData.length); Message msg =handler.obtainMessage(msgType,realData); handler.sendMessage(msg); } } } catch (Exception e) { e.printStackTrace(); socket.close(); } } public void close() { if (socket == null) return; socket.close(); } private void sendErrorMsg(String info){ } /** * 发送数据 * @param msg */ public void sendMsg(byte[] msg) { if (socket != null) { try { System.out.println("targetPort------------------->"+targetPort); DatagramPacket sendPacket = new DatagramPacket(msg, msg.length, InetAddress.getByName(IP), targetPort); socket.send(sendPacket); } catch (UnknownHostException e) { e.printStackTrace(); System.out.println("发送失败"); } catch (IOException e) { e.printStackTrace(); System.out.println("发送失败"); } } } public void setReceive(boolean receive) { this.receive = receive; } public void setTargetPort(int targetPort) { this.targetPort = targetPort; } public void setMsgType(int msgType){ this.msgType=msgType; } } 发送消息的线程类 /** * 发送消息的队列,每次发送数据时,只需要调用putMsg(byte[] data)方法 * * @author usr_liujinqi * */ private class SendMsgThread extends Thread { // 发送消息的队列 private Queue<byte[]> sendMsgQuene = new LinkedList<byte[]>(); // 是否发送消息 private boolean send = true; private GetInfoThread ss; public SendMsgThread(GetInfoThread ss) { this.ss = ss; } public synchronized void putMsg(byte[] msg) { // 唤醒线程 if (sendMsgQuene.size() == 0) notify(); sendMsgQuene.offer(msg); } public void run() { synchronized (this) { while (send) { // 当队列里的消息发送完毕后,线程等待 while (sendMsgQuene.size() > 0) { byte[] msg = sendMsgQuene.poll(); if (ss != null) ss.sendMsg(msg); } try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } public void setSend(boolean send) { this.send = send; } } 应用 【举例】发送搜索WIFI模块的指令 //1.用户获得温控器中WIFI模块的WIFI模块的IP地址,MAC地址,模块名称的指令 private final byte[] getInfoCode=new byte[]{(byte)0x48,0x46,0x2D,0x41,0x31,0x31,0x41,0x53,0x53,0x49,0x53,0x54,0x48,0x52,0x45,0x41,0x44}; public static final int REC_Module=0x04;//搜索WIFI模块的信息(包括IP、Mac、名称) //实例化一个线程,用户获得模块信息(IP,Mac,名称) //参数为监听为此线程的Handler,以及接收成功后,给Handler发送的消息类型 getInfoThread = new GetInfoThread(handler,Tool.REC_Module); getInfoThread.start(); //发送消息的线程 smt = new SendMsgThread(getInfoThread); smt.start(); //设置发送的目的端口号 getInfoThread.setTargetPort(Integer.parseInt("48899")); smt.putMsg(getInfoCode); WIFI模块在接收到指令后,就会回复信息,以下的Handler就是针对回复过来的信息进行解析处理等操作。 //处理消息的Handler private Handler handler= new Handler() { public void handleMessage(Message msg) { switch (msg.what) { case Tool.REC_Module:// 解析接收到的数据 //设置发送的目的端口号 getInfoThread.setTargetPort(Integer.parseInt("48899")); getInfoThread.setMsgType(Tool.REC_OK); smt.putMsg(okCode); SetServer(); SetDHCP(); byte[] data = (byte[]) msg.obj; //将十进制的数据转化成十六进制数据 String strTemp= Tool.bytesToHexString(data); //将十六进制的字符串去掉空格之后进行解析 String strdecode=Tool.DecodeHex(strTemp.replace(" ", "")); //取出IP,Mac地址,模块名称 decodeIP(strdecode); Toast.makeText(ConnectWifiActivity.this, "获得WIFI模块名称成功!"+ModuleName, Toast.LENGTH_SHORT).show(); break; case Tool.REC_Server: byte[] dataServer = (byte[])msg.obj; //将十进制的数据转化成十六进制数据 String strServer= Tool.bytesToHexString(dataServer); if("2b 6f 6b 0d 0a 0d 0a ".equals(strServer)){ Toast.makeText(ConnectWifiActivity.this, "设置服务器成功!", Toast.LENGTH_SHORT).show(); } break; case Tool.REC_SSID: byte[] dataSSID=(byte[])msg.obj; Tool.bytesToHexString(dataSSID); decodeData(dataSSID); break; case Tool.REC_AT: byte[] dataID = (byte[]) msg.obj; //将十进制的数据转化成十六进制数据 String strTempID= Tool.bytesToHexString(dataID); //将十六进制的字符串去掉空格之后进行解析 String strdecodeID=Tool.DecodeHex(strTempID.replace(" ", "")); break; case Tool.REC_DHCP: byte[] dataDHCP = (byte[])msg.obj; //将十进制的数据转化成十六进制数据 String strDHCP= Tool.bytesToHexString(dataDHCP); if("2b 6f 6b 0d 0a 0d 0a ".equals(strDHCP)){ Toast.makeText(ConnectWifiActivity.this, "设置DHCP网络参数成功!", Toast.LENGTH_SHORT).show(); } break; default: byte[] data1 = (byte[]) msg.obj; //将十进制的数据转化成十六进制数据 String strTemp1= Tool.bytesToHexString(data1); Toast.makeText(ConnectWifiActivity.this, strTemp1, Toast.LENGTH_SHORT).show(); break; } } }; 总结 凡是需要对WIFI模块发送指令的,就需要用到上述的两个线程类,还有一个对返回信息进行处理的Handler。只是发送的指令的code不一样,如上述表示的是搜索WIFI模块的十六进制的指令。不管WIFI模块在AP模式下还是STA模式,通信的最开始步骤都是先搜索模块,然后获得它的IP和Mac之后,立即回复+ok指令,就可以保持连接状态。 本文转自 一点点征服 博客园博客,原文链接: http://www.cnblogs.com/ldq2016/p/6774195.html ,如需转载请自行联系原作者

优秀的个人博客,低调大师

Android开发学习笔记:Intent的简介以及属性的详解

一.Intent的介绍 Intent的中文意思是“意图,意向”,在Android中提供了Intent机制来协助应用间的交互与通讯,Intent负责对应用中一次操作的动作、动作涉及数据、附加数据进行描述,Android则根据此Intent的描述,负责找到对应的组件,将 Intent传递给调用的组件,并完成组件的调用。Intent不仅可用于应用程序之间,也可用于应用程序内部的Activity/Service之间的交互。因此,可以将Intent理解为不同组件之间通信的“媒介”专门提供组件互相调用的相关信息。 二.Inten启动组件的方法 Intent可以启动一个Activity,也可以启动一个Service,还可以发起一个广播Broadcasts。具体方法如下: 组件名称 方法名称 Activity startActvity( ) startActivity( ) Service startService( ) bindService( ) Broadcasts sendBroadcasts( ) sendOrderedBroadcasts( ) sendStickyBroadcasts( ) 三.Intent的属性 Intent有以下几个属性: 动作(Action),数据(Data),分类(Category),类型(Type),组件(Compent)以及扩展信(Extra)。其中最常用的是Action属性和Data属性。 1.Intent的Action属性 Action是指Intent要完成的动作,是一个字符串常量。SDK中定义了一些标准的Action常量如下表所示。 Constant Target component Action ACTION_CALL activity Initiate a phone call. ACTION_EDIT activity Display data for the user to edit. ACTION_MAIN activity Start up as the initial activity of a task, with no data input and no returned output. ACTION_SYNC activity Synchronize data on a server with data on the mobile device. ACTION_BATTERY_LOW broadcast receiver A warning that the battery is low. ACTION_HEADSET_PLUG broadcast receiver A headset has been plugged into the device, or unplugged from it. ACTION_SCREEN_ON broadcast receiver The screen has been turned on. ACTION_TIMEZONE_CHANGED broadcast receiver The setting for the time zone has changed. 下面是一个测试Action常量的例子: main.xml <?xmlversion="1.0"encoding="utf-8"?> <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" /> <Button android:text="测试Action属性" android:id="@+id/getBtn" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> strings.xml <?xmlversion="1.0"encoding="utf-8"?> <resources> <stringname="hello">测试Action属性</string> <stringname="app_name">IntentActionDemo</string> </resources> MainActivity.java packagecom.android.action.activity; importandroid.app.Activity; importandroid.content.Intent; importandroid.os.Bundle; importandroid.view.View; importandroid.view.View.OnClickListener; importandroid.widget.Button; publicclassMainActivityextendsActivity{ privateButtongetBtn; @Override publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); getBtn=(Button)findViewById(R.id.getBtn); getBtn.setOnClickListener(newOnClickListener(){ @Override publicvoidonClick(Viewv){ Intentintent=newIntent(); intent.setAction(Intent.ACTION_GET_CONTENT);//设置IntentAction属性 intent.setType("vnd.android.cursor.item/phone");//设置IntentType属性 //主要是获取通讯录的内容 startActivity(intent);//启动Activity } }); } } 效果图: 2.Intent的Data属性 Intent的Data属性是执行动作的URI和MIME类型,不同的Action有不同的Data数据指定。比如:ACTION_EDIT Action应该和要编辑的文档URI Data匹配,ACTION_VIEW应用应该和要显示的URI匹配。 3.Intent的Category属性 Intent中的Category属性是一个执行动作Action的附加信息。比如:CATEGORY_HOME则表示放回到Home界面,ALTERNATIVE_CATEGORY表示当前的Intent是一系列的可选动作中的一个。下表是SDK文档中关于Category的信息。 Constant Meaning CATEGORY_BROWSABLE The target activity can be safely invoked by the browser to display data referenced by a link — for example, an image or an e-mail message. CATEGORY_GADGET The activity can be embedded inside of another activity that hosts gadgets. CATEGORY_HOME The activity displays the home screen, the first screen the user sees when the device is turned on or when the HOME key is pressed. CATEGORY_LAUNCHER The activity can be the initial activity of a task and is listed in the top-level application launcher. CATEGORY_PREFERENCE The target activity is a preference panel. 下面是一个回到Home界面的例子: main.xml <?xmlversion="1.0"encoding="utf-8"?> <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical"android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="测试IntentCategory" /> <Button android:id="@+id/Button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="转到Home界面" /> </LinearLayout> strings.xml <?xmlversion="1.0"encoding="utf-8"?> <resources> <stringname="hello">HelloWorld,MainActivity!</string> <stringname="app_name">IntentCategoryDemo</string> </resources> MainActivity.java packagecom.android.category.activity; importandroid.app.Activity; importandroid.content.Intent; importandroid.os.Bundle; importandroid.view.View; importandroid.view.View.OnClickListener; importandroid.widget.Button; publicclassMainActivityextendsActivity{ privateButtonbtn; @Override publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); btn=(Button)findViewById(R.id.Button1); btn.setOnClickListener(newOnClickListener(){ @Override publicvoidonClick(Viewv){ Intentintent=newIntent(); intent.setAction(Intent.ACTION_MAIN);//添加Action属性 intent.addCategory(Intent.CATEGORY_HOME);//添加Category属性 startActivity(intent);//启动Activity } }); } } 效果图: 4.Intent的Type属性 Intent的Type属性显式指定Intent的数据类型(MIME)。一般Intent的数据类型能够根据数据本身进行判定,但是通过设置这个属性,可以强制采用显式指定的类型而不再进行推导。 5.Intent的Compent属性 Intent的Compent属性指定Intent的的目标组件的类名称。通常 Android会根据Intent 中包含的其它属性的信息,比如action、data/type、category进行查找,最终找到一个与之匹配的目标组件。但是,如果 component这个属性有指定的话,将直接使用它指定的组件,而不再执行上述查找过程。指定了这个属性以后,Intent的其它所有属性都是可选的。 6.Intent的Extra属性 Intent的Extra属性是添加一些组件的附加信息。比如,如果我们要通过一个Activity来发送一个Email,就可以通过Extra属性来添加subject和body。 下面的例子在第一个Activity的EditText输入用户名,该年龄保存在Intent的Extras属性中。当单击Button时,会在第二个Activity中显示用户名。 first.xml <?xmlversion="1.0"encoding="utf-8"?> <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="请输入用户名" /> <EditText android:id="@+id/EditText1" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <Button android:id="@+id/Button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="测试Extras属性" /> </LinearLayout> second.xml <?xmlversion="1.0"encoding="utf-8"?> <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:id="@+id/TextView1" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> strings.xml <?xmlversion="1.0"encoding="utf-8"?> <resources> <stringname="hello">HelloWorld,FirstActivity!</string> <stringname="app_name">IntentExtrasDemo</string> </resources> FirstActivity.java packagecom.android.extras.activity; importandroid.app.Activity; importandroid.content.Intent; importandroid.os.Bundle; importandroid.view.View; importandroid.view.View.OnClickListener; importandroid.widget.Button; importandroid.widget.EditText; publicclassFirstActivityextendsActivity{ privateButtonbtn; privateEditTextetx; @Override publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.first); btn=(Button)findViewById(R.id.Button1); etx=(EditText)findViewById(R.id.EditText1); btn.setOnClickListener(newOnClickListener(){ @Override publicvoidonClick(Viewv){ Intentintent=newIntent(); //设置Intent的class属性,跳转到SecondActivity intent.setClass(FirstActivity.this,SecondActivity.class); //为intent添加额外的信息 intent.putExtra("useName",etx.getText().toString()); //启动Activity startActivity(intent); } }); } } SecondActivity.java packagecom.android.extras.activity; importandroid.app.Activity; importandroid.content.Intent; importandroid.os.Bundle; importandroid.widget.TextView; publicclassSecondActivityextendsActivity{ privateTextViewtv; @Override publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); //设置当前的Activity的界面布局 setContentView(R.layout.second); //获得Intent Intentintent=this.getIntent(); tv=(TextView)findViewById(R.id.TextView1); //从Intent获得额外信息,设置为TextView的文本 tv.setText(intent.getStringExtra("useName")); } } 注意:在添加第二个Activity SecondActivity的时候,要在AndroidManifest.xml里面添加上SecondActivity,具体如下,即是在15行</activity>的后面添加上16~18行的代码。如果不这样做,就会在模拟器上出现错误。 <?xmlversion="1.0"encoding="utf-8"?> <manifestxmlns:android="http://schemas.android.com/apk/res/android" package="com.android.extras.activity" android:versionCode="1" android:versionName="1.0"> <uses-sdkandroid:minSdkVersion="10"/> <applicationandroid:icon="@drawable/icon"android:label="@string/app_name"> <activityandroid:name=".FirstActivity" android:label="@string/app_name"> <intent-filter> <actionandroid:name="android.intent.action.MAIN"/> <categoryandroid:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> <activityandroid:name=".SecondActivity" android:label="@string/app_name"> </activity> </application> </manifest> 效果图: 本文转自 lingdududu 51CTO博客,原文链接: http://blog.51cto.com/liangruijun/634411

优秀的个人博客,低调大师

Android UI开发第七篇之Android Gallery

新建项目 ② 定义layout外部resource的xml文件,用来改变layout的背景 <?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="Gallery"> <attr name="android:galleryItemBackground" /> </declare-styleable> <!-- 定义layout 外部resource 的xml 文件,用来改变layout 的背景图。 --> </resources> 复制代码 ③ 修改main.xml布局,添加一个Gallery和一个ImageView <?xml version="1.0" encoding="utf-8"?> <AbsoluteLayout android:id="@+id/widget_absolutelayout" android:layout_width="fill_parent" android:layout_height="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android" > <Gallery android:layout_width="fill_parent" android:layout_height="143px" android:layout_x="0px" android:layout_y="51px" android:id="@+id/Gallery_preView"> </Gallery> <ImageView android:layout_width="239px" android:layout_height="218px" android:layout_x="38px" android:layout_y="184px" android:id="@+id/ImageView_photo"> </ImageView> </AbsoluteLayout> 复制代码 ④ 新建一个myImageAdapter类--Gallery的适配器,它继承于BaseAdapter类. package zyf.Ex_Ctrl_10ME; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; public class myImageAdapter extends BaseAdapter { @Override public int getCount() { // TODO Auto-generated method stub return 0; } @Override public Object getItem(int position) { // TODO Auto-generated method stub return null; } @Override public long getItemId(int position) { // TODO Auto-generated method stub return 0; } @Override public View getView(int position, View convertView, ViewGroup parent) { // TODO Auto-generated method stub return null; } } 复制代码 ⑤ 修改mainActivity.java,添加Gallery相关操作 package zyf.Ex_Ctrl_10ME; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.AdapterView; import android.widget.Gallery; import android.widget.ImageView; import android.widget.Toast; public class Ex_Ctrl_10ME extends Activity { /** Called when the activity is first created. */ /*定义要使用的对象*/ privateGallerygallery; private ImageView imageview; private myImageAdapter imageadapter; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); imageadapter=new myImageAdapter(this); /* 通过findViewById 取得 资源对象*/ gallery=(Gallery)findViewById(R.id.Gallery_preView); imageview=(ImageView)findViewById(R.id.ImageView_photo); /*给Gallery设置适配器 把Ex_Ctrl_10ME类传入参数*/ gallery.setAdapter(imageadapter); /*设置Gallery的点击事件监听器*/ gallery.setOnItemClickListener(newGallery.OnItemClickListener(){ @Override public void onItemClick(AdapterView<?> parent, View v, int position, long id) { // TODO Auto-generated method stub /*显示该图片是几号*/ Toast.makeText(Ex_Ctrl_10ME.this, "这是图片:"+position+"号", Toast.LENGTH_SHORT).show(); /*设置大图片*/ imageview.setBackgroundResource(imageadapter.myImageIds[position]); } }); } } 复制代码 ⑥ 修改myImageAdapter.java文件,实现相簿浏览效果 package zyf.Ex_Ctrl_10ME; import android.content.Context; import android.content.res.TypedArray; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.Gallery; import android.widget.ImageView; public class myImageAdapter extends BaseAdapter{//自定义的类变量 /*变量声明*/ int mGalleryItemBackground; private Context context;//上下文 /* 构建一Integer array 并取得预加载Drawable 的图片id */ public Integer[] myImageIds = { R.drawable.photo1, R.drawable.photo2, R.drawable.photo3, R.drawable.photo4, R.drawable.photo5, R.drawable.photo6, }; /*自定义的构造方法*/ public myImageAdapter(Context context) { // TODO Auto-generated constructor stub this.context=context; /* * 使用在res/values/attrs.xml 中的<declare-styleable>定义 的Gallery属性. */ TypedArray typed_array=context.obtainStyledAttributes(R.styleable.Gallery); /* 取得Gallery属性的Index id */ mGalleryItemBackground=typed_array.getResourceId(R.styleable.Gallery_android_galleryItemBackground, 0); /* 让对象的styleable 属性能够反复使用 */ typed_array.recycle(); } /* 重写的方法getCount,返回图片数目 */ @Override public int getCount() { // TODO Auto-generated method stub return myImageIds.length; } /* 重写的方法getItemId,返回图像的数组id */ @Override public Object getItem(int position) { // TODO Auto-generated method stub return position; } @Override public long getItemId(int position) { // TODO Auto-generated method stub return position; } /* 重写的方法getView,返回一View 对象 */ @Override public View getView(int position, View convertView, ViewGroup parent) { // TODO Auto-generated method stub /* 产生ImageView 对象 */ ImageView imageview = new ImageView(context); /* 设置图片给imageView 对象 */ imageview.setImageResource(myImageIds[position]); /* 重新设置图片的宽高 */ imageview.setScaleType(ImageView.ScaleType.FIT_XY); /* 重新设置Layout 的宽高 */ imageview.setLayoutParams(newGallery.LayoutParams(128, 128)); /* 设置Gallery背景图 */ imageview.setBackgroundResource(mGalleryItemBackground); /* 返回imageView 对象 */ return imageview; } } 复制代码 http://www.devdiv.com/home.php?mod=space&uid=14682&do=blog&id=3860 本文转自xyz_lmn51CTO博客,原文链接:http://blog.51cto.com/xyzlmn/817368,如需转载请自行联系原作者

优秀的个人博客,低调大师

【Android开发—智能家居系列】(三):手机连接WIFI模块

版权声明:本文为博主原创文章,未经博主允许不得转载。 目录(?)[+] 概述 实现连接WIFI的功能会用到一个工具类,源码可以点击链接下载。网上这些类似的工具类里的代码差不多是一样的。连接无线网主要有两个方法: 其中有一个Connect方法,还有一个connectSpecificAP方法,对于不需要密码就能链接的WIFI模块,我使用的是后者。 主要步骤 连接WIFI大致分为一下几个步骤: 【1】打开WIFI openWifi 【2】配置网络信息 createWifiInfo返回WIFiConfig 【3】添加配置好的网络并连接 int netID = mWifiManager.addNetwork(wifiConfig); boolean bRet = mWifiManager.enableNetwork(netID, false); 【4】判断连接是否成功 上面的enableNetWork方法返回成功并不能反映手机是否真的连接成功,所以还需要调用isConnect方法进行判断,针对自己的业务逻辑和场景,我又写了一个判断是否连接成功的方法:isWifiConnected的方法 应用 /** * 手机接入模块的WIFI网络——BLACKANTS */ private void ConnectDisplay(){ //获得消息对象 Message msg=mainHandler.obtainMessage(); //是否连接成功的一个标记 Boolean isConnected=false; //标志BLACKANTS的ScanResult是否存在,true存在,false不存在 Boolean isExist=false; //用户存放BLACKANTS的WIFI信息 ScanResult srWifiInfo=null; //声明一个用于临时存放SSID的变量 String strTempSSID; /******************以下一段代码主要是为了获得BLACKANTS的ScanResult(包括了它的SSID,BSSID,capabilities)*****************/ //扫描WIFI wifiAdmin.startScan(); //获得WIFI列表 List<ScanResult> lstWiFi= wifiAdmin.getWifiList(); //如果WIFI列表为空,则说明WIFI开关未打开,向Handler发送消息 if(lstWiFi==null || lstWiFi.size()==0){ msg.what=NotOpen; mainHandler.sendMessage(msg); return; } //如果列表存在,则对列表进行遍历 if(lstWiFi!=null & lstWiFi.size()>0){ //遍历列表,查看BLACKANTS是否存在 for(int i=0;i<lstWiFi.size();i++){ strTempSSID=lstWiFi.get(i).SSID; //如果存在,则退出For循环 if((DisplaySSID).equals(strTempSSID.trim()) ){ //修改标志位为存在 isExist=true; //将BLACKANTS的Wifi信息放入到变量srWifiInfo中 srWifiInfo=lstWiFi.get(i); break; } } } /******************以上一段代码主要是为了获得BLACKANTS的ScanResult(包括了它的SSID,BSSID,capabilities)*****************/ //默认是失败 msg.what=Failure; //如果存在,则让手机接入BLACKANTS-------------------V1.0 if(isExist){ if(wifiAdmin.connectSpecificAP(srWifiInfo)){ //判断是否连接上 if(wifiAdmin.isWifiConnected(InitActivity.this,DisplaySSID)){ msg.what=Success; } } } mainHandler.sendMessage(msg); } 附: 下载工具类(WIFIAdmin) 本文转自 一点点征服 博客园博客,原文链接: http://www.cnblogs.com/ldq2016/p/6774176.html ,如需转载请自行联系原作者

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册