View.post()和handler.post()小结

    首先,要感谢这篇文章 http://www.cnblogs.com/zenip/archive/2013/01/26/2877737.html还有要感谢csdn上某个放源码的家伙。

    我先说一下为什么我会注意到 View.post()和handler.post()这两个方法,因为某一天我想做一个得到状态栏和标题栏的Demo,然后在网上找了一个方法:

   方法一:状态栏和标题栏

 //1、得到状态栏高度

Rect rect = new Rect();
view.getWindowVisibleDisplayFrame(rect);
int statusBarHeight = rect.top; System.out.println("状态栏高度:" + statusBarHeight);

//2、得到标题栏高度

int wintop = getWindow().findViewById(android.R.id.content).getTop();

int titleBarHeight = wintop - statusBarHeight;

System.out.println("标题栏高度:" + titleBarHeight);


   这两个方法是在网上找到的,但是一用不行,得不到正确的值。这就蛋疼,百度上全是这答案,那就Google吧。

  

  这样儿就发现,方法二:状态栏

  public int getStatusBarHeight() {
		Class<?> c = null;
		Object obj = null;
		java.lang.reflect.Field field = null;
		int x = 0;
		int statusBarHeight = 0;
		try {
			c = Class.forName("com.android.internal.R$dimen");
			obj = c.newInstance();
			field = c.getField("status_bar_height");
			x = Integer.parseInt(field.get(obj).toString());
			statusBarHeight = getResources().getDimensionPixelSize(x);
			return statusBarHeight;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return statusBarHeight;
	}

  反射机制得到。这个是正确的。

  你们会问这个和View.post()和handler.post有毛线关系啊!

  这个就要讲,怎么让方法一起效。

  要得到正确的状态栏和标题栏的高度,那么就应该在onAttachedToWindow这个方法中,或者已经AttachedWindow之后的状态。

  View.post()方法和handler.post方法都是消息传递到UI线程。但是view.post这个post会出现成功但post不执行的问题。原因也是在view.post(),

  doc上的描述是:

  This method can be invoked from outside of the UI thread only when this View is attached to a window.

  view.post()中的线程要被成功的加入队列是需要在attached to a window 这发生之后。

 所以,逻辑就是View.post 要成功就是在 attached to a window.之后,要得到正确的状态栏和标题栏的高度也是在之后。

 那么,view.post中调用方法一,那就是得到正确的值了。事实也是如此。




可以成功的用方法一得到正确值方法有

1. 在oncreate中调用 view.post()方法,中间调用getRelatedAttributeValue;

2. 在onAttachedToWindow中调用handler.post ,中间调用getRelatedAttributeValue;


在onAttachedToWindow中直接调用getRelatedAttributeValue是得不到正确的值的








// Oncreate方法内:
//变量初始化没有贴

 txt_hello_ = (TextView) findViewById(R.id.id_txt_hello);

		Display display = getWindowManager().getDefaultDisplay();
		screenWidth_ = display.getWidth();
		screenHeight_ = display.getHeight();

		window_ = getWindow();
		/* 取得系统当前显示的 view根(它是一个framelayout对象) */
		view_boot_ = window_.findViewById(Window.ID_ANDROID_CONTENT);

              // 注意这里是 View。Post()方法
                txt_hello_.post(new Runnable() {
			public void run() {
				/* 获取相关参数 */
				

                   
				getRelatedAttributeValue();
			}
		});

              getRelatedAttributeValue 方法:
         /**
	 * 获取相关属性值
	 */
	private void getRelatedAttributeValue() {
		/* 定义一个区域 */
		Rect frame = new Rect();
		/* 区域范围为该textview的区域范围 */
				getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
		/* 获取状态栏高度。因为获取的区域不包含状态栏 */
		statusBarHeight_ = frame.top;
		/* 获取除了状态栏和标题内容的起始y坐标,也就是 状态栏+标题栏的高度 */
		int contentTop = view_boot_.getTop();
		/* 一减得出标题栏高度 */
		titleBarHeight_ = contentTop - statusBarHeight_;

		txt_hello_.setText("屏幕宽度=" + screenWidth_ + "\n屏幕高度=" + screenHeight_ + 
                  "\n状态栏高度=" + statusBarHeight_ + "\n标题栏高度=" + titleBarHeight_);
	}

  但是,值虽然正确了,又有新问题了:
ImageView img = null;

public void onCreate(...) {

 img = (ImageView)findViewById(R.id.image);

 new Thread() {
     public void run() {
         final Bitmap bmp = BitmapFactory.decodeFile("/sdcard/someImage.jpg");
         System.out.println("bitmap: "+bmp.toString()+" img: "+img.toString());
         if ( !img.post(new Runnable() {
             public void run() {
                 System.out.println("setting bitmap...");
                 img.setImageBitmap(bmp);
                 System.out.println("bitmap set.");
             }
         }) ) System.out.println("Runnable won't run!");
         System.out.println("runnable posted");
 }
}.start();


 I/System.out( 8066): bitmap: android.graphics.Bitmap@432f3ee8 img: android.widget.ImageView@4339d698
 I/System.out( 8066): runnable posted
 
 这段代码的结果是, post成功,但是没有执行。

那么同理,我在oncreate中使用view.post 为什么可以得到 正确的状态栏的高度呢?

 对了, 这是个人愚见,跪求大神指正。谢谢。






还忘了一件事,分享一个微信平台 vjiazhi 就是讲个人开发者赚钱的一个平台。有空去关注一下








  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
下面是一个使用 `window.webkit.messageHandlers.<handlerName>.postMessage(<message>)` 进行消息传递的简单例子: 在 H5 页面中,可以使用以下代码向 iOS App 发送消息: ```javascript window.webkit.messageHandlers.myHandler.postMessage("Hello from H5"); ``` 在 iOS App 中,需要进行相应的设置来接收并处理这个消息。以下是一个示例代码: ```swift import WebKit class ViewController: UIViewController, WKScriptMessageHandler { var webView: WKWebView! override func viewDidLoad() { super.viewDidLoad() let configuration = WKWebViewConfiguration() // 注册 messageHandler configuration.userContentController.add(self, name: "myHandler") webView = WKWebView(frame: view.bounds, configuration: configuration) view.addSubview(webView) // 加载 H5 页面 if let htmlPath = Bundle.main.path(forResource: "index", ofType: "html") { let htmlUrl = URL(fileURLWithPath: htmlPath) webView.loadFileURL(htmlUrl, allowingReadAccessTo: htmlUrl) } } // 实现 WKScriptMessageHandler 的代理方法,接收并处理从 H5 发送过来的消息 func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { if message.name == "myHandler" { if let body = message.body as? String { print("Received message from H5: \(body)") // 在这里可以进行相应的处理逻辑 } } } } ``` 在这个例子中,我们注册了名为 "myHandler" 的 messageHandler,并在 H5 页面中使用 `window.webkit.messageHandlers.myHandler.postMessage("Hello from H5")` 发送消息。在 iOS App 中,我们实现了 `WKScriptMessageHandler` 的代理方法 `userContentController(_:didReceive:)` 来接收并处理从 H5 发送过来的消息。 当 H5 页面中调用 `window.webkit.messageHandlers.myHandler.postMessage(<message>)` 时,iOS App 中的 `userContentController(_:didReceive:)` 方法会被调用,我们可以在这个方法中获取到消息内容,然后进行相应的处理。 希望这个例子能够帮助你理解如何在 iOS App 中接收来自 H5 页面的消息。如果有任何问题,请随时提问!
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值