-
Notifications
You must be signed in to change notification settings - Fork 0
/
atom.xml
1049 lines (844 loc) · 157 KB
/
atom.xml
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
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Botasky's Blog</title>
<link href="/atom.xml" rel="self"/>
<link href="https://github.com/iBotasky/"/>
<updated>2017-11-05T13:21:05.000Z</updated>
<id>https://github.com/iBotasky/</id>
<author>
<name>Botasky</name>
</author>
<generator uri="http://hexo.io/">Hexo</generator>
<entry>
<title>ConstraintLayout介绍</title>
<link href="https://github.com/iBotasky/2017/10/31/ConstraintLayout%E4%BB%8B%E7%BB%8D/"/>
<id>https://github.com/iBotasky/2017/10/31/ConstraintLayout介绍/</id>
<published>2017-10-31T14:17:14.000Z</published>
<updated>2017-11-05T13:21:05.000Z</updated>
<content type="html"><![CDATA[<p>介绍ConstrainLayout</p>
<a id="more"></a>
<h1 id="ConstraintLayout"><a href="#ConstraintLayout" class="headerlink" title="ConstraintLayout"></a>ConstraintLayout</h1><h2 id="1-为什么用ConstraintLayout"><a href="#1-为什么用ConstraintLayout" class="headerlink" title="1.为什么用ConstraintLayout"></a>1.为什么用ConstraintLayout</h2><h3 id="1-1-减少嵌套,加速界面渲染"><a href="#1-1-减少嵌套,加速界面渲染" class="headerlink" title="1.1 减少嵌套,加速界面渲染"></a>1.1 减少嵌套,加速界面渲染</h3><p><strong>ConstraintLayout</strong>的基本使用方式就是这些, 兼顾LinearLayout与RelativeLayout的优点, 非常适合构建复杂布局, 降低布局的层级, 优化布局,加快渲染速度。</p>
<h3 id="1-2-提供很多约束属性多,开发效率高"><a href="#1-2-提供很多约束属性多,开发效率高" class="headerlink" title="1.2 提供很多约束属性多,开发效率高"></a>1.2 提供很多约束属性多,开发效率高</h3><p>ConstraintLayout的属性有很多,有很多种约束属性, 熟悉之后可以高效完成界面搭建。</p>
<h3 id="1-3-有助于界面的适配"><a href="#1-3-有助于界面的适配" class="headerlink" title="1.3 有助于界面的适配"></a>1.3 有助于界面的适配</h3><p>传统Layout经常会遇到界面在不同机型界面不统一的问题,ConstraintLayout可以配合一些辅助控件像<code>GuideLine</code>的百分比(<code>app:layout_constraintGuide_percent="0.5"</code>)来对屏幕的水平和竖直方向做分割,在利用ConstraintLayout的属性对控件进行约束,可以达到让界面适配的效果。</p>
<h2 id="2-ConstraintLayout入门"><a href="#2-ConstraintLayout入门" class="headerlink" title="2.ConstraintLayout入门"></a>2.ConstraintLayout入门</h2><h3 id="2-1-常用约束"><a href="#2-1-常用约束" class="headerlink" title="2.1 常用约束"></a>2.1 常用约束</h3><p>公式:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">layout_constraint[本源控件要做约束位置]_to[目标控件相对的位置]="[目标控件ID]"</div></pre></td></tr></table></figure>
<blockquote>
<p>本源控件要做约束位置与目标控件的相对位置不能是随意的,是要在同一个方向上的位置,例如<code>Bottom_toBottomOf</code>,<code>Top_toBottomOf</code>, <code>Bottom_toTopOf</code>,<code>Top_toTopOf</code>是垂直方向上的一组约束,没有<code>Top_toStart</code>这样的约束。</p>
</blockquote>
<p><img src="http://oktzkaa8p.bkt.clouddn.com/20171031150945732850740.png" alt="20171031150945732850740.png"></p>
<blockquote>
<p>垂直方向有三个约束位置:Top, Bottom, BaseLine</p>
<p>水平方向有两个约束位置:Start(Left), End(Right)</p>
</blockquote>
<p>可用的约束,可以搭配<code>layout_[位置]</code>做一些基础和复杂的布局:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div></pre></td><td class="code"><pre><div class="line">layout_constraintLeft_toLeftOf</div><div class="line">layout_constraintLeft_toRightOf</div><div class="line">layout_constraintRight_toLeftOf</div><div class="line">layout_constraintRight_toRightOf</div><div class="line">layout_constraintTop_toTopOf</div><div class="line">layout_constraintTop_toBottomOf</div><div class="line">layout_constraintBottom_toTopOf</div><div class="line">layout_constraintBottom_toBottomOf</div><div class="line">layout_constraintBaseline_toBaselineOf</div><div class="line">layout_constraintStart_toEndOf</div><div class="line">layout_constraintStart_toStartOf</div><div class="line">layout_constraintEnd_toStartOf</div><div class="line">layout_constraintEnd_toEndOf</div></pre></td></tr></table></figure>
<h3 id="2-2-居中"><a href="#2-2-居中" class="headerlink" title="2.2 居中"></a>2.2 居中</h3><p>ConstraintLayout的居中是个比较不明显的功能,水平方向的居中,要对居中的控件<code>start(left)</code>和<code>end(right)</code>两个位置做好约束,垂直方向的居中要对控件<code>top</code>和<code>bottom</code>两个位置做约束就可以达到控件在约束区域的居中效果。如下</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line"><span class="tag"><<span class="name">ImageView</span></span></div><div class="line"> <span class="attr">android:id</span>=<span class="string">"@+id/imageView2"</span></div><div class="line"> <span class="attr">app:layout_constraintStart_toStartOf</span>=<span class="string">"parent"</span></div><div class="line"> <span class="attr">app:layout_constraintEnd_toEndOf</span>=<span class="string">"parent"</span></div><div class="line"> <span class="attr">app:layout_constraintTop_toTopOf</span>=<span class="string">"parent"</span></div><div class="line"> <span class="attr">app:layout_constraintBottom_toBottomOf</span>=<span class="string">"parent"</span></div><div class="line"> <span class="attr">android:layout_width</span>=<span class="string">"117dp"</span></div><div class="line"> <span class="attr">android:layout_height</span>=<span class="string">"143dp"</span></div><div class="line"> <span class="attr">app:srcCompat</span>=<span class="string">"@drawable/icon_android_bg"</span>/></div></pre></td></tr></table></figure>
<p><img src="http://oktzkaa8p.bkt.clouddn.com/20171101150954763071757.png" alt="20171101150954763071757.png"></p>
<h3 id="2-3-match-parent要用0dp来替代"><a href="#2-3-match-parent要用0dp来替代" class="headerlink" title="2.3 match_parent要用0dp来替代"></a>2.3 match_parent要用0dp来替代</h3><p>ConstraintLayout中de控件如果宽高要设置成<code>match_parent</code>需要设置成<code>0dp</code>(官方建议,也可以设置成match_parent,但是有些情况下match_parent会不生效)。设置成<code>0dp</code>也需要配合相对方向的约束。</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line"><span class="tag"><<span class="name">Button</span></span></div><div class="line"> <span class="attr">android:layout_width</span>=<span class="string">"0dp"</span></div><div class="line"> <span class="attr">android:layout_height</span>=<span class="string">"wrap_content"</span></div><div class="line"> <span class="attr">android:layout_marginBottom</span>=<span class="string">"64dp"</span></div><div class="line"> <span class="attr">android:text</span>=<span class="string">"注册"</span></div><div class="line"> <span class="attr">app:layout_constraintStart_toStartOf</span>=<span class="string">"parent"</span></div><div class="line"> <span class="attr">app:layout_constraintEnd_toEndOf</span>=<span class="string">"parent"</span>/></div></pre></td></tr></table></figure>
<p><img src="http://oktzkaa8p.bkt.clouddn.com/20171101150954786245526.png" alt="20171101150954786245526.png"></p>
<h3 id="2-4一些高级用法"><a href="#2-4一些高级用法" class="headerlink" title="2.4一些高级用法"></a>2.4一些高级用法</h3><h4 id="1-GONE与Margin"><a href="#1-GONE与Margin" class="headerlink" title="1.GONE与Margin"></a>1.GONE与Margin</h4><p>有可能会遇到一个情况是,目标控件有可能会被设置为<code>GONE</code>,这时候约束还是存在,界面有可能会产生不整齐的问题,这时候就可以用<code>layout_goneMargin</code>来重新设置margin。比如:</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div></pre></td><td class="code"><pre><div class="line"><span class="tag"><<span class="name">Button</span></span></div><div class="line"> <span class="attr">android:id</span>=<span class="string">"@+id/button1"</span></div><div class="line"> <span class="attr">android:layout_width</span>=<span class="string">"wrap_content"</span></div><div class="line"> <span class="attr">android:layout_height</span>=<span class="string">"wrap_content"</span></div><div class="line"> <span class="attr">android:layout_marginStart</span>=<span class="string">"20dp"</span></div><div class="line"> <span class="attr">android:text</span>=<span class="string">"BTN1"</span></div><div class="line"> <span class="attr">app:layout_constraintStart_toStartOf</span>=<span class="string">"parent"</span></div><div class="line"> <span class="attr">app:layout_constraintTop_toTopOf</span>=<span class="string">"parent"</span> /></div><div class="line"></div><div class="line"><span class="tag"><<span class="name">Button</span></span></div><div class="line"> <span class="attr">android:id</span>=<span class="string">"@+id/button2"</span></div><div class="line"> <span class="attr">android:layout_width</span>=<span class="string">"wrap_content"</span></div><div class="line"> <span class="attr">android:layout_height</span>=<span class="string">"wrap_content"</span></div><div class="line"> <span class="attr">android:text</span>=<span class="string">"BTN2"</span></div><div class="line"> <span class="attr">app:layout_constraintStart_toStartOf</span>=<span class="string">"@id/button1"</span></div><div class="line"> <span class="attr">app:layout_constraintTop_toBottomOf</span>=<span class="string">"@id/button1"</span> /></div><div class="line"></div><div class="line"><span class="tag"><<span class="name">Button</span></span></div><div class="line"> <span class="attr">android:layout_width</span>=<span class="string">"wrap_content"</span></div><div class="line"> <span class="attr">android:layout_height</span>=<span class="string">"wrap_content"</span></div><div class="line"> <span class="attr">android:layout_marginStart</span>=<span class="string">"50dp"</span></div><div class="line"> <span class="attr">android:text</span>=<span class="string">"BTN3"</span></div><div class="line"> <span class="attr">app:layout_constraintStart_toEndOf</span>=<span class="string">"@id/button2"</span></div><div class="line"> <span class="attr">app:layout_constraintTop_toTopOf</span>=<span class="string">"@id/button2"</span> /></div></pre></td></tr></table></figure>
<p><img src="http://oktzkaa8p.bkt.clouddn.com/20171105150988782494038.png" alt="20171105150988782494038.png"></p>
<p>button2设置GONE后,约束还在,btn3与左边间距还是50,导致界面不美观:</p>
<p><img src="http://oktzkaa8p.bkt.clouddn.com/2017110515098878884334.png" alt="2017110515098878884334.png"></p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line"><span class="tag"><<span class="name">Button</span></span></div><div class="line"> <span class="attr">android:layout_width</span>=<span class="string">"wrap_content"</span></div><div class="line"> <span class="attr">android:layout_height</span>=<span class="string">"wrap_content"</span></div><div class="line"> <span class="attr">android:layout_marginStart</span>=<span class="string">"50dp"</span></div><div class="line"> //在<span class="attr">Button</span>设置<span class="attr">goneMarginStart</span>表示左边控件<span class="attr">Gone</span>掉的话采用新的<span class="attr">margine</span></div><div class="line"> <span class="attr">app:layout_goneMarginStart</span>=<span class="string">"0dp"</span></div><div class="line"> <span class="attr">android:text</span>=<span class="string">"BTN3"</span></div><div class="line"> <span class="attr">app:layout_constraintStart_toEndOf</span>=<span class="string">"@id/button2"</span></div><div class="line"> <span class="attr">app:layout_constraintTop_toTopOf</span>=<span class="string">"@id/button2"</span> /></div></pre></td></tr></table></figure>
<p><img src="http://oktzkaa8p.bkt.clouddn.com/20171105150988805696462.png" alt="20171105150988805696462.png"></p>
<h4 id="2-Chain链式(主要是为了替代LinearLayout)"><a href="#2-Chain链式(主要是为了替代LinearLayout)" class="headerlink" title="2.Chain链式(主要是为了替代LinearLayout)"></a>2.Chain链式(主要是为了替代LinearLayout)</h4><p>有一种情况是需要等分显示布局,一般用的是LinearLayout,在ConstraintLayout里面主要是要用Chain来完成平分。各个布局之前都要做一个相对的约束。即各个布局之间都要做相互的约束。</p>
<p><img src="http://oktzkaa8p.bkt.clouddn.com/2017103115094573196056.png" alt="2017103115094573196056.png"></p>
<p>A与B做水平的平分,则A与B要做相互约束就能产生Chain:</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line"><span class="comment"><!--伪代码--></span></div><div class="line"><span class="comment"><!--A控件--></span></div><div class="line">start_toStartOf="parent"</div><div class="line">end_toStartOf="B" //对B约束</div><div class="line"></div><div class="line"><span class="comment"><!--B控件--></span></div><div class="line">start_toEndOf="A" //对A约束</div><div class="line">end_toEndOf="parent"</div></pre></td></tr></table></figure>
<p>并且可以通过<code>layout_constraintHorizontal_chainStyle</code> 或者<code>layout_constraintVertical_chainStyle</code>在平分的第一个控件设置水平或者垂直方向上Chain的方式:</p>
<p><img src="http://oktzkaa8p.bkt.clouddn.com/20171031150945730476198.png" alt="20171031150945730476198.png"></p>
<h4 id="3-GuideLine"><a href="#3-GuideLine" class="headerlink" title="3.GuideLine"></a>3.GuideLine</h4><p>GuideLine主要是可以创建一条基准线,用来做一个百分比,或者固定值的控件,用法有很多,在适配上面有好的效果。</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div></pre></td><td class="code"><pre><div class="line"></div><div class="line"><span class="tag"><<span class="name">android.support.constraint.Guideline</span></span></div><div class="line"> <span class="attr">android:id</span>=<span class="string">"@+id/guideline_v"</span></div><div class="line"> <span class="attr">android:layout_width</span>=<span class="string">"wrap_content"</span></div><div class="line"> <span class="attr">android:layout_height</span>=<span class="string">"wrap_content"</span></div><div class="line"> <span class="attr">android:orientation</span>=<span class="string">"horizontal"</span></div><div class="line"> <span class="attr">app:layout_constraintGuide_percent</span>=<span class="string">"0.6"</span>/></div><div class="line"><span class="tag"><<span class="name">com.botasky.cyberblack.view.ScanView</span></span></div><div class="line"> <span class="attr">android:layout_width</span>=<span class="string">"0dp"</span></div><div class="line"> <span class="attr">android:layout_height</span>=<span class="string">"0dp"</span></div><div class="line"> <span class="attr">app:layout_constraintStart_toStartOf</span>=<span class="string">"parent"</span></div><div class="line"> <span class="attr">app:layout_constraintEnd_toEndOf</span>=<span class="string">"parent"</span></div><div class="line"> <span class="attr">app:layout_constraintTop_toTopOf</span>=<span class="string">"parent"</span></div><div class="line"> <span class="attr">app:layout_constraintBottom_toBottomOf</span>=<span class="string">"@id/guideline_v"</span>/></div></pre></td></tr></table></figure>
<p><img src="http://oktzkaa8p.bkt.clouddn.com/20171105150988716083952.png" alt="20171105150988716083952.png"></p>
<p>上面的GuideLine就可以让自定义View,ScanView(或者其他的原生控件和自定义View)的height不管在任何屏幕下所占的高度都是主屏幕的60%。与传统的写死高度相比,用GuideLine可以让适配方案不在变得复杂。</p>
<h3 id="ConstraintLayout上手建议"><a href="#ConstraintLayout上手建议" class="headerlink" title="ConstraintLayout上手建议"></a>ConstraintLayout上手建议</h3><h4 id="1-尽量不要用手托控件去对控件做约束,而是用纯手打的方式去写约束"><a href="#1-尽量不要用手托控件去对控件做约束,而是用纯手打的方式去写约束" class="headerlink" title="1.尽量不要用手托控件去对控件做约束,而是用纯手打的方式去写约束"></a>1.尽量不要用手托控件去对控件做约束,而是用纯手打的方式去写约束</h4><p>AndroidStudio的手托控件功能很鸡肋,没有像Xcode的XIB那样强大,手托控件造成的一个问题是你可能会不理解Constraint的约束原理,并且手托控件会造成IDE生成一些让人琢磨不透的代码。</p>
<h4 id="2-协同开发AndroidStuido版本要统一"><a href="#2-协同开发AndroidStuido版本要统一" class="headerlink" title="2.协同开发AndroidStuido版本要统一"></a>2.协同开发AndroidStuido版本要统一</h4><p>开发过程中遇到过因为AndroidStudio版本不统一导致其他的开发队员拉取代码后出现XML代码会自动删除一些margin的代码,并且生成一些没有意义的布局代码,导致在低版本下面布局会错乱的问题。建议开发中把IDE升级到AndroidStudio3.0,对ConstraintLayout的支持会比较稳定。并且将ConstraintLayout的版本升到最新,目前最新版本是<code>1.1.0-beta3</code>。</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line"><span class="tag"><<span class="name">ImageView</span></span></div><div class="line"> <span class="attr">android:id</span>=<span class="string">"@+id/imageView2"</span></div><div class="line"> <span class="attr">android:layout_width</span>=<span class="string">"117dp"</span></div><div class="line"> <span class="attr">android:layout_height</span>=<span class="string">"143dp"</span></div><div class="line"> <span class="attr">app:srcCompat</span>=<span class="string">"@drawable/icon_android_bg"</span></div><div class="line"> //生成的无意义的代码</div><div class="line"> <span class="attr">tools:layout_editor_absoluteX</span>=<span class="string">"122dp"</span></div><div class="line"> <span class="attr">tools:layout_editor_absoluteY</span>=<span class="string">"312dp"</span> /></div></pre></td></tr></table></figure>
]]></content>
<summary type="html">
<p>介绍ConstrainLayout</p>
</summary>
<category term="Android" scheme="https://github.com/iBotasky/tags/Android/"/>
</entry>
<entry>
<title>iOS集成ShareSDK</title>
<link href="https://github.com/iBotasky/2017/08/29/iOS%E9%9B%86%E6%88%90ShareSDK/"/>
<id>https://github.com/iBotasky/2017/08/29/iOS集成ShareSDK/</id>
<published>2017-08-29T07:57:35.000Z</published>
<updated>2017-08-30T02:01:01.000Z</updated>
<content type="html"><![CDATA[<p>整理关于iOS集成ShareSDK遇到的问题.</p>
<a id="more"></a>
<p><a href="http://wiki.mob.com/cocoapods%E9%9B%86%E6%88%90/" target="_blank" rel="external">ShareSDK iOS 集成</a></p>
<h2 id="1-分享的时候没有显示相关图标的问题"><a href="#1-分享的时候没有显示相关图标的问题" class="headerlink" title="1.分享的时候没有显示相关图标的问题"></a>1.分享的时候没有显示相关图标的问题</h2><p>在<code>AppDelegate.m</code>配置了微博/QQ/微信,(代码中微信还没配置),代码如下:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div></pre></td><td class="code"><pre><div class="line">/**</div><div class="line"> 初始化ShareSDK</div><div class="line"> */</div><div class="line">- (void)initShareSDK{</div><div class="line"> [ShareSDK registerActivePlatforms:@[</div><div class="line"> @(SSDKPlatformTypeQQ),</div><div class="line"> @(SSDKPlatformTypeSinaWeibo),</div><div class="line"> @(SSDKPlatformTypeWechat)</div><div class="line"> ]</div><div class="line"> onImport:^(SSDKPlatformType platformType) {</div><div class="line"> switch (platformType) {</div><div class="line"> case SSDKPlatformTypeWechat:</div><div class="line"> [ShareSDKConnector connectWeChat:[WXApi class]];</div><div class="line"> break;</div><div class="line"> case SSDKPlatformTypeQQ:</div><div class="line"> [ShareSDKConnector connectQQ:[QQApiInterface class] tencentOAuthClass:[TencentOAuth class]];</div><div class="line"> break;</div><div class="line"> case SSDKPlatformTypeSinaWeibo:</div><div class="line"> [ShareSDKConnector connectWeibo:[WeiboSDK class]];</div><div class="line"> break;</div><div class="line"> default:</div><div class="line"> break;</div><div class="line"> }</div><div class="line"> </div><div class="line"> }</div><div class="line"> onConfiguration:^(SSDKPlatformType platformType, NSMutableDictionary *appInfo) {</div><div class="line"> switch (platformType) {</div><div class="line"> case SSDKPlatformTypeWechat:</div><div class="line"> </div><div class="line"> break;</div><div class="line"> case SSDKPlatformTypeQQ:</div><div class="line"> [appInfo SSDKSetupQQByAppId:@"1106033955"</div><div class="line"> appKey:@"lvUDjsm3mIKTaBOa"</div><div class="line"> authType:SSDKAuthTypeBoth];</div><div class="line"> break;</div><div class="line"> case SSDKPlatformTypeSinaWeibo:</div><div class="line"> //设置新浪微博应用信息,其中authType设置为使用SSO+Web形式授权</div><div class="line"> [appInfo SSDKSetupSinaWeiboByAppKey:@"1585205826"</div><div class="line"> appSecret:@"d0f8acf2e5c2f38efe7e996f7ce53832"</div><div class="line"> redirectUri:@"http://www.sharesdk.cn"</div><div class="line"> authType:SSDKAuthTypeBoth];</div><div class="line"></div><div class="line"> break;</div><div class="line"> default:</div><div class="line"> break;</div><div class="line"> }</div><div class="line"> }];</div><div class="line">}</div></pre></td></tr></table></figure>
<p>但是在实际显示出来,是有问题的,QQ跟QZone没有显示出来,只显示了微博:</p>
<p><img src="https://ooo.0o0.ooo/2017/08/29/59a52283cd38d.jpg" alt="59a52283cd38d.jpg"></p>
<p>原因是没有配置一些必要的Schem白名单:</p>
<p><a href="http://wiki.mob.com/%E9%80%82%E9%85%8Dios-9%EF%BC%8B%E7%B3%BB%E7%BB%9F/" target="_blank" rel="external">配置白名单</a></p>
<p>对应的一些平台如微信,QQ等平台还要按照集成文档的方案去配置<code>URL Types</code></p>
<p><a href="http://wiki.mob.com/cocoapods%E9%9B%86%E6%88%90/" target="_blank" rel="external">ShareSDK iOS CocoPods集成</a></p>
<p>否则会分享失败.</p>
<h2 id="2-分享成功后-如果停留在分享平台-返回自己的App-即是分享成功-回调的状态是Cancel"><a href="#2-分享成功后-如果停留在分享平台-返回自己的App-即是分享成功-回调的状态是Cancel" class="headerlink" title="2.分享成功后,如果停留在分享平台,返回自己的App,即是分享成功,回调的状态是Cancel"></a>2.分享成功后,如果停留在分享平台,返回自己的App,即是分享成功,回调的状态是Cancel</h2><p>按照ShareSDK人工服务的回答来说这个是正常的流程,所以如果是Cancel状态,就不做提示.</p>
<h2 id="3-做的过程中遗忘了添加ShareSDK的Appkey跟Secret到info-plist"><a href="#3-做的过程中遗忘了添加ShareSDK的Appkey跟Secret到info-plist" class="headerlink" title="3.做的过程中遗忘了添加ShareSDK的Appkey跟Secret到info.plist"></a>3.做的过程中遗忘了添加ShareSDK的Appkey跟Secret到info.plist</h2><p>在项目的根<code>info.plist</code>添加在官网申请的Secret跟Key,KEY为<code>MOBAppSecret</code>跟<code>MOBAppkey</code>.</p>
]]></content>
<summary type="html">
<p>整理关于iOS集成ShareSDK遇到的问题.</p>
</summary>
<category term="iOS" scheme="https://github.com/iBotasky/categories/iOS/"/>
<category term="Social" scheme="https://github.com/iBotasky/categories/iOS/Social/"/>
<category term="iOS" scheme="https://github.com/iBotasky/tags/iOS/"/>
<category term="Social" scheme="https://github.com/iBotasky/tags/Social/"/>
</entry>
<entry>
<title>iOS动画:CABasicAnimation</title>
<link href="https://github.com/iBotasky/2017/08/28/iOS%E5%8A%A8%E7%94%BB-CABasicAnimation/"/>
<id>https://github.com/iBotasky/2017/08/28/iOS动画-CABasicAnimation/</id>
<published>2017-08-28T02:46:32.000Z</published>
<updated>2017-08-28T03:49:36.000Z</updated>
<content type="html"><![CDATA[<p>介绍iOS的Layer层的CABasicAnimataion动画</p>
<a id="more"></a>
<h2 id="1-CAAnimation"><a href="#1-CAAnimation" class="headerlink" title="1.CAAnimation"></a>1.CAAnimation</h2><p>iOS中Core Animation层的动画是依赖CAAnimation类实现的.iOS中还有其他层的动画</p>
<p><img src="http://upload-images.jianshu.io/upload_images/1053533-6eae72f7fd9bd271.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="iOS动画"></p>
<p>越上层,动画的封装度越高,动画实现越简洁,但是相反的,自由度更低.</p>
<p>这里主要理解CAAnimation,CAAnimation分为几类:</p>
<blockquote>
<ul>
<li>CABasicAnimation基础动画,通过设定起始点,终点,时间动画会沿着指定的设定去做动画.可以看做特殊的CAKeyFrameAniamtion</li>
<li>CAKeyFrameAniamtion关键帧动画,可指定度度比CABasicAnimation高</li>
<li>CAAnimationGroup组动画,可以将一系列CABasicAniamtion或者CAKeyFrameAniamtion组合起来同时执行的动画方式.</li>
</ul>
</blockquote>
<h2 id="2-CABasicAnimation"><a href="#2-CABasicAnimation" class="headerlink" title="2.CABasicAnimation"></a>2.CABasicAnimation</h2><h3 id="2-1缩放"><a href="#2-1缩放" class="headerlink" title="2.1缩放"></a>2.1缩放</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];</div><div class="line"> scaleAnimation.fromValue = [NSNumber numberWithFloat:1.0];</div><div class="line"> scaleAnimation.toValue = [NSNumber numberWithFloat:1.5];</div><div class="line"> scaleAnimation.autoreverses = YES;</div><div class="line"> scaleAnimation.repeatCount = MAXFLOAT;</div><div class="line"> scaleAnimation.duration = 0.8;</div></pre></td></tr></table></figure>
<table>
<thead>
<tr>
<th>KeyPath</th>
<th>Description</th>
<th>ValueType</th>
</tr>
</thead>
<tbody>
<tr>
<td>transform.scale</td>
<td>对三个轴做缩放变换</td>
<td>NSNumber</td>
</tr>
<tr>
<td>transform.scale.x</td>
<td>对x轴做缩放</td>
<td>NSNumber</td>
</tr>
<tr>
<td>transform.scale.y</td>
<td>对y轴做缩放</td>
<td>NSNumber</td>
</tr>
<tr>
<td>transform.scale.z</td>
<td>对z轴做缩放</td>
<td>NSNumber</td>
</tr>
</tbody>
</table>
<h3 id="2-2移动"><a href="#2-2移动" class="headerlink" title="2.2移动"></a>2.2移动</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">CABasicAnimation *moveAnimation = [CABasicAnimation animationWithKeyPath:@"position"];</div><div class="line"> moveAnimation.fromValue = [NSValue valueWithCGPoint:groupLayer.position];</div><div class="line"> moveAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(320 - 80, groupLayer.position.y)];</div><div class="line"> moveAnimation.autoreverses = YES;</div><div class="line"> moveAnimation.repeatCount = MAXFLOAT;</div><div class="line"> moveAnimation.duration = 2;</div></pre></td></tr></table></figure>
<table>
<thead>
<tr>
<th>KeyPath</th>
<th>Description</th>
<th>ValueType</th>
</tr>
</thead>
<tbody>
<tr>
<td>transform.translation.x</td>
<td>沿着x轴平移</td>
<td>NSNumber</td>
</tr>
<tr>
<td>transform.translation.y</td>
<td>沿着y轴平移</td>
<td>NSNumber</td>
</tr>
<tr>
<td>transform.translation.z</td>
<td>沿着z轴平移</td>
<td>NSNumber</td>
</tr>
<tr>
<td>transform.translation</td>
<td>沿着x/y轴平移</td>
<td>NSSize/CGSize</td>
</tr>
</tbody>
</table>
<h3 id="2-3旋转"><a href="#2-3旋转" class="headerlink" title="2.3旋转"></a>2.3旋转</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">CABasicAnimation *rotateAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.x"];</div><div class="line"> rotateAnimation.fromValue = [NSNumber numberWithFloat:0.0];</div><div class="line"> rotateAnimation.toValue = [NSNumber numberWithFloat:6.0 * M_PI];</div><div class="line"> rotateAnimation.autoreverses = YES;</div><div class="line"> rotateAnimation.repeatCount = MAXFLOAT;</div><div class="line"> rotateAnimation.duration = 2;</div></pre></td></tr></table></figure>
<table>
<thead>
<tr>
<th>KeyPath</th>
<th>Description</th>
<th>ValueType</th>
</tr>
</thead>
<tbody>
<tr>
<td>transform.rotation.x</td>
<td>以x轴为轴心旋转</td>
<td>NSNumber</td>
</tr>
<tr>
<td>transform.rotation.y</td>
<td>以Y轴为轴心旋转</td>
<td>NSNumber</td>
</tr>
<tr>
<td>transform.rotation.z</td>
<td>以z轴为轴心旋转</td>
<td>NSNumber</td>
</tr>
<tr>
<td>transform.rotation</td>
<td>跟rotation.z一样以z为轴心旋转</td>
<td>NSNumber</td>
</tr>
</tbody>
</table>
<h3 id="2-4其他的KeyPath动画"><a href="#2-4其他的KeyPath动画" class="headerlink" title="2.4其他的KeyPath动画"></a>2.4其他的KeyPath动画</h3><table>
<thead>
<tr>
<th>KeyPath</th>
<th>Description</th>
<th>ValueType</th>
</tr>
</thead>
<tbody>
<tr>
<td>position</td>
<td>中心变化,可以用来做移动动画</td>
<td>CGPoint</td>
</tr>
<tr>
<td>position.x</td>
<td>中心X变化</td>
<td>CGFloat</td>
</tr>
<tr>
<td>position.y</td>
<td>中心Y变化</td>
<td>CGFloat</td>
</tr>
<tr>
<td>opacity</td>
<td>透明度变化</td>
<td>NSNumber</td>
</tr>
<tr>
<td>contents</td>
<td>内容变化,如imageView.iamge</td>
<td>Image.CGImage</td>
</tr>
<tr>
<td>cornerRadius</td>
<td>圆角变化</td>
<td>NSNum</td>
</tr>
<tr>
<td>bounds</td>
<td>大小变化,中心不变</td>
<td>CGRect</td>
</tr>
<tr>
<td>borderWidth</td>
<td>边框宽</td>
<td>NSNumber</td>
</tr>
</tbody>
</table>
<h3 id="2-5-组动画"><a href="#2-5-组动画" class="headerlink" title="2.5 组动画"></a>2.5 组动画</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">CAAnimationGroup *groupAnnimation = [CAAnimationGroup animation];</div><div class="line"> groupAnnimation.duration = 2;</div><div class="line"> groupAnnimation.autoreverses = YES;</div><div class="line"> groupAnnimation.animations = @[moveAnimation, scaleAnimation, rotateAnimation];</div><div class="line"> groupAnnimation.repeatCount = MAXFLOAT;</div></pre></td></tr></table></figure>
<h2 id="3-CABasicAnimation中的关键属性"><a href="#3-CABasicAnimation中的关键属性" class="headerlink" title="3.CABasicAnimation中的关键属性"></a>3.CABasicAnimation中的关键属性</h2><h3 id="3-1keyPath"><a href="#3-1keyPath" class="headerlink" title="3.1keyPath"></a>3.1keyPath</h3><p>决定动画的类型,不能随便取,只能按文档上面的取值. 如改变中心位置要用<code>position</code>,改变透明度要用<code>opacity</code>,如上面的几张表所示.</p>
<h3 id="3-2-fromValue-toValue"><a href="#3-2-fromValue-toValue" class="headerlink" title="3.2 fromValue/toValue"></a>3.2 fromValue/toValue</h3><p>动画的起始状态跟结束状态的值,根据文档中相应的ValueType提供值.</p>
<h3 id="3-3-autoreverse"><a href="#3-3-autoreverse" class="headerlink" title="3.3 autoreverse"></a>3.3 autoreverse</h3><p>是否反向动画,即正方向播放完动画,设置是否反方向播放.</p>
<h3 id="3-4-fileMode"><a href="#3-4-fileMode" class="headerlink" title="3.4 fileMode"></a>3.4 fileMode</h3><p>fillMode的作用就是决定当前对象过了非active时间段的行为. 非active时间段是指动画开始之前以及动画结束之后。</p>
<p>如果是一个动画CAAnimation,则<strong>需要将其removedOnCompletion设置为NO,要不然fillMode不起作用</strong>. </p>
<blockquote>
<p>*kCAFillModeRemoved 这个是默认值,也就是说当动画开始前和动画结束后,动画对layer都没有影响,动画结束后,layer会恢复到之前的状态</p>
<p>*kCAFillModeForwards 当动画结束后,layer会一直保持着动画最后的状态 </p>
<p>*kCAFillModeBackwards 这个和kCAFillModeForwards是相对的,就是在动画开始前,你只要将动画加入了一个layer,layer便立即进入动画的初始状态。因为有可能出现fromValue不是目前layer的初始状态的情况,如果fromValue就是layer当前的状态,则这个参数就没太大意义。</p>
<p>*kCAFillModeBoth 理解了上面两个,这个就很好理解了,这个其实就是上面两个的合成.动画加入后开始之前,layer便处于动画初始状态,动画结束后layer保持动画最后的状态.</p>
</blockquote>
<p>## </p>
]]></content>
<summary type="html">
<p>介绍iOS的Layer层的CABasicAnimataion动画</p>
</summary>
<category term="iOS" scheme="https://github.com/iBotasky/categories/iOS/"/>
<category term="iOS动画" scheme="https://github.com/iBotasky/categories/iOS/iOS%E5%8A%A8%E7%94%BB/"/>
<category term="iOS" scheme="https://github.com/iBotasky/tags/iOS/"/>
<category term="iOS动画" scheme="https://github.com/iBotasky/tags/iOS%E5%8A%A8%E7%94%BB/"/>
</entry>
<entry>
<title>iOS锚点</title>
<link href="https://github.com/iBotasky/2017/08/28/iOS%E9%94%9A%E7%82%B9/"/>
<id>https://github.com/iBotasky/2017/08/28/iOS锚点/</id>
<published>2017-08-28T01:34:29.000Z</published>
<updated>2017-08-28T01:55:01.000Z</updated>
<content type="html"><![CDATA[<p>介绍iOS图层中d的锚点<code>anchorPoint</code></p>
<a id="more"></a>
<h2 id="AnchorPoint-锚点"><a href="#AnchorPoint-锚点" class="headerlink" title="AnchorPoint 锚点"></a>AnchorPoint 锚点</h2><p>视图(View)的<code>center</code>属性跟图层(Layer)的<code>position</code>属性都指定了<code>anchorPoint</code>相对于父图层的位置。图层的<code>anchorPoint</code>通过<code>position</code>来控制它<code>frame</code>的位置. 可以说<code>anchorPoint</code>是用来移动图层的<em>把柄</em>.</p>
<p>默认的,<code>anchorPoint</code>位于图层中点,所以图层会以这个点为中心放置. <code>anchorPoint</code>的属性在<code>UIVIew</code>没有被暴露出来,这也是View的<code>position</code>叫做<code>center</code>的原因.</p>
<p>但是图层的<code>anchorPoint</code>可以被移动.比如,你可以把它置于图层<code>frame</code>的左上角,于是图层的内容就会向右下角的<code>position</code>移动,而不是居中了.</p>
<p><img src="https://i.loli.net/2017/08/28/59a37615c18b9.jpg" alt="59a37615c18b9.jpg"></p>
<h2 id="AnchorPoint的应用场景"><a href="#AnchorPoint的应用场景" class="headerlink" title="AnchorPoint的应用场景"></a>AnchorPoint的应用场景</h2><p><a href="https://zsisme.gitbooks.io/ios-/content/chapter3/anchor.html" target="_blank" rel="external">参照</a></p>
]]></content>
<summary type="html">
<p>介绍iOS图层中d的锚点<code>anchorPoint</code></p>
</summary>
<category term="iOS" scheme="https://github.com/iBotasky/categories/iOS/"/>
<category term="iOS动画" scheme="https://github.com/iBotasky/categories/iOS/iOS%E5%8A%A8%E7%94%BB/"/>
<category term="iOS" scheme="https://github.com/iBotasky/tags/iOS/"/>
<category term="iOS动画" scheme="https://github.com/iBotasky/tags/iOS%E5%8A%A8%E7%94%BB/"/>
</entry>
<entry>
<title>更新于2017/08/27</title>
<link href="https://github.com/iBotasky/2017/08/26/%E6%9B%B4%E6%96%B0%E4%BA%8E2017-08-27/"/>
<id>https://github.com/iBotasky/2017/08/26/更新于2017-08-27/</id>
<published>2017-08-26T15:56:36.000Z</published>
<updated>2017-08-26T16:00:50.000Z</updated>
<content type="html"><![CDATA[<p>今天更新了博客主题</p>
<a id="more"></a>
<p>今天更新了Hexo博客的主题,是一个以Material设计为主的模板,看着很好,就用了这个主题。推荐给大家</p>
<p><a href="https://github.com/viosey/hexo-theme-material">Material</a></p>
<p><a href="https://material.viosey.com/" target="_blank" rel="external">Material配置及教程</a></p>
]]></content>
<summary type="html">
<p>今天更新了博客主题</p>
</summary>
<category term="随笔" scheme="https://github.com/iBotasky/tags/%E9%9A%8F%E7%AC%94/"/>
</entry>
<entry>
<title>iOS模态视图.md</title>
<link href="https://github.com/iBotasky/2017/08/15/iOS%E6%A8%A1%E6%80%81%E8%A7%86%E5%9B%BE/"/>
<id>https://github.com/iBotasky/2017/08/15/iOS模态视图/</id>
<published>2017-08-15T06:17:54.000Z</published>
<updated>2017-08-27T09:19:26.000Z</updated>
<content type="html"><![CDATA[<p>iOS的模态视图<br><a id="more"></a></p>
<h2 id="1-概念"><a href="#1-概念" class="headerlink" title="1.概念"></a>1.概念</h2><p>iOS开发中,在当前视图上弹出一个视图(模态视图)例如登录视图,分享视图,注册视图等等。</p>
<h2 id="2-说明"><a href="#2-说明" class="headerlink" title="2.说明"></a>2.说明</h2><p>实现一个简单的多视图应用,视图控制器都会有一个<code>presentViewController</code>方法,用来显示模态视图窗口,在一些特别的环境下,例如登录,注册,分享等我们尤其希望使用这种方式去展现视图。</p>
<h3 id="2-1-具体设置和使用"><a href="#2-1-具体设置和使用" class="headerlink" title="2.1 具体设置和使用"></a>2.1 具体设置和使用</h3><h4 id="1-弹出模态视图窗口-presentViewController-方法"><a href="#1-弹出模态视图窗口-presentViewController-方法" class="headerlink" title="1.弹出模态视图窗口(presentViewController)方法"></a>1.弹出模态视图窗口(presentViewController)方法</h4><p>代码:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">RegisterViewContrller *registerVc = [RegisterViewController alloc]init];</div><div class="line">[self presentViewController:registerVc animated:YES];</div></pre></td></tr></table></figure>
<h4 id="2-弹出时动画风格"><a href="#2-弹出时动画风格" class="headerlink" title="2.弹出时动画风格"></a>2.弹出时动画风格</h4><p>弹出模态窗口时,如果我们选择了动画,那么我们可以通过modalTranslationStyle属性设置动画风格</p>
<p><strong>UIModalTransitionStyleCoverVertical</strong> // 底部滑入。<br><strong>UIModalTransitionStyleFlipHorizontal</strong> // 水平翻转。<br><strong>UIModalTransitionStyleCrossDissolve</strong> // 交叉溶解。<br><strong>UIModalTransitionStylePartialCurl</strong> // 翻页。</p>
<h4 id="3-回收模态视图"><a href="#3-回收模态视图" class="headerlink" title="3.回收模态视图"></a>3.回收模态视图</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">[self dissmissViewControllerAnimated:YES completion:nil];</div></pre></td></tr></table></figure>
<h4 id="4-presentingViewController"><a href="#4-presentingViewController" class="headerlink" title="4.presentingViewController"></a>4.presentingViewController</h4><p>presentingViewController是UIViewController的属性,官方文档上这么解释</p>
<blockquote>
<p><a href="https://developer.apple.com/reference/uikit/uiviewcontroller/1621430-presentingviewcontroller?language=objc" target="_blank" rel="external">presentingViewController </a><br>The view controller that presented this view controller.</p>
</blockquote>
<p>A 视图present了B视图,B视图的presentingViewContrller就是A视图 </p>
<h2 id="3-视图控制容器(ViewController-Container"><a href="#3-视图控制容器(ViewController-Container" class="headerlink" title="3.视图控制容器(ViewController Container)"></a>3.视图控制容器(ViewController Container)</h2><p><code>UINavigationController</code>/ <code>UITabBarController</code>/<code>UISlipViewController</code>等都属于ViewController Container,这些类的共性是都有一个类型为<code>ViewController</code>的对象数组,属性叫<code>viewControllers</code>,用于保存一组ViewControlller, ViewController Container会有自己默认的外观。</p>
<p>任何的<code>ViewController Container</code>对象都可以通过属性<code>viewControllers</code>访问子对象,而子对象也可以通过<code>navigationController</code>/<code>tabbarController</code>/<code>slipViewController</code>/<code>presentViewController</code>找到相应的<code>viewController Container</code>。</p>
<p><strong>- (void)dismissViewControllerAnimated:(BOOL)flag completion:(void (^)(void))completion;</strong></p>
<p>A present B,那么A就有责任dismiss B,如果在B中调用<strong>[self dismissViewControllerAnimated…]</strong>就会A中发送dismiss,最终会由有A进行dismiss,相当于在B中执行<strong>[self.presentingViewController dismissViewControllerAnimated…]</strong></p>
]]></content>
<summary type="html">
<p>iOS的模态视图<br>
</summary>
<category term="iOS" scheme="https://github.com/iBotasky/categories/iOS/"/>
<category term="iOS" scheme="https://github.com/iBotasky/tags/iOS/"/>
</entry>
<entry>
<title>iOS的.h跟.m文件</title>
<link href="https://github.com/iBotasky/2017/07/20/iOS%E7%9A%84-h%E8%B7%9F-m%E6%96%87%E4%BB%B6/"/>
<id>https://github.com/iBotasky/2017/07/20/iOS的-h跟-m文件/</id>
<published>2017-07-20T01:31:02.000Z</published>
<updated>2017-08-27T09:19:39.000Z</updated>
<content type="html"><![CDATA[<p>iOS开发中OC的.h文件跟.m文件</p>
<a id="more"></a>
<h2 id="1-文件"><a href="#1-文件" class="headerlink" title="1.文件"></a>1.文件</h2><h3 id="1-1-h文件"><a href="#1-1-h文件" class="headerlink" title="1.1.h文件"></a>1.1.h文件</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line">@interface ClassName{</div><div class="line"> NSString* _value1;</div><div class="line">}</div><div class="line"></div><div class="line">@property(nonatomic,assign)NSString* value1;</div><div class="line"></div><div class="line">-(void)func1;</div></pre></td></tr></table></figure>
<h3 id="1-2-m文件"><a href="#1-2-m文件" class="headerlink" title="1.2 .m文件"></a>1.2 .m文件</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line">@interface ClassName(){</div><div class="line">}</div><div class="line">@end</div><div class="line"></div><div class="line">@synthesize value1;</div><div class="line"></div><div class="line">@implementation ClassName</div><div class="line"></div><div class="line">-(void)func1{</div><div class="line">}</div><div class="line">@end</div></pre></td></tr></table></figure>
<h2 id="2-问题"><a href="#2-问题" class="headerlink" title="2. 问题"></a>2. 问题</h2><h3 id="2-1-为什么-h文件和-m文件里各有1个-interface-它们分别有什么用?"><a href="#2-1-为什么-h文件和-m文件里各有1个-interface-它们分别有什么用?" class="headerlink" title="2.1 为什么.h文件和.m文件里各有1个@interface?它们分别有什么用?"></a>2.1 为什么.h文件和.m文件里各有1个<code>@interface</code>?它们分别有什么用?</h3><p>.h里面的<code>@interface</code>,不消说,是典型的头文件,它是供其它Class调用的。它的<code>@property</code>和functions,都能够被其它Class“看到”。</p>
<p><strong><em>用我的话理解就是,如果写在了.h的<code>@interface</code>的属性和方法就是<code>public</code>可以被外面调用的。写在了.m的<code>@interface</code>里面就是<code>private</code>。</em></strong></p>
<p>因此,我们将对外开放的方法、变量放到.h文件中,而将不想要对外开放的变量放到.m文件中(.m文件的方法可以不声明,直接用)。</p>
<h3 id="2-2-h中,value1为什么要定义2遍?"><a href="#2-2-h中,value1为什么要定义2遍?" class="headerlink" title="2.2.h中,value1为什么要定义2遍?"></a>2.2.h中,value1为什么要定义2遍?</h3><p>当然,现在<code>@interface{}</code>里的定义也可以省略掉了,不过原理还是要搞清楚。</p>
<p>严格来说<code>@interface{}</code>里定义的变量,叫作instance variable,它是这个Class内部真正的全局变量。然而这个instance variable是不对外公开的,因此我们还需要一个对外公开的东西来调用,就是@property<br>@property是对外的,它其实是告诉大家,我这个Class里,有一个变量的set/get方法。比如,<code>@property NSString* string;</code> 就是说,本Class里有一个getString/setString供你们调用。</p>
<p>因此需要2次声明。当然现在lldb也升级了,只要你声明了<code>@property</code>,它就可以自动创建对应的全局变量。</p>
<h3 id="2-3-synthesize有什么用?"><a href="#2-3-synthesize有什么用?" class="headerlink" title="2.3@synthesize有什么用?"></a>2.3@synthesize有什么用?</h3><p><code>@property</code> 一个变量后,在<code>@implementation</code>里再<code>@synthesize</code>一下,相信是很多人的习惯。但是为什么要有这个@synthesize方法呢?</p>
<p><code>@property</code>是对外声明了Class的get/set方法,然后我们就需要在.m文件里手写get/set方法。这可就麻烦了,1个变量对应2个方法,假如一个Class里有10个变量,那岂不是要写20个方法?烦也烦死唠。</p>
<p>@synthesize帮我们解决了这个问题。<code>@synthesize</code>在.m文件里自动生成了get/set方法。因此,我们只要在<code>@implementation</code>后面加上一行:<code>@synthesize</code> 就可以自动生成get/set方法了,省掉了很多麻烦。比如<code>@synthesize value1 = _value1;</code>的意思就是,将instance variable _value1用作getValue1和setValue1方法里。</p>
<p>get/set方法有时候是比较复杂的,因为它和变量的属性相关,就是<code>@property(nonatomic, assign/retain(strong/weak))</code>这就和内存有关了。然而@synthesize为我们做了这些事情,就不要再为这些事情烦恼了!</p>
]]></content>
<summary type="html">
<p>iOS开发中OC的.h文件跟.m文件</p>
</summary>
<category term="iOS" scheme="https://github.com/iBotasky/categories/iOS/"/>
<category term="iOS基础" scheme="https://github.com/iBotasky/categories/iOS/iOS%E5%9F%BA%E7%A1%80/"/>
<category term="iOS" scheme="https://github.com/iBotasky/tags/iOS/"/>
<category term="iOS基础" scheme="https://github.com/iBotasky/tags/iOS%E5%9F%BA%E7%A1%80/"/>
</entry>
<entry>
<title>Lambda在Android中的使用</title>
<link href="https://github.com/iBotasky/2017/07/06/Lambda%E5%9C%A8Android%E4%B8%AD%E7%9A%84%E4%BD%BF%E7%94%A8/"/>
<id>https://github.com/iBotasky/2017/07/06/Lambda在Android中的使用/</id>
<published>2017-07-06T06:41:59.000Z</published>
<updated>2017-08-27T09:20:28.000Z</updated>
<content type="html"><![CDATA[<p>Lambda语法在Android中的应用</p>
<a id="more"></a>
<h2 id="0-作用"><a href="#0-作用" class="headerlink" title="0.作用"></a>0.作用</h2><p>lambda是匿名函数的别名,用来简化匿名内部类,使用lambda的前提是编译器可以准确的推断出你需要哪个匿名内部类被简化。</p>
<h3 id="0-1-例子"><a href="#0-1-例子" class="headerlink" title="0.1 例子"></a>0.1 例子</h3><p>我们最常接触到的例子是view设置onClickListener:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">button.setOnClickListener(<span class="keyword">new</span> View.OnClickListener(){</div><div class="line"> <span class="meta">@Override</span> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onClick</span><span class="params">(View v)</span></span>{</div><div class="line"> doSomeWork();</div><div class="line"> }</div><div class="line">});</div></pre></td></tr></table></figure>
<p>使用lambda:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">button.setOnClickListener( </div><div class="line"> (View v) -> {</div><div class="line"> doSomeWork();</div><div class="line"> }</div><div class="line">);</div></pre></td></tr></table></figure>
<p>lambda不仅把对象名隐匿(<code>View.OnClickLisetener</code>),更完成了方法名的隐匿(<code>onClick(View v)</code>),展示了一个接口抽象方法最有价值的亮点:<strong>参数</strong>、<strong>实现方法</strong></p>
<h2 id="1-lambda表达式的形式"><a href="#1-lambda表达式的形式" class="headerlink" title="1.lambda表达式的形式"></a>1.lambda表达式的形式</h2><h3 id="1-1-函数式接口"><a href="#1-1-函数式接口" class="headerlink" title="1.1 函数式接口"></a>1.1 函数式接口</h3><p><strong>函数式接口是最基本的lambda表达式,其余的形式都是由其扩展而来</strong></p>
<p>函数式接口是指有且只有一个抽象方法的接口, 比如各种Listener和Runnable接口。lambda表达式就是对这类接口的匿名接口内部类进行简化,基本形式如下:</p>
<p><code>(参数列表 ... ) -> { 语句块...}</code></p>
<p>面以 Java 提供的 Comparator 接口来展示一个实例,该接口常用于排序比较:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line"><span class="class"><span class="keyword">interface</span> <span class="title">Comparator</span><<span class="title">T</span>> </span>{<span class="function"><span class="keyword">int</span> <span class="title">compare</span><span class="params">(T var1, T var2)</span></span>;}</div><div class="line">Comparator<String> comparator = <span class="keyword">new</span> Comparator<String> (){</div><div class="line"> <span class="meta">@Override</span> <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">compare</span><span class="params">(String s1, String s2)</span> </span>{</div><div class="line"> doSomeWork();</div><div class="line"> <span class="keyword">return</span> result;</div><div class="line"> }</div><div class="line">};</div><div class="line">Comparator<String> comparator = (String s1, String s2) -> {</div><div class="line"> doSomeWork();</div><div class="line"> <span class="keyword">return</span> result;</div><div class="line">};</div></pre></td></tr></table></figure>
<p>当编译器可以推到出具体的参数类型,可以忽略参数类型,简化:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">Comparator<String> comparator = ( s1 , s2 ) -> {</div><div class="line"> doSomeWork();</div><div class="line"> <span class="keyword">return</span> result;</div><div class="line">};</div></pre></td></tr></table></figure>
<p>当参数只有一个时, 参数列表可以去掉括号<code>()</code>, 简化:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="class"><span class="keyword">interface</span> <span class="title">OnClickListener</span> </span>{ <span class="function"><span class="keyword">void</span> <span class="title">onClick</span><span class="params">(View v)</span></span>; }</div><div class="line">OnClickListener listener = v -> { 语句块... } ;</div></pre></td></tr></table></figure>
<p>但是,当没有参数传入的时候,参数列表的括号就要保留:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="class"><span class="keyword">interface</span> <span class="title">Runnable</span> </span>{ <span class="function"><span class="keyword">void</span> <span class="title">run</span><span class="params">()</span></span>; }</div><div class="line">Runnable runnable = () -> { 语句块... } ;</div></pre></td></tr></table></figure>
<p>当具体实现的处理逻辑只有一句的时候,也可以省略语句块的<code>{}</code>:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">button.setOnClickListener( v -> activity.finish() );</div></pre></td></tr></table></figure>
<p>当<strong>具体实现只有一句,并且是个return返回值的时候</strong>,这个表达式不用在表达式前面加<code>retrun</code>:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line"><span class="class"><span class="keyword">interface</span> <span class="title">Function</span> <<span class="title">T</span>, <span class="title">R</span>> </span>{ <span class="function">R <span class="title">apply</span><span class="params">(T t)</span></span>; }</div><div class="line">Function <User, String> function = <span class="keyword">new</span> Function <User, String>(){</div><div class="line"> <span class="meta">@Override</span> <span class="function"><span class="keyword">public</span> String <span class="title">apply</span><span class="params">(User user)</span> </span>{</div><div class="line"> <span class="keyword">return</span> user.getName();</div><div class="line"> }</div><div class="line">};</div><div class="line"><span class="comment">//不能加return,因为只有一句表达式,并且是return一个值</span></div><div class="line">Function <User, String> function = user -> user.getName() ;</div></pre></td></tr></table></figure>
<h2 id="1-2-方法引用"><a href="#1-2-方法引用" class="headerlink" title="1.2 方法引用"></a>1.2 方法引用</h2><p>当我们使用函数接口的lambda的时候,进行逻辑实现的时候,我们既可以自己实现一系列处理,也可以调用已存在的方法,下面以 Java 的 Predicate 接口作为示例,此接口用来实现判断功能,我们来对字符串进行全面的判空操作:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="class"><span class="keyword">interface</span> <span class="title">Predicate</span><<span class="title">T</span>> </span>{ <span class="function"><span class="keyword">boolean</span> <span class="title">test</span><span class="params">(T t)</span></span>; }</div><div class="line">Predicate<String> predicate=</div><div class="line"> s -> {</div><div class="line"> <span class="comment">//用基本代码组合进行判断</span></div><div class="line"> <span class="keyword">return</span> s==<span class="keyword">null</span> || s.length()==<span class="number">0</span> ;</div><div class="line"> };</div></pre></td></tr></table></figure>
<p>我们知道,TextUtils.isEmpty()实现了上述功能,所以我们可以调用已存在的方法来进行逻辑判断:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">Predicate<String> predicate = s -> TextUtils.isEmpty(s);</div></pre></td></tr></table></figure>
<p>当我们调用已存在的方法来进行逻辑判断,可以简化使用lambda的方法引用:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">Predicate<String> predicate = TextUtils::isEmpty;</div></pre></td></tr></table></figure>
<p>方法引用就是:<strong>当逻辑实现只有一句,且调用了已存在的方法进行处理(静态方法,this,super的方法也包括在内)时,对函数接口形式的lambda的进一步简化</strong>。传入方法的参数就是原接口的参数。</p>
<p>接下来总结三种方法引用的形式:</p>
<ol>
<li><p>object::instanceMethod</p>
<p>直接调用任意对象的实例方法,如<code>obj::equals</code> 代表调用了obj这个对象的equals方法与接口方法参数比较是否相等,效果等同于<code>obj.equals(t)</code>。当前类的方法可以直接调用<code>this::method</code>,父类方法同理。</p>
</li>
<li><p>ClassName::staticMethod</p>
<p>直接调用某类的静态方法,并将接口方法参数传入,如上述<code>TextUtils::isEmpty</code> 等同于<code>TextUtils.isEmpty(s)</code>。</p>
</li>
</ol>
<ol>
<li><p>ClassName::instanceMethod</p>
<p>较为特殊,将接口方法参数列表的第一个参数作为方法调用者,其余参数作为方法参数。由于此类接口较少,故选择Java提供的BiFunctin接口作为示例,该接口接受一个T1类,T2类对象,并返回R对象:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line"><span class="class"><span class="keyword">interface</span> <span class="title">BiFunction</span><<span class="title">T1</span>, <span class="title">T2</span>, <span class="title">R</span>> </span>{</div><div class="line"> <span class="function">R <span class="title">apply</span><span class="params">(T1 t1, T2 t2)</span></span>;</div><div class="line">}</div><div class="line">BiFunction<String,String,Boolean> biFunction=</div><div class="line"> <span class="keyword">new</span> BiFunction<String, String, Boolean>() {</div><div class="line"> <span class="meta">@Override</span> <span class="function"><span class="keyword">public</span> Boolean <span class="title">apply</span><span class="params">(String s1, String s2)</span></span>{</div><div class="line"> <span class="keyword">return</span> s1.equals(s2);</div><div class="line"> }</div><div class="line"> };</div><div class="line"><span class="comment">// ClassName 为接口方法的第一个参数的类名,同时利用接口方法的第一个参数作为方法调用者,其余参数作为方法参数,实现 s1.equals(s2);</span></div><div class="line">BiFunction<String,String,Boolean> biFunction= String::equals;</div></pre></td></tr></table></figure>
</li>
</ol>
<h3 id="1-3-构造器引用"><a href="#1-3-构造器引用" class="headerlink" title="1.3 构造器引用"></a>1.3 构造器引用</h3><p>Lambda 表达式的第三种形式,其实和方法引用十分相似,只不过方法名替换为 new 。其格式为 <code>ClassName :: new</code>。这时编译器会通过上下文判断传入的参数的类型、顺序、数量等,来调用适合的构造器,返回对象。</p>
<h2 id="2-一点玄学"><a href="#2-一点玄学" class="headerlink" title="2. 一点玄学"></a>2. 一点玄学</h2><h3 id="2-1-this关键字"><a href="#2-1-this关键字" class="headerlink" title="2.1 this关键字"></a>2.1 this关键字</h3><p>在匿名内部类中,this 关键字指向的是匿名类本身的对象,而在 lambda 中,this 指向的是 lambda 表达式的外部类。</p>
<h3 id="2-2-方法数差异"><a href="#2-2-方法数差异" class="headerlink" title="2.2 方法数差异"></a>2.2 方法数差异</h3><p>前 Android Studio 对 Java 8 新特性编译时采用脱糖(desugar)处理,lambda 表达式经过编译器编译后,每一个 lambda 表达式都会增加 1~2 个方法数。而 Android 应用的方法数不能超过 65536 个。虽然一般应用较难触发,但仍需注意。</p>
]]></content>
<summary type="html">
<p>Lambda语法在Android中的应用</p>
</summary>
<category term="Android" scheme="https://github.com/iBotasky/categories/Android/"/>
<category term="Lambda" scheme="https://github.com/iBotasky/categories/Android/Lambda/"/>
<category term="Android" scheme="https://github.com/iBotasky/tags/Android/"/>
<category term="Lambda" scheme="https://github.com/iBotasky/tags/Lambda/"/>
</entry>
<entry>
<title>Android 蓝牙</title>
<link href="https://github.com/iBotasky/2017/04/17/Android-%E8%93%9D%E7%89%99/"/>
<id>https://github.com/iBotasky/2017/04/17/Android-蓝牙/</id>
<published>2017-04-17T06:34:53.000Z</published>
<updated>2017-08-27T09:14:28.000Z</updated>
<content type="html"><![CDATA[<p>关于Android下BLE(Bluetooth Low Energy)开发的一些积累<br><a id="more"></a></p>
<h2 id="1-创建BLE基本步骤"><a href="#1-创建BLE基本步骤" class="headerlink" title="1.创建BLE基本步骤"></a>1.创建BLE基本步骤</h2><h2 id="1-1获取BluethoothAdapter"><a href="#1-1获取BluethoothAdapter" class="headerlink" title="1.1获取BluethoothAdapter"></a>1.1获取BluethoothAdapter</h2><p>所有的蓝牙活动都需要蓝牙适配器。BluetoothAdapter代表设备本身的蓝牙适配器(蓝牙无线)。整个系统只有一个蓝牙适配器,而且你的app使用它与系统交互。下面的代码片段显示了如何得到适配器。注意该方法使用getSystemService()返回BluetoothManager,然后将其用于获取适配器的一个实例。<strong>Android 4.3(API 18)引入BluetoothManager。</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">private</span> BluetoothAdapter mBluetoothAdapter;</div><div class="line">...</div><div class="line"><span class="comment">// Initializes Bluetooth adapter.</span></div><div class="line"><span class="keyword">final</span> BluetoothManager bluetoothManager =</div><div class="line"> (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);</div><div class="line">mBluetoothAdapter = bluetoothManager.getAdapter();</div></pre></td></tr></table></figure>
<h2 id="1-2-开启蓝牙"><a href="#1-2-开启蓝牙" class="headerlink" title="1.2 开启蓝牙"></a>1.2 开启蓝牙</h2><p>接下来,你需要确认蓝牙是否开启。调用isEnabled())去检测蓝牙当前是否开启。如果该方法返回false,蓝牙被禁用。下面的代码检查蓝牙是否开启,如果没有开启,将显示错误提示用户去设置开启蓝牙。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// 确保蓝牙在设备上可以开启</span></div><div class="line"><span class="keyword">if</span> (mBluetoothAdapter == <span class="keyword">null</span> || !mBluetoothAdapter.isEnabled()) {</div><div class="line"> Intent enableBtIntent = <span class="keyword">new</span> Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);</div><div class="line"> startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);</div><div class="line">}</div></pre></td></tr></table></figure>
<h2 id="1-3-发现设备"><a href="#1-3-发现设备" class="headerlink" title="1.3 发现设备"></a>1.3 发现设备</h2><p>为了发现BLE设备,使用startLeScan()方法。这个方法需要一个参数BluetoothAdapter.LeScanCallback。你必须实现它的回调函数,那就是返回的扫描结果。因为扫描非常消耗电量,你应当遵守以下准则:</p>
<p>只要找到所需的设备,停止扫描。<br>不要在循环里扫描,并且对扫描设置时间限制。以前可用的设备可能已经移出范围,继续扫描消耗电池电量。<br>下面代码显示了如何开始和停止一个扫描:</p>
<blockquote>
<p>JellyBean —API18及以上:直接用BlueAdapter.startLeScan(), 这里有个坑,传入的阐述UUID… serviceUUIDs传入这个参数搜索的BLEDevice都要满足这些UUIDS才能被搜到,这些UUID不是或关系,而是与关系。</p>
<p>Lollipop —API21及以上:用BluetoothAdapter获取到:BluetoothAdapter.getBluetoothLeScanner(),获取到一个BluetoothLeScanner对象,在用这个调用<code>startScan(List<ScanFilter> filter , ScanSetting setting, ScanCallback scancallbacn)</code>来查找设备。这里的fileter就是或关系了。可以把UUID转成ScanFilter。</p>
</blockquote>
<h2 id="1-4-连接到GATT服务端"><a href="#1-4-连接到GATT服务端" class="headerlink" title="1.4 连接到GATT服务端"></a>1.4 连接到GATT服务端</h2><p>与一个BLE设备交互的第一步就是连接它——更具体的,连接到BLE设备上的GATT服务端。为了连接到BLE设备上的GATT服务端,需要使用connectGatt( )方法。这个方法需要三个参数:一个Context对象,自动连接(boolean值,表示只要BLE设备可用是否自动连接到它),和BluetoothGattCallback调用。</p>
<p><code>mBluetoothGatt = device.connectGatt(this, false, mGattCallback);</code><br>连接到GATT服务端时,由BLE设备做主机,并返回一个BluetoothGatt实例,然后你可以使用这个实例来进行GATT客户端操作。请求方(Android app)是GATT客户端。BluetoothGattCallback用于传递结果给用户,例如连接状态,以及任何进一步GATT客户端操作。</p>
<h2 id="1-5-读取BLE变量"><a href="#1-5-读取BLE变量" class="headerlink" title="1.5 读取BLE变量"></a>1.5 读取BLE变量</h2><p>你的android app完成与GATT服务端连接和发现services后,就可以读写支持的属性。例如,这段代码通过服务端的services和 characteristics迭代,并且将它们显示在UI上。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">DeviceControlActivity</span> <span class="keyword">extends</span> <span class="title">Activity</span> </span>{</div><div class="line"> ...</div><div class="line"> <span class="comment">// Demonstrates how to iterate through the supported GATT</span></div><div class="line"> <span class="comment">// Services/Characteristics.</span></div><div class="line"> <span class="comment">// In this sample, we populate the data structure that is bound to the</span></div><div class="line"> <span class="comment">// ExpandableListView on the UI.</span></div><div class="line"> <span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">displayGattServices</span><span class="params">(List<BluetoothGattService> gattServices)</span> </span>{</div><div class="line"> <span class="keyword">if</span> (gattServices == <span class="keyword">null</span>) <span class="keyword">return</span>;</div><div class="line"> String uuid = <span class="keyword">null</span>;</div><div class="line"> String unknownServiceString = getResources().</div><div class="line"> getString(R.string.unknown_service);</div><div class="line"> String unknownCharaString = getResources().</div><div class="line"> getString(R.string.unknown_characteristic);</div><div class="line"> ArrayList<HashMap<String, String>> gattServiceData =</div><div class="line"> <span class="keyword">new</span> ArrayList<HashMap<String, String>>();</div><div class="line"> ArrayList<ArrayList<HashMap<String, String>>> gattCharacteristicData</div><div class="line"> = <span class="keyword">new</span> ArrayList<ArrayList<HashMap<String, String>>>();</div><div class="line"> mGattCharacteristics =</div><div class="line"> <span class="keyword">new</span> ArrayList<ArrayList<BluetoothGattCharacteristic>>();</div><div class="line"></div><div class="line"> <span class="comment">// Loops through available GATT Services.</span></div><div class="line"> <span class="keyword">for</span> (BluetoothGattService gattService : gattServices) {</div><div class="line"> HashMap<String, String> currentServiceData =</div><div class="line"> <span class="keyword">new</span> HashMap<String, String>();</div><div class="line"> uuid = gattService.getUuid().toString();</div><div class="line"> currentServiceData.put(</div><div class="line"> LIST_NAME, SampleGattAttributes.</div><div class="line"> lookup(uuid, unknownServiceString));</div><div class="line"> currentServiceData.put(LIST_UUID, uuid);</div><div class="line"> gattServiceData.add(currentServiceData);</div><div class="line"></div><div class="line"> ArrayList<HashMap<String, String>> gattCharacteristicGroupData =</div><div class="line"> <span class="keyword">new</span> ArrayList<HashMap<String, String>>();</div><div class="line"> List<BluetoothGattCharacteristic> gattCharacteristics =</div><div class="line"> gattService.getCharacteristics();</div><div class="line"> ArrayList<BluetoothGattCharacteristic> charas =</div><div class="line"> <span class="keyword">new</span> ArrayList<BluetoothGattCharacteristic>();</div><div class="line"> <span class="comment">// Loops through available Characteristics.</span></div><div class="line"> <span class="keyword">for</span> (BluetoothGattCharacteristic gattCharacteristic :</div><div class="line"> gattCharacteristics) {</div><div class="line"> charas.add(gattCharacteristic);</div><div class="line"> HashMap<String, String> currentCharaData =</div><div class="line"> <span class="keyword">new</span> HashMap<String, String>();</div><div class="line"> uuid = gattCharacteristic.getUuid().toString();</div><div class="line"> currentCharaData.put(</div><div class="line"> LIST_NAME, SampleGattAttributes.lookup(uuid,</div><div class="line"> unknownCharaString));</div><div class="line"> currentCharaData.put(LIST_UUID, uuid);</div><div class="line"> gattCharacteristicGroupData.add(currentCharaData);</div><div class="line"> }</div><div class="line"> mGattCharacteristics.add(charas);</div><div class="line"> gattCharacteristicData.add(gattCharacteristicGroupData);</div><div class="line"> }</div><div class="line"> ...</div><div class="line"> }</div><div class="line">...</div><div class="line">}</div></pre></td></tr></table></figure>
<h2 id="1-6开启通知"><a href="#1-6开启通知" class="headerlink" title="1.6开启通知"></a>1.6开启通知</h2><p>当设备上的特性改变时会通知BLE应用程序。这段代码显示了如何使用setCharacteristicNotification( )给一个特性设置通知。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">private</span> BluetoothGatt mBluetoothGatt;</div><div class="line">BluetoothGattCharacteristic characteristic;</div><div class="line"><span class="keyword">boolean</span> enabled;</div><div class="line">...</div><div class="line">mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);</div><div class="line">...</div><div class="line">BluetoothGattDescriptor descriptor = characteristic.getDescriptor(</div><div class="line"> UUID.fromString(SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG));</div><div class="line">descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);</div><div class="line">mBluetoothGatt.writeDescriptor(descriptor);</div></pre></td></tr></table></figure>
<h2 id="1-7关闭App客户端"><a href="#1-7关闭App客户端" class="headerlink" title="1.7关闭App客户端"></a>1.7关闭App客户端</h2><p>当你的app完成BLE设备的使用后,应该调用close( )),系统可以合理释放占用资源。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">close</span><span class="params">()</span> </span>{</div><div class="line"> <span class="keyword">if</span> (mBluetoothGatt == <span class="keyword">null</span>) {</div><div class="line"> <span class="keyword">return</span>;</div><div class="line"> }</div><div class="line"> mBluetoothGatt.close();</div><div class="line"> mBluetoothGatt = <span class="keyword">null</span>;</div><div class="line">}</div></pre></td></tr></table></figure>
<p> </p>
]]></content>
<summary type="html">
<p>关于Android下BLE(Bluetooth Low Energy)开发的一些积累<br>
</summary>
<category term="Android" scheme="https://github.com/iBotasky/categories/Android/"/>
<category term="BLE" scheme="https://github.com/iBotasky/categories/Android/BLE/"/>
<category term="Android" scheme="https://github.com/iBotasky/tags/Android/"/>
<category term="BLE" scheme="https://github.com/iBotasky/tags/BLE/"/>
</entry>
<entry>
<title>Android权限之shareUserId</title>
<link href="https://github.com/iBotasky/2017/04/07/Android%E6%9D%83%E9%99%90%E4%B9%8BshareUserId/"/>
<id>https://github.com/iBotasky/2017/04/07/Android权限之shareUserId/</id>
<published>2017-04-07T02:27:33.000Z</published>
<updated>2017-08-27T09:16:49.000Z</updated>
<content type="html"><![CDATA[<p>项目中看到过shareUserId,了解了这个配置特性</p>
<a id="more"></a>
<h2 id="1-关于shareUserId"><a href="#1-关于shareUserId" class="headerlink" title="1.关于shareUserId"></a>1.关于shareUserId</h2><p>每一个APK在安装到设备上的时候,设备都会为其分配一个单独的空间,mainfest中的userid就是对应一个Linux用户都会被分配到一个属于自己的统一的Linux用户ID,并且为他创建一个沙箱,以防止影响其他程序。用户ID在应用程序安装到设备中时被分配。</p>
<p>通过在AndroidMainfest.xml设置<code>android:shareUserId</code>可以让拥有同一个Userid的多个应用运行在统一进程,或者不同进程。<strong>多个相同UserId的应用可以互相随意访问数据。</strong></p>
<h2 id="2-共享UID步骤"><a href="#2-共享UID步骤" class="headerlink" title="2.共享UID步骤"></a>2.共享UID步骤</h2><blockquote>
<p>1.在AndroidMainfest.xml设置相同的<code>android:shareUserId</code></p>
<p>2.在Android.mk中增加LOCAL_CERTIFICATE的定义。</p>
</blockquote>
<p>如果增加了上面的属性但没有定义与之对应的LOCAL_CERTIFICATE的话,APK是安装不上去的。提示错误是:Package com.test.MyTest has no signatures that match those in shared user android.uid.system; ignoring!也就是说,仅有相同签名和相同sharedUserID标签的两个应用程序签名都会被分配相同的用户ID。例如所有和media/download相关的APK都使用android.media作为sharedUserId的话,那么它们必须有相同的签名media。</p>
<blockquote>
<p>3.把apk的源码放到package/apps/目录下,用mm进行编译</p>
</blockquote>
<h2 id="3-使用shareUserId-”android-uid-system“的好处"><a href="#3-使用shareUserId-”android-uid-system“的好处" class="headerlink" title="3.使用shareUserId=”android.uid.system“的好处"></a>3.使用shareUserId=”android.uid.system“的好处</h2><p>提升app的优先级,内存不足少被杀</p>
]]></content>
<summary type="html">
<p>项目中看到过shareUserId,了解了这个配置特性</p>
</summary>
<category term="Android" scheme="https://github.com/iBotasky/categories/Android/"/>
<category term="Android" scheme="https://github.com/iBotasky/tags/Android/"/>
</entry>
<entry>
<title>Android消息机制</title>
<link href="https://github.com/iBotasky/2017/04/06/Android%E6%B6%88%E6%81%AF%E6%9C%BA%E5%88%B6/"/>
<id>https://github.com/iBotasky/2017/04/06/Android消息机制/</id>
<published>2017-04-06T01:55:13.000Z</published>
<updated>2017-08-27T09:17:07.000Z</updated>
<content type="html"><![CDATA[<p>关于Android消息机制的源码分析</p>
<a id="more"></a>
<h2 id="1-应用程序入口分析"><a href="#1-应用程序入口分析" class="headerlink" title="1.应用程序入口分析"></a>1.应用程序入口分析</h2><p>应用程序入口是在<code>ActivityThread</code>类里<code>main</code>方法,(当应用启动后,底层通过C/C++调用main方法)。</p>
<p>核心代码:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>{</div><div class="line"> Environment.initForCurrentUser();</div><div class="line"> EventLogger.setReporter(<span class="keyword">new</span> EventLoggingReporter());</div><div class="line"> Looper.prepareMainLooper();</div><div class="line"> ActivityThread thread = <span class="keyword">new</span> ActivityThread();</div><div class="line"> thread.attach(<span class="keyword">false</span>);</div><div class="line"> <span class="keyword">if</span> (sMainThreadHandler == <span class="keyword">null</span>) {</div><div class="line"> sMainThreadHandler = thread.getHandler();</div><div class="line"> }</div><div class="line"> Looper.loop();</div><div class="line"> }</div></pre></td></tr></table></figure>
<p>1.1 初始化了Environment对象,然后创建了Lopper,然后开始消息循环。如果程序没有死循环,执行完main函数就会立马退出。之所以App可以一直运行是因为<code>Looper.loop()</code>是一个死循环。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">loop</span><span class="params">()</span> </span>{</div><div class="line"> <span class="keyword">for</span> (;;) {</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
<p>这里用<code>for(;;)</code>而不是<code>while(true)</code>是为了防止一些人通过黑科技修改这个标志位(通过反射机制)(这里不是很懂)!</p>
<p><strong>在非主线程里面我们也可以创建一个Handler,但是需要我们主动去为当前的子线程绑定一个Looper,并且启动消息循环</strong></p>
<p>Looper有两个核心方法:prepare()与loop()。通过Looper、Handle、Message、MessageQueue等组成了Android的消息处理机制。</p>
<h2 id="2-为什么需要这样一个消息机制"><a href="#2-为什么需要这样一个消息机制" class="headerlink" title="2.为什么需要这样一个消息机制"></a>2.为什么需要这样一个消息机制</h2><h2 id="2-1-不阻塞主线程"><a href="#2-1-不阻塞主线程" class="headerlink" title="2.1 不阻塞主线程"></a>2.1 不阻塞主线程</h2><p>Android应用启动时,会创主线程, 负责与UI组件(widget,view)进行交互, 比如控制UI界面显示,更新等。这种单线程模型导致运行性大大降低,只能处理简单、短暂的操作。过重的任务比如下载访问数据库等都会导致ANR。<strong>Android大部分耗时操作都应该放到子线程,不要在主线程做操作</strong></p>
<h2 id="2-2-并发程序的有序性"><a href="#2-2-并发程序的有序性" class="headerlink" title="2.2 并发程序的有序性"></a>2.2 并发程序的有序性</h2><p>单线程模型的UI主线程也是不安全的,会造成不可确定的结果。</p>
<blockquote>
<p>线程不安全简单理解为:多线程访问资源时,有可能出现多个线程先后更改数据造成数据不一致。比如,A工作线程(也称为子线程)访问某个公共UI资源,B工作线程在某个时候也访问了该公共资源,当B线程正访问时,公共资源的属性已经被A改变了,这样B得到的结果不是所需要的的,造成了数据不一致的混乱情况。</p>
<p>线程安全简单理解为:当一个线程访问功能资源时,对该资源进程了保护,比如加了锁机制,当前线程在没有访问结束释放锁之前,其他线程只能等待直到释放锁才能访问,这样的线程就是安全的。</p>
</blockquote>
<p> <strong>Android只允许主线程更新UI界面,子线程处理后的结果无法和主线程交互,即无法直接访问主线程,这就要用到Handler机制来解决此问题。基于Handler机制,在子线程先获得Handler对象,该对象将数据发送到主线程消息队列,主线程通过Loop循环获取消息交给Handler处理。</strong></p>
<p>有了消息机制,我们可以发送消息,然后Looper把消息发给主线程,然后就可以执行了。</p>
<p>消息包括:</p>
<blockquote>
<p>我们自己的操作消息,即客户端的Handler</p>
<p>操作系统的操作消息,系统的Handler,例如来电话跳出界面,就需要。</p>
</blockquote>
<p>先分析系统的Handler,再去深入理解消息机制里面各个组件</p>
<h2 id="3-系统的Handler"><a href="#3-系统的Handler" class="headerlink" title="3.系统的Handler"></a>3.系统的Handler</h2><p>ActivityThread的成员变量有这样一个H(继承自Handler),这个就是系统的Handler。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">final</span> H mH = <span class="keyword">new</span> H();</div></pre></td></tr></table></figure>
<p>回顾一下ActivityThread的初始化,在main方法中<code>ActivityThread thread = new ActivityThread();</code>在new的时候就已经完成了初始化成员变量,单例饿加载。</p>
<p>在H中定义了大量的常量,然后用case做操作。</p>
<p>从系统的Handler中,在handlerMessage我们可以看到四大组件的生命周期操作,创建,销毁,切换等。跨进程通信及Application进程的销毁。</p>
<p>比如说我们有一个 应用程序A 通过 Binder 去跨进程启动另外一个 应用程序B 的 Service(或者同一个应用程序中不同进程的Service),如图:AMS是四大组件的生命周期的一个比较重要的类,IPC机制会涉及</p>
<p><img src="https://ooo.0o0.ooo/2017/04/06/58e5affdc7e6c.png" alt="58e5affdc7e6c.png"></p>
<p>最后AMS接收到消息后,发送消息到MessageQueue里面,最后由系统的Handler处理启动Service的操作:</p>
<p><img src="https://ooo.0o0.ooo/2017/04/06/58e5b282509cd.png" alt="58e5b282509cd.png"></p>
<p>在handlerCreateService()里通过反射的方式去newInstance(),并且毁掉了Service的Oncreate方法。</p>
<p><img src="https://ooo.0o0.ooo/2017/04/06/58e5b2de61799.png" alt="58e5b2de61799.png"></p>
<p>又例如我们可以通过发SUICIDE消息可以自杀,这样来退出应用程序。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">case</span> SUICIDE:</div><div class="line"> Process.killProcess(Process.myPid());</div><div class="line"> <span class="keyword">break</span>;</div></pre></td></tr></table></figure>
<p><strong>应用程序退出</strong></p>
<p>实际上我们要退出应用程序的话,就是让主线程结束,换句话说就是要让 Looper 的循环结束。这里是直接结束 Looper 循环,因此我们四大组件的生命周期方法可能就不会执行了,因为四大组件的生命周期方法就是通过 Handler 去处理的,Looper 循环都没有了,四大组件还玩毛线!因此我们平常写程序的时候就要注意了,onDestroy 方法是不一定能够回调的。</p>
<p><img src="https://ooo.0o0.ooo/2017/04/06/58e5b38e7a18e.png" alt="58e5b38e7a18e.png"></p>
<p>这里实际上是调用了 MessageQueue 的 quit,清空所有 Message。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">quit</span><span class="params">()</span> </span>{</div><div class="line"> mQueue.quit(<span class="keyword">false</span>);</div><div class="line">}</div></pre></td></tr></table></figure>
<h2 id="4-消息机制的分析"><a href="#4-消息机制的分析" class="headerlink" title="4.消息机制的分析"></a>4.消息机制的分析</h2><h3 id="4-1-消息对象Message的分析"><a href="#4-1-消息对象Message的分析" class="headerlink" title="4.1 消息对象Message的分析"></a>4.1 消息对象Message的分析</h3><p>提到消息机制,在MessageQueue里面存在的就是我们Message对象。</p>
<p><img src="https://ooo.0o0.ooo/2017/04/06/58e5b4e08f7e6.png" alt="58e5b4e08f7e6.png"></p>
<p>Message 里面有一些我们常见的参数,arg1 arg2 obj callback when 等等。这里要提一下的就是这个 target 对象,这个对象就是发送这个消息的 Handler对象,最终这条消息也是通过这个 Handler 去处理掉的。</p>
<h3 id="4-2-消息的循环过程分析"><a href="#4-2-消息的循环过程分析" class="headerlink" title="4.2 消息的循环过程分析"></a>4.2 消息的循环过程分析</h3><p>1.拿到Looper()对象(me),如果当前线程没有Looper,那么就抛出异常。这就是为什么在子线程里面创建Handler如果不手动创建启动Looper会报错的原因。</p>
<p>2.拿到Looper的成员变量MessageQueue,在MessageQueue里面不断地去区消息,关于MessageQueue的next用法如下:</p>
<p>这里可以看到消息的取出用到了一些native方法,这样做是为了获得更高的效率,消息的去取出并不是直接就从队列的头部取出的,而是根据了消息的when时间参数有关的,因为我们可以发送延时消息、也可以发送一个指定时间点的消息。因此这个函数有点复杂,我们点到为止即可。</p>
<p><img src="https://ooo.0o0.ooo/2017/04/06/58e5ba6c7b791.png" alt="58e5ba6c7b791.png"></p>
<p><img src="https://ooo.0o0.ooo/2017/04/06/58e5baf15d1d6.png" alt="58e5baf15d1d6.png"></p>
<p><strong>3、</strong>继续分析 loop方法:如果已经没有消息了,那么就可以退出循环,那么整个应用程序就退出了。什么情况下会发生呢?还记得我们分析应用退出吗?</p>
<p>在 系统Handler 收到 EXIT_APPLICATION 消息的时候,就会调用 Looper 的 quit方法:</p>
<p><img src="https://ooo.0o0.ooo/2017/04/06/58e5bacc9d2ee.png" alt="58e5bacc9d2ee.png"></p>
]]></content>
<summary type="html">
<p>关于Android消息机制的源码分析</p>
</summary>
<category term="Android进阶" scheme="https://github.com/iBotasky/categories/Android%E8%BF%9B%E9%98%B6/"/>
<category term="Android进阶" scheme="https://github.com/iBotasky/tags/Android%E8%BF%9B%E9%98%B6/"/>
</entry>
<entry>
<title>RxJava遇到的问题整理</title>
<link href="https://github.com/iBotasky/2017/03/07/RxJava%E9%81%87%E5%88%B0%E7%9A%84%E9%97%AE%E9%A2%98%E6%95%B4%E7%90%86/"/>
<id>https://github.com/iBotasky/2017/03/07/RxJava遇到的问题整理/</id>
<published>2017-03-07T07:27:37.000Z</published>
<updated>2017-08-27T09:21:08.000Z</updated>
<content type="html"><![CDATA[<p>编程中遇到的RxJava的错<br><a id="more"></a></p>
<h2 id="1-Subject与toList-操作符"><a href="#1-Subject与toList-操作符" class="headerlink" title="1.Subject与toList()操作符"></a>1.Subject与toList()操作符</h2><p>一个项目钟一个页面用<code>PublistEvent</code>发送消息(消息的内容是一个CalendarDay日期值),通知另一个页面,另一个页面在去数据库取数据,原来的代码是这样,但是打过log后,<code>toList()</code>后面的数据都没出来。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line">PublishEvent.SELECTION_DATE</div><div class="line"> .flatMap(calendarDay -> mPresenter.getHistoriesByDay(year, month, day)</div><div class="line"> .flatMap(histories -> Observable.from(histories)</div><div class="line"> .map(history -> <span class="keyword">new</span> MineTrainDayItem(history))</div><div class="line"> .toList() </div><div class="line"> .compose(bindToLifecycle())</div><div class="line"> .compose(SchedulersCompat.applyComputationSchedulers())</div><div class="line"> .subscribe(mineTrainDayItems -> {</div><div class="line"> removeRangeItem(<span class="number">0</span>, getItemCount());</div><div class="line"> addItem(mineTrainDayItems);</div><div class="line"> });</div></pre></td></tr></table></figure>
<p>Goole一下,找到这个<a href="https://github.com/ReactiveX/RxJava/issues/3716">PublishSubject</a>, 大意是,使用<code>PublishSubject</code>后调用<code>toList()操作符</code> 要用<code>onCompelete</code>才能走入其他输出。即<code>onList()</code>操作符是要在<code>Observable.onComplete</code> 之后才能走,不然会一直卡住。</p>
<p>修改成下面的代码:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line">ublishEvent.SELECTION_DATE</div><div class="line"> .flatMap(calendarDay -> mPresenter.getHistoriesByDay(year, month, day)</div><div class="line"> .flatMap(histories -> Observable.from(histories))</div><div class="line"> .map(history -> <span class="keyword">new</span> MineTrainDayItem(history))</div><div class="line"> .toList())<span class="comment">//放在内层做聚合</span></div><div class="line"> .compose(bindToLifecycle())</div><div class="line"> .compose(SchedulersCompat.applyComputationSchedulers())</div><div class="line"> .subscribe(mineTrainDayItems -> {</div><div class="line"> removeRangeItem(<span class="number">0</span>, getItemCount());</div><div class="line"> addItem(mineTrainDayItems);</div><div class="line"> });</div></pre></td></tr></table></figure>
<p>把<code>toList()</code>放在最内层的Observable里面去做数据聚合,最外层就不用等待<code>onComplete()</code>.这样就不会再外层的<code>PublishSubject</code>的Observable卡住。</p>
<hr>
<h2 id="2-Transform-与compose-操作符"><a href="#2-Transform-与compose-操作符" class="headerlink" title="2.Transform 与compose()操作符"></a>2.Transform 与<code>compose()</code>操作符</h2><p>看到Megear项目中很多代码都用到了<code>compose()</code>操作符,研究了一下<code>compose()</code>操作符的用法。</p>
<p>就目前来说compose主要是用来对一个Observable做整个变换,例如一个网络请求的过程,请求及数据处理都应该放在一个新线程中,而展示数据,要放到<code>MainThread</code>中,一般而言就平常做法就是<code>subscribeOn()</code>和<code>observeOn()</code>,但是如果考虑到这样的请求有很多个,就要考虑到复用问题,不能每次都对每一个<code>Observable</code>对象都做一次<code>subscribeOn()</code>和<code>observeOn()</code>操作,这样就不符合一个规范。</p>
<h3 id="2-1Transform"><a href="#2-1Transform" class="headerlink" title="2.1Transform"></a>2.1Transform</h3><p><code>Transformer</code>实际上就是一个<code>Func1<Observable<T>, Observable<R>></code>,换言之就是:可以通过它将一种类型的<code>Observable</code>转换成另一种类型的<code>Observable</code>,和调用一系列的内联操作符是一模一样的。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//一般模式 </span></div><div class="line"><T> <span class="function">Transformer<T, T> <span class="title">applySchedulers</span><span class="params">()</span> </span>{</div><div class="line"> <span class="keyword">return</span> <span class="keyword">new</span> Transformer<T, T>() {</div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> Observable<T> <span class="title">call</span><span class="params">(Observable<T> observable)</span> </span>{</div><div class="line"> <span class="keyword">return</span> observable.subscribeOn(Schedulers.io())</div><div class="line"> .observeOn(AndroidSchedulers.mainThread());</div><div class="line"> }</div><div class="line"> };</div><div class="line">}</div><div class="line"><span class="comment">//lambda模式</span></div><div class="line"><T> <span class="function">Transformer<T, T> <span class="title">applySchedulers</span><span class="params">()</span> </span>{ </div><div class="line"><span class="keyword">return</span> observable -> observable.subscribeOn(Schedulers.io())</div><div class="line"> .observeOn(AndroidSchedulers.mainThread());</div><div class="line">}</div></pre></td></tr></table></figure>
<p>与<code>compose()</code>操作符一起用,就可以做到切换线程:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line">Observable.from(someSource)</div><div class="line"> .map(<span class="keyword">new</span> Func1<Data, Data>() {</div><div class="line"> <span class="meta">@Override</span> <span class="function"><span class="keyword">public</span> Data <span class="title">call</span><span class="params">(Data data)</span> </span>{</div><div class="line"> <span class="keyword">return</span> manipulate(data);</div><div class="line"> }</div><div class="line"> })</div><div class="line"> .compose(<span class="keyword">this</span>.<YourType>applySchedulers())</div><div class="line"> .subscribe(<span class="keyword">new</span> Action1<Data>() {</div><div class="line"> <span class="meta">@Override</span> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">call</span><span class="params">(Data data)</span> </span>{</div><div class="line"> doSomething(data);</div><div class="line"> }</div><div class="line"> });</div></pre></td></tr></table></figure>
<h3 id="2-2重用Transform"><a href="#2-2重用Transform" class="headerlink" title="2.2重用Transform"></a>2.2重用Transform</h3><p>上面代码每次都会<code>new</code>一个Transform,依然做不到重用,你可以创建一个实例化版本,节省不必要的实例化对象。毕竟,Transformers关乎着代码重用。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">static</span> <span class="keyword">final</span> Observable.Transformer schedulersTransformer = <span class="keyword">new</span> Observable.Transformer() {</div><div class="line"> <span class="meta">@Override</span> <span class="function"><span class="keyword">public</span> Object <span class="title">call</span><span class="params">(Object observable)</span> </span>{</div><div class="line"> <span class="keyword">return</span> ((Observable) observable).subscribeOn(Schedulers.newThread())</div><div class="line"> .observeOn(AndroidSchedulers.mainThread());</div><div class="line"> }</div><div class="line">};</div><div class="line"></div><div class="line"> <T> Observable.<span class="function">Transformer<T, T> <span class="title">applySchedulers</span><span class="params">()</span> </span>{</div><div class="line"> <span class="keyword">return</span> (Observable.Transformer<T, T>) schedulersTransformer;</div><div class="line">}</div></pre></td></tr></table></figure>
]]></content>
<summary type="html">
<p>编程中遇到的RxJava的错<br>
</summary>
<category term="Android" scheme="https://github.com/iBotasky/categories/Android/"/>
<category term="RxJava" scheme="https://github.com/iBotasky/categories/Android/RxJava/"/>
<category term="Android" scheme="https://github.com/iBotasky/tags/Android/"/>
<category term="RxJava" scheme="https://github.com/iBotasky/tags/RxJava/"/>
</entry>
<entry>
<title>关于集成ShareSDK</title>
<link href="https://github.com/iBotasky/2017/02/24/%E5%85%B3%E4%BA%8E%E9%9B%86%E6%88%90ShareSDK/"/>
<id>https://github.com/iBotasky/2017/02/24/关于集成ShareSDK/</id>
<published>2017-02-24T07:09:19.000Z</published>
<updated>2017-08-27T09:21:48.000Z</updated>
<content type="html"><![CDATA[<p>整理项目中集成ShareSDK遇到的问题</p>
<a id="more"></a>
<h3 id="1-微信"><a href="#1-微信" class="headerlink" title="1.微信"></a>1.微信</h3><h3 id="1-1官方提供一个wxapi的包,要放在主项目包的下面"><a href="#1-1官方提供一个wxapi的包,要放在主项目包的下面" class="headerlink" title="1.1官方提供一个wxapi的包,要放在主项目包的下面"></a>1.1官方提供一个wxapi的包,要放在主项目包的下面</h3><p>起初为了分离ShareSDK,新建一个ShareSDK的Module,把ShareSDK的东西都放到里面去,包括官方提供的一个wxapi的包,但是这个包要放在主项目下面的包名底下。</p>
<p><img src="http://oktzkaa8p.bkt.clouddn.com/20170224148792056653655.png" alt="20170224148792056653655.png"></p>
<p>包括微信回调的Activity也要写在主项目的<code>AndroidManifest.xml</code>下面</p>
<h2 id="2-微博"><a href="#2-微博" class="headerlink" title="2.微博"></a>2.微博</h2><p>微博的调用客户端认证需要注意的是新浪微博客户端授权是需要用户在开发者平台(网址:<a href="http://open.weibo.com)**申请的应用用过了新浪的审核**。而且要**通过keystore进行签名打包测试**。注意打包所用的**keystore上的md5签名、项目的包名要与新浪开发者平台上填写的签名与包名一致**" target="_blank" rel="external">http://open.weibo.com)**申请的应用用过了新浪的审核**。而且要**通过keystore进行签名打包测试**。注意打包所用的**keystore上的md5签名、项目的包名要与新浪开发者平台上填写的签名与包名一致**</a></p>
<h2 id="3-关于API"><a href="#3-关于API" class="headerlink" title="3.关于API"></a>3.关于API</h2><p>ShareSDK的调用客户端认证有个坑的地方</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//使用SSO授权,通过客户单授权</span></div><div class="line">plat.SSOSetting(<span class="keyword">false</span>);</div></pre></td></tr></table></figure>
<p>false才是调用客户端认证</p>
]]></content>
<summary type="html">
<p>整理项目中集成ShareSDK遇到的问题</p>
</summary>
<category term="Android" scheme="https://github.com/iBotasky/categories/Android/"/>
<category term="Social" scheme="https://github.com/iBotasky/categories/Android/Social/"/>
<category term="Android" scheme="https://github.com/iBotasky/tags/Android/"/>
</entry>
<entry>
<title>Android Studio插件</title>
<link href="https://github.com/iBotasky/2017/02/13/Android-Studio%E6%8F%92%E4%BB%B6/"/>
<id>https://github.com/iBotasky/2017/02/13/Android-Studio插件/</id>
<published>2017-02-13T01:14:00.000Z</published>
<updated>2017-08-27T09:14:14.000Z</updated>
<content type="html"><![CDATA[<p>关于Android Studio上比较好用的插件整理</p>
<a id="more"></a>
<table>
<thead>
<tr>
<th>插件</th>
<th>解释</th>
</tr>
</thead>
<tbody>
<tr>
<td>0.Android ButterKnife Zelezny</td>
<td>ButterKnife快速生成View对象</td>
</tr>
<tr>
<td>1.GsonFormat</td>
<td>Json字符串转成JAVA Bean</td>
</tr>
<tr>
<td>2.Android Parcelable code generator</td>
<td>JavaBean序列化,快速实现Parcelable接口。</td>
</tr>
<tr>
<td>3.Translation</td>
<td>翻译插件</td>
</tr>
<tr>
<td>4.Android Code Generator</td>
<td>根据布局文件快速生成对应的Activity,Fragment,Adapter,Menu</td>
</tr>
<tr>
<td>5.Lifecycle Sorter</td>
<td>Activity/Fragment生命周期排序快捷键Ctrl + alt + K</td>
</tr>
<tr>
<td>6.JsonOnlineViewer</td>
<td>在Android Studio中请求、调试接口</td>
</tr>
</tbody>
</table>
<p><a href="http://www.jianshu.com/p/c76b0d8a642d" target="_blank" rel="external">参考</a></p>
]]></content>
<summary type="html">
<p>关于Android Studio上比较好用的插件整理</p>
</summary>
<category term="Andrioid" scheme="https://github.com/iBotasky/categories/Andrioid/"/>
<category term="Android Studio" scheme="https://github.com/iBotasky/categories/Andrioid/Android-Studio/"/>
<category term="Andrioid" scheme="https://github.com/iBotasky/tags/Andrioid/"/>
<category term="Android Studio" scheme="https://github.com/iBotasky/tags/Android-Studio/"/>
</entry>
<entry>
<title>WebView遇到的用法</title>
<link href="https://github.com/iBotasky/2017/02/12/WebView%E9%81%87%E5%88%B0%E7%9A%84%E7%94%A8%E6%B3%95/"/>
<id>https://github.com/iBotasky/2017/02/12/WebView遇到的用法/</id>
<published>2017-02-12T09:19:46.000Z</published>
<updated>2017-08-27T09:21:24.000Z</updated>
<content type="html"><![CDATA[<p>这里总结一些项目中遇到的WebView的一些用法:)</p>
<a id="more"></a>
<hr>
<h2 id="1-CyberBlack项目中遇到的"><a href="#1-CyberBlack项目中遇到的" class="headerlink" title="1.CyberBlack项目中遇到的"></a>1.CyberBlack项目中遇到的</h2><h3 id="1-1描述:CyberBlack是自己利用空闲时间做的App,里面调用了知乎的API,关于知乎API请看这篇文章:知乎日报API分析-。"><a href="#1-1描述:CyberBlack是自己利用空闲时间做的App,里面调用了知乎的API,关于知乎API请看这篇文章:知乎日报API分析-。" class="headerlink" title="1.1描述:CyberBlack是自己利用空闲时间做的App,里面调用了知乎的API,关于知乎API请看这篇文章:知乎日报API分析 。"></a>1.1描述:CyberBlack是自己利用空闲时间做的App,里面调用了知乎的API,关于知乎API请看这篇文章:<a href="https://github.com/izzyleung/ZhihuDailyPurify/wiki/%E7%9F%A5%E4%B9%8E%E6%97%A5%E6%8A%A5-API-%E5%88%86%E6%9E%90">知乎日报API分析</a> 。</h3><p>项目里面用了<code>http://news-at.zhihu.com/api/4/news/3892357</code>这个接口,里面是拿到了html内容的<code>css</code>文件跟<code>body</code>,然后App端要用WebView做显示。</p>
<h3 id=""><a href="#" class="headerlink" title=""></a><img src="http://oktzkaa8p.bkt.clouddn.com/20170212148689169013360.png" alt="20170212148689169013360.png"></h3><p>对如何显示内容有一点迷惑。</p>
<h3 id="1-2-解决:在网上查看资料找到这篇-知乎日报四-(http-krelve-com-android-127-html)看了一下,用了博主的方法,顺利显示内容:"><a href="#1-2-解决:在网上查看资料找到这篇-知乎日报四-(http-krelve-com-android-127-html)看了一下,用了博主的方法,顺利显示内容:" class="headerlink" title="1.2 解决:在网上查看资料找到这篇[知乎日报四](http://krelve.com/android/127.html)看了一下,用了博主的方法,顺利显示内容:"></a>1.2 解决:在网上查看资料找到这篇[知乎日报四](<a href="http://krelve.com/android/127.html)看了一下,用了博主的方法,顺利显示内容:" target="_blank" rel="external">http://krelve.com/android/127.html)看了一下,用了博主的方法,顺利显示内容:</a></h3><p>做法:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">loadData</span><span class="params">()</span> </span>{</div><div class="line"> HttpHelper httpHelper = <span class="keyword">new</span> HttpHelper();</div><div class="line"> httpHelper.setEnd_points(Urls.ZHI_HU_HOST);</div><div class="line"> httpHelper.getService(ZhiHuDailyApi.class)</div><div class="line"> .getNewsDetail(id)</div><div class="line"> .subscribeOn(Schedulers.newThread())</div><div class="line"> .observeOn(AndroidSchedulers.mainThread())</div><div class="line"> .subscribe(dailyDetailResponse -> {</div><div class="line"> loadView(dailyDetailResponse);</div><div class="line"> }, throwable -> {</div><div class="line"></div><div class="line"> }, () -> {</div><div class="line"></div><div class="line"> });</div><div class="line"> }</div><div class="line"> <span class="comment">//这边是拿到了css路径跟html的body,然后用拼接起来放到html中,最后用webview显示。很简单。</span></div><div class="line"> <span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">loadView</span><span class="params">(DailyDetailResponse dailyDetailResponse)</span> </span>{</div><div class="line"> wvContent.getSettings().setJavaScriptEnabled(<span class="keyword">true</span>);</div><div class="line"> String css = <span class="string">"<link rel=\"stylesheet\" href=\""</span> + dailyDetailResponse.getCss().get(<span class="number">0</span>) + <span class="string">"\" type=\"text/css\">"</span>;</div><div class="line"> String html = <span class="string">"<html><head>"</span> + css + <span class="string">"</head><body>"</span> + dailyDetailResponse.getBody() + <span class="string">"</body></html>"</span>;</div><div class="line"> html = html.replace(<span class="string">"<div class=\"img-place-holder\">"</span>, <span class="string">""</span>);</div><div class="line"> wvContent.loadDataWithBaseURL(<span class="string">"x-data://base"</span>, html, <span class="string">"text/html"</span>, <span class="string">"UTF-8"</span>, <span class="keyword">null</span>);</div><div class="line"> }</div></pre></td></tr></table></figure>
<p>最后用了这个方法调试几次后成功让webview显示出来正确的格式内容。</p>
<hr>
<h2 id="2-Podoon项目的WebView"><a href="#2-Podoon项目的WebView" class="headerlink" title="2.Podoon项目的WebView"></a>2.Podoon项目的WebView</h2><h3 id="2-1描述"><a href="#2-1描述" class="headerlink" title="2.1描述"></a>2.1描述</h3><p>选鞋详细界面需要展示鞋子的详细信息,这个界面是用WebView展示的。但是里面包含了一些<code>js</code>的方法。</p>
<h3 id="2-2用法"><a href="#2-2用法" class="headerlink" title="2.2用法"></a>2.2用法</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div></pre></td><td class="code"><pre><div class="line">mWebView.getSettings().setJavaScriptEnabled(<span class="keyword">true</span>);</div><div class="line"> mWebView.setWebViewClient(<span class="keyword">new</span> WebViewClient() {</div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">shouldOverrideUrlLoading</span><span class="params">(WebView view, String url)</span> </span>{</div><div class="line"> <span class="keyword">return</span> <span class="keyword">true</span>;</div><div class="line"> }</div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onPageStarted</span><span class="params">(WebView view, String url, Bitmap favicon)</span> </span>{</div><div class="line"> <span class="keyword">super</span>.onPageStarted(view, url, favicon);</div><div class="line"> ShoeRecordActivity.<span class="keyword">this</span>.showDialog(<span class="keyword">null</span>, <span class="string">"载入中,请稍后..."</span>);</div><div class="line"> logger.info(<span class="string">"onPageStarted() called with: "</span> + <span class="string">"view = ["</span> + view + <span class="string">"], url = ["</span> + url + <span class="string">"], favicon = ["</span> + favicon + <span class="string">"]"</span>);</div><div class="line"> }</div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onPageFinished</span><span class="params">(WebView view, String url)</span> </span>{</div><div class="line"> <span class="comment">//这里放javaScript代码,webview加载</span></div><div class="line"> String javaScript = <span class="string">"javascript:function annotationData(){"</span> +</div><div class="line"> <span class="string">"var x=document.getElementById(\"accomTotalDistance\"); x.innerHTML="</span> + <span class="string">"'"</span> + dis + <span class="string">"km"</span> + <span class="string">"'"</span> + <span class="string">";"</span> +</div><div class="line"> <span class="string">"var y=document.getElementById(\"accomPace\"); y.innerHTML="</span> + <span class="string">"'"</span> + pace2 + <span class="string">"'"</span> + <span class="string">";"</span> +</div><div class="line"> <span class="string">"var z=document.getElementById(\"accomRecordAccount\"); z.innerHTML="</span> + <span class="string">"'"</span> + record + <span class="string">"'"</span> + <span class="string">";"</span> +</div><div class="line"> <span class="string">"var a=document.getElementById(\"processDiv\"); a.style.width="</span> + <span class="string">"'"</span> + progress + <span class="string">"%"</span> + <span class="string">"'"</span> + <span class="string">";"</span> +</div><div class="line"> <span class="string">"}"</span>;</div><div class="line"> logger.error(<span class="string">"onPageFinished() returned: "</span> + javaScript);</div><div class="line"> mWebView.loadUrl(javaScript);</div><div class="line"> mWebView.loadUrl(<span class="string">"javascript:annotationData()"</span>);</div><div class="line"> <span class="keyword">super</span>.onPageFinished(view, url);</div><div class="line"> <span class="keyword">if</span> (dialog.isShowing() && dialog != <span class="keyword">null</span>) {</div><div class="line"> dialog.cancel();</div><div class="line"> }</div><div class="line"> }</div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onReceivedHttpAuthRequest</span><span class="params">(WebView view, HttpAuthHandler handler, String host, String realm)</span> </span>{</div><div class="line"> <span class="keyword">super</span>.onReceivedHttpAuthRequest(view, handler, host, realm);</div><div class="line"> }</div><div class="line"> });</div><div class="line"> mWebView.loadUrl(mURL);</div></pre></td></tr></table></figure>
]]></content>
<summary type="html">
<p>这里总结一些项目中遇到的WebView的一些用法:)</p>
</summary>
<category term="Android" scheme="https://github.com/iBotasky/categories/Android/"/>
<category term="AndroidView" scheme="https://github.com/iBotasky/categories/Android/AndroidView/"/>
<category term="Android" scheme="https://github.com/iBotasky/tags/Android/"/>
<category term="AndroidView" scheme="https://github.com/iBotasky/tags/AndroidView/"/>
</entry>
<entry>
<title>Mac OS 显示/隐藏文件夹</title>
<link href="https://github.com/iBotasky/2017/02/06/Mac-OS-%E6%98%BE%E7%A4%BA-%E9%9A%90%E8%97%8F%E6%96%87%E4%BB%B6%E5%A4%B9/"/>
<id>https://github.com/iBotasky/2017/02/06/Mac-OS-显示-隐藏文件夹/</id>
<published>2017-02-06T03:56:19.000Z</published>
<updated>2017-08-27T09:20:39.000Z</updated>
<content type="html"><![CDATA[<p>Mac显示/隐藏文件夹<br><a id="more"></a></p>
<p>显示隐藏文件:<br><code>defaults write com.apple.finder AppleShowAllFiles -bool TRUE ; killall Finder</code><br>停止显示隐藏文件:<br><code>defaults write com.apple.finder AppleShowAllFiles -bool FALSE ; killall Finder</code></p>
<p>隐藏一个文件夹:<br><code>chflags hidden 文件绝对路径/ 相对路径</code><br>取消隐藏一个文件夹:<br><code>chflags nohidden 文件绝对路径/ 相对路径</code></p>
<p>注:重启Finder的方法:<br>按住option+command,dock上右键->“Relanch”/“重新开启”。</p>
<p><a href="http://www.howtogeek.com/211496/how-to-hide-files-and-view-hidden-files-on-mac-os-x/" target="_blank" rel="external">参考网址</a></p>
]]></content>
<summary type="html">
<p>Mac显示/隐藏文件夹<br>
</summary>
<category term="Mac" scheme="https://github.com/iBotasky/categories/Mac/"/>
<category term="Mac" scheme="https://github.com/iBotasky/tags/Mac/"/>
</entry>
<entry>
<title>Android进程优先级</title>
<link href="https://github.com/iBotasky/2017/02/04/Android%E8%BF%9B%E7%A8%8B%E4%BC%98%E5%85%88%E7%BA%A7/"/>
<id>https://github.com/iBotasky/2017/02/04/Android进程优先级/</id>
<published>2017-02-04T06:40:37.000Z</published>
<updated>2017-10-15T04:38:27.000Z</updated>
<content type="html"><![CDATA[<p>进程优先级介绍<br><a id="more"></a><br>查看命令当前进程优先级:adb shell cat /proc/<strong><em>process_id</em></strong>/oom_adj</p>
<p><a href="http://blog.csdn.net/wangliang198901/article/details/12342845" target="_blank" rel="external">文章地址</a><br>一个进程可以做一个前台的ForegroundService做通知栏,或<br><figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"></div><div class="line"></div></pre></td></tr></table></figure></p>
]]></content>
<summary type="html">
<p>进程优先级介绍<br>
</summary>
<category term="Android进阶" scheme="https://github.com/iBotasky/categories/Android%E8%BF%9B%E9%98%B6/"/>
<category term="Android进阶" scheme="https://github.com/iBotasky/tags/Android%E8%BF%9B%E9%98%B6/"/>
</entry>
<entry>
<title>Android保活</title>
<link href="https://github.com/iBotasky/2017/02/04/Android%E4%BF%9D%E6%B4%BB/"/>
<id>https://github.com/iBotasky/2017/02/04/Android保活/</id>
<published>2017-02-04T06:38:22.000Z</published>
<updated>2017-08-27T09:15:32.000Z</updated>
<content type="html"><![CDATA[<p>平常接触到的保活<br><a id="more"></a><br>自启动保活 系统通知权限<br><figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyNotificationService</span> <span class="keyword">extends</span> <span class="title">NotificationListenerService</span> </span>{</div><div class="line"> <span class="keyword">private</span> String TAG = MyNotificationService.class.getName();</div><div class="line"></div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onNotificationPosted</span><span class="params">(StatusBarNotification sbn)</span> </span>{</div><div class="line"> Log.d(TAG, <span class="string">"onNotificationPosted: "</span>);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onNotificationRemoved</span><span class="params">(StatusBarNotification sbn)</span> </span>{</div><div class="line"> Log.d(TAG, <span class="string">"onNotificationRemoved: "</span>);</div><div class="line"> Intent intent = <span class="keyword">new</span> Intent(<span class="keyword">this</span>, BackgroundService.class);</div><div class="line"> startService(intent);</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>跳转<br><figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">goNLPermission</span><span class="params">(Context context)</span> </span>{</div><div class="line"> <span class="keyword">try</span> {</div><div class="line"> Intent intent = <span class="keyword">new</span> Intent(<span class="string">"android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS"</span>);</div><div class="line"> context.startActivity(intent);</div><div class="line"> } <span class="keyword">catch</span> (Exception e) {</div><div class="line"> e.printStackTrace();</div><div class="line"> }</div><div class="line"> }</div><div class="line"> </div><div class="line"> </div><div class="line"> <span class="comment">/**</span></div><div class="line"> * Notification keep live</div><div class="line"> */</div><div class="line"> goNLPermission(<span class="keyword">this</span>);</div><div class="line"> Intent notificationService = <span class="keyword">new</span> Intent(<span class="keyword">this</span>, MyNotificationService.class);</div><div class="line"> startService(notificationService);</div></pre></td></tr></table></figure></p>
]]></content>
<summary type="html">
<p>平常接触到的保活<br>
</summary>
<category term="Android进阶" scheme="https://github.com/iBotasky/categories/Android%E8%BF%9B%E9%98%B6/"/>
<category term="Android进阶" scheme="https://github.com/iBotasky/tags/Android%E8%BF%9B%E9%98%B6/"/>
</entry>
<entry>
<title>Android动画相关</title>
<link href="https://github.com/iBotasky/2017/02/04/Android%E5%8A%A8%E7%94%BB%E7%9B%B8%E5%85%B3/"/>
<id>https://github.com/iBotasky/2017/02/04/Android动画相关/</id>
<published>2017-02-04T06:37:15.000Z</published>
<updated>2017-08-27T09:16:26.000Z</updated>
<content type="html"><![CDATA[<p>平常用到的一些比较机智的动画</p>
<a id="more"></a>
<h2 id="1-ViewCompat"><a href="#1-ViewCompat" class="headerlink" title="1.ViewCompat"></a>1.ViewCompat</h2><p>ServiceApp里面看到一个二维码扫描/条形码输入的一个界面,两个界面放在一个Activity里面,切换二维码扫描跟条形码输入的时候会有一个过渡动画,</p>
<h3 id="1-1先设置要做过渡动画的View"><a href="#1-1先设置要做过渡动画的View" class="headerlink" title="1.1先设置要做过渡动画的View"></a>1.1先设置要做过渡动画的View</h3><p><code>ViewCompat.setAlpha(rlBlur, 0);</code></p>
<h3 id="1-2-在该显示的时候-设置VISIBLE,(默认应该是GONE)"><a href="#1-2-在该显示的时候-设置VISIBLE,(默认应该是GONE)" class="headerlink" title="1.2 在该显示的时候, 设置VISIBLE,(默认应该是GONE)"></a>1.2 在该显示的时候, 设置VISIBLE,(默认应该是GONE)</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">rlBlur.setVisibility(View.VISIBLE);</div><div class="line">rlBlur.setBackground(<span class="keyword">new</span> BitmapDrawable(<span class="keyword">null</span>, blurBg));</div><div class="line">ViewCompat.animate(rlBlur).alpha(<span class="number">1</span>).setDuration(<span class="number">400</span>).start();</div></pre></td></tr></table></figure>
<h3 id="1-3-在不显示的时候是指GONE和透明度"><a href="#1-3-在不显示的时候是指GONE和透明度" class="headerlink" title="1.3 在不显示的时候是指GONE和透明度"></a>1.3 在不显示的时候是指GONE和透明度</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">rlBlur.setVisibility(View.GONE);</div><div class="line">ViewCompat.setAlpha(rlBlur, <span class="number">0</span>);</div></pre></td></tr></table></figure>
<h3 id="1-4-也可以设置一些监听操作"><a href="#1-4-也可以设置一些监听操作" class="headerlink" title="1.4 也可以设置一些监听操作"></a>1.4 也可以设置一些监听操作</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">switch</span> (v.getId()) {</div><div class="line"> <span class="keyword">case</span> R.id.tv_qr_scan:</div><div class="line"> <span class="keyword">if</span> (!tvQrScan.isSelected()) {</div><div class="line"> tvCodeInput.setSelected(<span class="keyword">false</span>);</div><div class="line"> tvQrScan.setSelected(<span class="keyword">true</span>);</div><div class="line"> ViewCompat.animate(llInput).alpha(<span class="number">0</span>).setDuration(<span class="number">400</span>).setListener(<span class="keyword">new</span> ViewPropertyAnimatorListener() {</div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onAnimationStart</span><span class="params">(View view)</span> </span>{</div><div class="line"></div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onAnimationEnd</span><span class="params">(View view)</span> </span>{</div><div class="line"> llInput.setVisibility(View.GONE);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onAnimationCancel</span><span class="params">(View view)</span> </span>{</div><div class="line"></div><div class="line"> }</div><div class="line"> }).start();</div><div class="line"></div><div class="line"></div><div class="line"> mQRCodeView.startSpot();</div><div class="line"> }</div><div class="line"> <span class="keyword">break</span>;</div><div class="line"> <span class="keyword">case</span> R.id.tv_code_input:</div><div class="line"> <span class="keyword">if</span> (!tvCodeInput.isSelected()) {</div><div class="line"> tvQrScan.setSelected(<span class="keyword">false</span>);</div><div class="line"> tvCodeInput.setSelected(<span class="keyword">true</span>);</div><div class="line"> ViewCompat.animate(llInput).alpha(<span class="number">1</span>).setDuration(<span class="number">400</span>).setListener(<span class="keyword">new</span> ViewPropertyAnimatorListener() {</div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onAnimationStart</span><span class="params">(View view)</span> </span>{</div><div class="line"> llInput.setVisibility(View.VISIBLE);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onAnimationEnd</span><span class="params">(View view)</span> </span>{</div><div class="line"></div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onAnimationCancel</span><span class="params">(View view)</span> </span>{</div><div class="line"></div><div class="line"> }</div><div class="line"> }).start();</div><div class="line"></div><div class="line"> mQRCodeView.stopSpot();</div><div class="line"> }</div><div class="line"> <span class="keyword">break</span>;</div></pre></td></tr></table></figure>
<p>感觉用起来还不错,有需要可以用这个,在两个VIEW切换的时候用,显得切换不会那么生硬。</p>
<hr>
<h2 id="2-Activity启动退出动画"><a href="#2-Activity启动退出动画" class="headerlink" title="2.Activity启动退出动画"></a>2.Activity启动退出动画</h2><h3 id="2-1-首先在res-anim文件夹下创建进入和退出动画的set"><a href="#2-1-首先在res-anim文件夹下创建进入和退出动画的set" class="headerlink" title="2.1.首先在res/anim文件夹下创建进入和退出动画的set"></a>2.1.首先在<code>res/anim</code>文件夹下创建进入和退出动画的<code>set</code></h3><p>这里以底部上滑出现和从顶部下滑退出为例:<br><code>activity_open.xml</code>:</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line"><?xml version="1.0" encoding="utf-8"?> </div><div class="line"><span class="tag"><<span class="name">set</span> <span class="attr">xmlns:android</span>=<span class="string">"http://schemas.android.com/apk/res/android"</span>></span> </div><div class="line"> <span class="tag"><<span class="name">translate</span> </span></div><div class="line"> <span class="attr">android:fromYDelta</span>=<span class="string">"100%p"</span> </div><div class="line"> <span class="attr">android:toYDelta</span>=<span class="string">"0"</span> </div><div class="line"> <span class="attr">android:duration</span>=<span class="string">"1500"</span> </div><div class="line"> /> </div><div class="line"><span class="tag"></<span class="name">set</span>></span></div></pre></td></tr></table></figure>
<figure class="highlight plain"><figcaption><span>:</span></figcaption><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line">```xml</div><div class="line"><?xml version="1.0" encoding="utf-8"?> </div><div class="line"><set xmlns:android="http://schemas.android.com/apk/res/android"> </div><div class="line"> <translate </div><div class="line"> android:fromYDelta="25" </div><div class="line"> android:toYDelta="100%p" </div><div class="line"> android:duration="1500" </div><div class="line"> /> </div><div class="line"></set></div></pre></td></tr></table></figure>
<h3 id="2-2-设置启动动画:"><a href="#2-2-设置启动动画:" class="headerlink" title="2.2.设置启动动画:"></a>2.2.设置启动动画:</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">Intent intent = <span class="keyword">new</span> Intent(); </div><div class="line">intent.setClassName(cxt,<span class="string">"com.test.mrn.android.route.RouteDemoActivity"</span>);<span class="comment">//打开一个activity </span></div><div class="line">startActivity(intent); </div><div class="line">overridePendingTransition(R.anim.activity_open,<span class="number">0</span>);</div></pre></td></tr></table></figure>
<h3 id="2-3-设置关闭动画"><a href="#2-3-设置关闭动画" class="headerlink" title="2.3.设置关闭动画"></a>2.3.设置关闭动画</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line">button.setOnClickListener(<span class="keyword">new</span> OnClickListener() {</div><div class="line"> <span class="meta">@Override</span></div><div class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onClick</span><span class="params">(View v)</span> </span>{</div><div class="line"> finish();</div><div class="line"> overridePendingTransition(<span class="number">0</span>, R.anim.activity_close);</div><div class="line"> }</div><div class="line">});</div></pre></td></tr></table></figure>
<hr>
<h2 id="3-使用style的方式定义Activity的切换动画"><a href="#3-使用style的方式定义Activity的切换动画" class="headerlink" title="3.使用style的方式定义Activity的切换动画"></a>3.使用style的方式定义Activity的切换动画</h2><h3 id="3-1-定义Application的style"><a href="#3-1-定义Application的style" class="headerlink" title="3.1 定义Application的style"></a>3.1 定义Application的style</h3><figure class="highlight xml"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="tag"><<span class="name">application</span> <span class="attr">android:allowbackup</span>=<span class="string">"true"</span> <span class="attr">android:icon</span>=<span class="string">"@mipmap/ic_launcher"</span> </span></div><div class="line"><span class="attr">android:label</span>=<span class="string">"@string/app_name"</span> </div><div class="line"><span class="attr">android:supportsrtl</span>=<span class="string">"true"</span> </div><div class="line"><span class="attr">android:theme</span>=<span class="string">"@style/AppTheme"</span>></div><div class="line"><span class="tag"></<span class="name">application</span>></span></div></pre></td></tr></table></figure>
<h3 id="3-2-定义具体的AppTheme样式"><a href="#3-2-定义具体的AppTheme样式" class="headerlink" title="3.2 定义具体的AppTheme样式"></a>3.2 定义具体的AppTheme样式</h3><p>其中这里的windowAnimationStyle就是我们定义的Actvity切换动画的style。而<code>@anim/slide_in_top</code>就是我们定义的动画文件。也就是说通过切换Application的style,然后为windowAnimationStyle设置动画文件就可以全局的为Activity跳转配置动画效果:<br><figure class="highlight"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div></pre></td><td class="code"><pre><div class="line"> <<!-- Base application theme. --></div><div class="line"> <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"></div><div class="line"> <!-- Customize your theme here. --></div><div class="line"> <item name="colorPrimary">@color/colorPrimary</item></div><div class="line"> <item name="colorPrimaryDark">@color/colorPrimaryDark</item></div><div class="line"> <item name="colorAccent">@color/colorAccent</item></div><div class="line"> <item name="android:windowAnimationStyle">@style/activityAnim</item></div><div class="line"> </style></div><div class="line"></div><div class="line"></div><div class="line"><!-- 使用style方式定义activity切换动画 --></div><div class="line"> <style name="activityAnim"></div><div class="line"> <item name="android:activityOpenEnterAnimation">@anim/slide_in_top</item></div><div class="line"> <item name="android:activityOpenExitAnimation">@anim/slide_in_top</item></div><div class="line"> </style></div></pre></td></tr></table></figure></p>
<p>在windowAnimationStyle存在四中动画:</p>
<blockquote>
<ul>
<li>activityOpenEnterAnimation</li>
<li>activityOpenExitAnimation </li>
<li>activityCloseEnterAnimation</li>
<li>activityCloseExitAnimation </li>
</ul>
</blockquote>
]]></content>
<summary type="html">
<p>平常用到的一些比较机智的动画</p>
</summary>
<category term="Android" scheme="https://github.com/iBotasky/categories/Android/"/>
<category term="Android" scheme="https://github.com/iBotasky/tags/Android/"/>
</entry>
<entry>
<title>Android系统架构</title>
<link href="https://github.com/iBotasky/2017/02/04/Android%E7%B3%BB%E7%BB%9F%E6%9E%B6%E6%9E%84/"/>
<id>https://github.com/iBotasky/2017/02/04/Android系统架构/</id>
<published>2017-02-04T06:34:45.000Z</published>
<updated>2017-08-27T09:17:22.000Z</updated>
<content type="html"><![CDATA[<p>Android系统架构</p>
<p><a id="more"></a>##Android框架分层自顶向下</p>
<blockquote>
<p><em>应用程序层 (Applications)
</em>应用程序框架 (Application Frameworks)<br><em>系统运行库与Android运行环境 (Library&Runtime)