четверг, февраля 21, 2013

Выделить фоном нажатия элементов ListView

Чтобы нажатый элемент ListView выделялся бы нужным фоном, нужно:

1. определить цвет для "обычного" фона, используемый для исходного состояния, и цвет для фона, используемого для выбранного или нажатого элемента списка:


    <color name="background_default">...</color>
    <color name="background_selected">...</color>

2. создать селектор для выбора цвета фона в зависимости от состояния элемента
drawable/item_background.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@color/background_selected" android:state_pressed="false" android:state_selected="true"/>
    <item android:drawable="@color/background_selected" android:state_pressed="true"/>
    <item android:drawable="@color/background_default"/>
</selector>

3. указать свежесозданный селектор в качестве фона для элемента, отображаемого в списке
layout/listview_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:background="@drawable/listitem_background_selector" ... ... ...>
   ... ... ...

</LinearLayout>

вместо п. 3 можно сделать проще и указать свойство ListView:
android:listSelector="@drawable/background_selected"

Готово.

воскресенье, февраля 17, 2013

Как показать в WebView страницу целиком

С настройками по-умолчанию WebView не даёт возможности уменьшить отображаемую страницу так, чтобы она показалась бы целиком - пусть и мелко.

Добавить такую возможность легко:

webView = (WebView) findViewById(R.id.webview);
WebSettings settings = webView.getSettings();


settings.setLoadWithOverviewMode(true);
settings.setUseWideViewPort(true);

Определить размер элементов в runtime

Иногда необходимо узнать размеры элементов - ширину, высоту - во время выполнения. Понадобиться это может чтобы изменить их взаимное расположение - например, чтобы отцентровать по высоте.

Проблема заключается в том, что во время выполнения onResume, а тем более - onCreate, размеры элементов ещё не известны. При этом какого-либо специального метода жизненного цикла Activity, вызываемого после окончания построения layout, нет.

Есть несколько способов решить такую проблему:
1. упаковать нужный набор компонентов в какой-нибудь потомок View, переопределить для полученного потомка метод onLayout, в котором вначале вызвать super-метод, а потом уже взять готовые размеры элементов и сделать то, что требуется.
Проблема - ну не хочется на каждый набор элементов создавать отдельный класс, так и утонуть в них недолго.

2. есть решение, использующее ViewTreeObserver - создать слушатель на OnGlobalLayoutListener(), в котором реализовать метод onGlobalLayout. Такое решение можно посмотреть в этом топике. Это уже лучше, но работать с этим не очень удобно, так как нужно поразбираться в isAlive(), не забыть вызвать removeGlobalOnLayoutListener, то есть работать нужно аккуратно.

Мне больше понравилось следующее решение, которое сейчас представляется наиболее и универсальным, и наиболее простым:

1. Создаём интерфейс

public interface OnLayoutCompletedListener {
void layoutCompleted(ViewGroup layout);
}


2. Делаем производный класс от одного из "базовых" layout - например, MyLinearLayout, в котором переопределяем метод onLayout - и в переопределённом методе вызываем layoutCompleted.


public class MyLinearLayout extends LinearLayout {
private OnLayoutCompletedListener layoutCompletedListener;

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
if (layoutCompletedListener != null) {
layoutCompletedListener.layoutCompleted(this);
}
}

public void setOnLayoutCompletedListener(OnLayoutCompletedListener layoutCompletedListener) {
this.layoutCompletedListener = layoutCompletedListener;
}
}

3. В раскладке Activity (пусть activity_main.xml) заменяем "корневой" LineаrLayout на свежесозданный MyLinearLayout, при этом не забыть установить для него идентификатор:


<my.components.MyLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    ... тут обычный набор ...

</my.components.MyLinearLayout>


4. Допиливаем Activity (у меня используются AndroidAnnotations):

@EActivity(R.layout.activity_main)
public class MyActivity extends Activity implements OnLayoutCompletedListener {

@ViewById
MyLinearLayout layout;

@AfterViews
protected void initViews() {
layout.setOnLayoutCompletedListener(this);
...
}

@Override
public void layoutCompleted(ViewGroup layout) {
updateArrowsPosition();
}
}

Вот и всё. Мне нравится то, что получаемое решение интуитивно понятно и набор дополнительных действий - минимален. Всё что нужно сделать (после того, как уже созданы нужные потомки "базовый" раскладок):


1. изменить раскладку для этой активити:
1.1. изменить класс для root-layout
1.2. добавить идентификатор
2. реализовать в активити интерфейс OnLayoutCompletedListener

2.1. добавить интерфейс в implements
2.2. получить экземпляр раскладки - в общем случае через findViewById
2.3. установить для экземпляра раскладки слушатель события
2.4. реализовать обработку события, генерируемого после завершения раскладки.

Вроде вполне несложно.






четверг, февраля 14, 2013

WebView, SSL, сайт с неверным сертификатом и Fatal signal 11 (SIGSEGV) at 0x00000010 (code=1)

Понадобилось отобразить в WebView страницу с сайта с некорректным сертификатом. Для того, чтобы игнорировать ошибку сертификата, создал экземпляр WebViewClient и переопределил в нём метод onReceivedSslError:


webView = (WebView) findViewById(R.id.webview);

WebViewClient viewClient = new WebViewClient() {
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
super.onReceivedSslError(view, handler, error); 
handler.proceed();
}
};

webView.setWebViewClient(viewClient);


Вызов handler.proceed() указывает на необходимость продолжать обработку, игнорируя ошибку сертификата.

После этого при запуске приложения на Android 4.0.4, Android 4.1.2 (проверял на устройствах, которые есть под рукой) стала возникать такая ошибка:
02-13 18:08:53.017: A/libc(1594): Fatal signal 11 (SIGSEGV) at 0x00000010 (code=1), thread 1622 (WebViewCoreThre)
(полный дамп приведён ниже, чтобы не мешать).

При этом приложение закрывается без каких либо сообщений и запускается снова.

На Android 2.2.2 такой ошибки не возникает.

Проблема решилась исключением вызова родительского метода onReceivedSslError:

public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
// super.onReceivedSslError(view, handler, error); REMOVE THIS LINE!
handler.proceed();
}
};


Заглянув в исходный код WebViewClient, увидел следующую реализацию:
public class WebViewClient {
   ...

   public void onReceivedSslError(WebView view, SslErrorHandler   handler, SslError error) {
        handler.cancel();
   }
   ...
}


Таким образом, вызвав унаследованный метод, я фактически получил
handler.cancel();
handler.proceed();

Как видно, такое сочетание Андроиду не понравилось.

А вот дамп:


02-13 18:08:53.017: A/libc(1594): Fatal signal 11 (SIGSEGV) at 0x00000010 (code=1), thread 1622 (WebViewCoreThre)
02-13 18:08:53.117: I/DEBUG(924): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
02-13 18:08:53.117: I/DEBUG(924): Build fingerprint: 'generic/google_sdk/generic:4.1.2/MASTER/495790:eng/test-keys'
02-13 18:08:53.117: I/DEBUG(924): pid: 1594, tid: 1622, name: UNKNOWN  >>> skipped by me <<<
02-13 18:08:53.117: I/DEBUG(924): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 00000010
02-13 18:08:53.327: I/DEBUG(924):     r0 45947a90  r1 c4760772  r2 46249169  r3 00000000
02-13 18:08:53.327: I/DEBUG(924):     r4 00000000  r5 40076a4c  r6 40076a4c  r7 49040eb4
02-13 18:08:53.327: I/DEBUG(924):     r8 00000000  r9 00000000  sl 40076a4c  fp 00000001
02-13 18:08:53.327: I/DEBUG(924):     ip 467346ac  sp 49040998  lr 462461bd  pc 458a6f24  cpsr 80000030
02-13 18:08:53.327: I/DEBUG(924):     d0  bfcc400000002710  d1  40c3880000000005
02-13 18:08:53.327: I/DEBUG(924):     d2  3ff0000000000000  d3  bf95c966c155d531
02-13 18:08:53.327: I/DEBUG(924):     d4  4000000000000000  d5  3fc8adc3e03ae00c
02-13 18:08:53.327: I/DEBUG(924):     d6  7e37e43c8800759c  d7  40c3880000000000
02-13 18:08:53.327: I/DEBUG(924):     d8  000000003dcccccd  d9  43a0000042880000
02-13 18:08:53.327: I/DEBUG(924):     d10 0000000043450000  d11 0000000000000000
02-13 18:08:53.327: I/DEBUG(924):     d12 0000000000000000  d13 0000000000000000
02-13 18:08:53.327: I/DEBUG(924):     d14 0000000000000000  d15 0000000000000000
02-13 18:08:53.337: I/DEBUG(924):     scr 20000012
02-13 18:08:53.337: I/DEBUG(924): backtrace:
02-13 18:08:53.337: I/DEBUG(924):     #00  pc 00101f24  /system/lib/libchromium_net.so (net::URLRequest::ContinueDespiteLastError()+71)
02-13 18:08:53.337: I/DEBUG(924):     #01  pc 002311bb  /system/lib/libwebcore.so
02-13 18:08:53.337: I/DEBUG(924):     #02  pc 000565d9  /system/lib/libchromium_net.so (MessageLoop::RunTask(Task*)+180)
02-13 18:08:53.337: I/DEBUG(924):     #03  pc 0005773b  /system/lib/libchromium_net.so (MessageLoop::DeferOrRunPendingTask(MessageLoop::PendingTask const&)+18)
02-13 18:08:53.347: I/DEBUG(924):     #04  pc 000577ab  /system/lib/libchromium_net.so (MessageLoop::DoWork()+94)
02-13 18:08:53.347: I/DEBUG(924):     #05  pc 000584eb  /system/lib/libchromium_net.so
02-13 18:08:53.347: I/DEBUG(924):     #06  pc 00056c9b  /system/lib/libchromium_net.so (MessageLoop::RunInternal()+114)
02-13 18:08:53.347: I/DEBUG(924):     #07  pc 00056cf9  /system/lib/libchromium_net.so (MessageLoop::Run()+16)
02-13 18:08:53.347: I/DEBUG(924):     #08  pc 000773a9  /system/lib/libchromium_net.so (base::Thread::ThreadMain()+188)
02-13 18:08:53.347: I/DEBUG(924):     #09  pc 00076e33  /system/lib/libchromium_net.so
02-13 18:08:53.347: I/DEBUG(924):     #10  pc 00012db0  /system/lib/libc.so (__thread_entry+48)
02-13 18:08:53.347: I/DEBUG(924):     #11  pc 00012514  /system/lib/libc.so (pthread_create+172)
02-13 18:08:53.347: I/DEBUG(924):     #12  pc 000fedd4  
02-13 18:08:53.347: I/DEBUG(924): stack:
02-13 18:08:53.347: I/DEBUG(924):          49040958  2a2d1cfc  [heap]
02-13 18:08:53.347: I/DEBUG(924):          4904095c  2a131dd0  [heap]
02-13 18:08:53.347: I/DEBUG(924):          49040960  2a2d1d0c  [heap]
02-13 18:08:53.347: I/DEBUG(924):          49040964  2a294ff8  [heap]
02-13 18:08:53.347: I/DEBUG(924):          49040968  2a131dd0  [heap]
02-13 18:08:53.347: I/DEBUG(924):          4904096c  c4760772  
02-13 18:08:53.357: I/DEBUG(924):          49040970  00000000  
02-13 18:08:53.357: I/DEBUG(924):          49040974  2a2d1cfc  [heap]
02-13 18:08:53.357: I/DEBUG(924):          49040978  2a131dd0  [heap]
02-13 18:08:53.357: I/DEBUG(924):          4904097c  00000000  
02-13 18:08:53.357: I/DEBUG(924):          49040980  40076a4c  
02-13 18:08:53.357: I/DEBUG(924):          49040984  45852bc7  /system/lib/libchromium_net.so
02-13 18:08:53.357: I/DEBUG(924):          49040988  00000000  
02-13 18:08:53.357: I/DEBUG(924):          4904098c  2a2bcbe4  [heap]
02-13 18:08:53.357: I/DEBUG(924):          49040990  df0027ad  
02-13 18:08:53.357: I/DEBUG(924):          49040994  00000000  
02-13 18:08:53.357: I/DEBUG(924):     #00  49040998  2a247720  [heap]
02-13 18:08:53.357: I/DEBUG(924):          4904099c  40076a4c  
02-13 18:08:53.357: I/DEBUG(924):          490409a0  40076a4c  
02-13 18:08:53.357: I/DEBUG(924):          490409a4  49040dd8  
02-13 18:08:53.357: I/DEBUG(924):          490409a8  40076a4c  
02-13 18:08:53.357: I/DEBUG(924):          490409ac  4581b1af  /system/lib/libchromium_net.so (base::internal::LockImpl::Unlock()+18)
02-13 18:08:53.357: I/DEBUG(924):          490409b0  00001000  
02-13 18:08:53.367: I/DEBUG(924):          490409b4  2a2d2828  [heap]
02-13 18:08:53.367: I/DEBUG(924):          490409b8  00000000  
02-13 18:08:53.367: I/DEBUG(924):          490409bc  2a2ebee0  [heap]
02-13 18:08:53.367: I/DEBUG(924):          490409c0  00000000  
02-13 18:08:53.367: I/DEBUG(924):          490409c4  4003b769  /system/lib/libc.so (dlfree+56)
02-13 18:08:53.367: I/DEBUG(924):          490409c8  46247d6b  /system/lib/libwebcore.so
02-13 18:08:53.367: I/DEBUG(924):          490409cc  00000000  
02-13 18:08:53.367: I/DEBUG(924):          490409d0  00001000  
02-13 18:08:53.367: I/DEBUG(924):          490409d4  2a13b210  [heap]
02-13 18:08:53.367: I/DEBUG(924):          ........  ........
02-13 18:08:53.367: I/DEBUG(924):     #01  49040a50  46249169  /system/lib/libwebcore.so
02-13 18:08:53.367: I/DEBUG(924):          49040a54  00000000  
02-13 18:08:53.367: I/DEBUG(924):          49040a58  46246193  /system/lib/libwebcore.so
02-13 18:08:53.367: I/DEBUG(924):          49040a5c  457fb5db  /system/lib/libchromium_net.so (MessageLoop::RunTask(Task*)+182)
02-13 18:08:53.367: I/DEBUG(924):     #02  49040a60  49040eb4  
02-13 18:08:53.367: I/DEBUG(924):          49040a64  00000000  
02-13 18:08:53.367: I/DEBUG(924):          49040a68  ffffffff  
02-13 18:08:53.378: I/DEBUG(924):          49040a6c  49040ea8  
02-13 18:08:53.378: I/DEBUG(924):          49040a70  40076a4c  
02-13 18:08:53.378: I/DEBUG(924):          49040a74  457fb505  /system/lib/libchromium_net.so (MessageLoop::ReloadWorkQueue()+164)
02-13 18:08:53.378: I/DEBUG(924):          49040a78  00000002  
02-13 18:08:53.378: I/DEBUG(924):          49040a7c  2a2d6718  [heap]
02-13 18:08:53.378: I/DEBUG(924):          49040a80  00000001  
02-13 18:08:53.378: I/DEBUG(924):          49040a84  2a2d6718  [heap]
02-13 18:08:53.378: I/DEBUG(924):          49040a88  00000000  
02-13 18:08:53.378: I/DEBUG(924):          49040a8c  457fbabf  /system/lib/libchromium_net.so
02-13 18:08:53.378: I/DEBUG(924):          49040a90  49040ad4  
02-13 18:08:53.378: I/DEBUG(924):          49040a94  2a2d6718  [heap]
02-13 18:08:53.378: I/DEBUG(924):          49040a98  49040b68  
02-13 18:08:53.378: I/DEBUG(924):          49040a9c  457fd125  /system/lib/libchromium_net.so
02-13 18:08:53.378: I/DEBUG(924):          ........  ........
02-13 18:08:53.397: I/DEBUG(924): memory near r0:
02-13 18:08:53.397: I/DEBUG(924):     45947a70 00000000 00000000 00000000 00000000  ................
02-13 18:08:53.397: I/DEBUG(924):     45947a80 00000000 00000000 00000000 00000000  ................
02-13 18:08:53.397: I/DEBUG(924):     45947a90 00000000 00000000 463906e9 00000000  ..........9F....
02-13 18:08:53.397: I/DEBUG(924):     45947aa0 00000000 00000000 00000000 00000002  ................
02-13 18:08:53.397: I/DEBUG(924):     45947ab0 0000000f 45947ab0 ffffffff 00000000  .....z.E........
02-13 18:08:53.397: I/DEBUG(924): memory near r2:
02-13 18:08:53.397: I/DEBUG(924):     46249148 4a062006 447a4479 ef48f6b8 e8bd68e0  . .JyDzD..H..h..
02-13 18:08:53.397: I/DEBUG(924):     46249158 f2b04010 bf00b859 0034639c 003464ea  .@..Y....c4..d4.
02-13 18:08:53.397: I/DEBUG(924):     46249168 f2b068c0 68c0b859 b85ef2b0 4605b57f  .h..Y..h..^....F
02-13 18:08:53.397: I/DEBUG(924):     46249178 b1eb6843 0108f100 c903aa04 0003e902  Ch..............
02-13 18:08:53.397: I/DEBUG(924):     46249188 9c029803 0f01f010 0660ea4f bf186928  ........O.`.(i..
02-13 18:08:53.397: I/DEBUG(924): memory near r5:
02-13 18:08:53.397: I/DEBUG(924):     40076a2c 00000000 00000000 00000000 00000000  ................
02-13 18:08:53.407: I/DEBUG(924):     40076a3c 00000000 00000000 00000000 00000000  ................
02-13 18:08:53.407: I/DEBUG(924):     40076a4c c4760772 00000000 00000000 00000000  r.v.............
02-13 18:08:53.417: I/DEBUG(924):     40076a5c 00000000 00000000 00000000 00000000  ................
02-13 18:08:53.417: I/DEBUG(924):     40076a6c 00000000 00000000 00000000 00000000  ................
02-13 18:08:53.417: I/DEBUG(924): memory near r6:
02-13 18:08:53.417: I/DEBUG(924):     40076a2c 00000000 00000000 00000000 00000000  ................
02-13 18:08:53.417: I/DEBUG(924):     40076a3c 00000000 00000000 00000000 00000000  ................
02-13 18:08:53.417: I/DEBUG(924):     40076a4c c4760772 00000000 00000000 00000000  r.v.............
02-13 18:08:53.417: I/DEBUG(924):     40076a5c 00000000 00000000 00000000 00000000  ................
02-13 18:08:53.417: I/DEBUG(924):     40076a6c 00000000 00000000 00000000 00000000  ................
02-13 18:08:53.417: I/DEBUG(924): memory near r7:
02-13 18:08:53.417: I/DEBUG(924):     49040e94 2a247720 2a247798 2a12d710 2a12d6f8   w$*.w$*...*...*
02-13 18:08:53.417: I/DEBUG(924):     49040ea4 00000008 00000000 49040d14 00000005  ...........I....
02-13 18:08:53.417: I/DEBUG(924):     49040eb4 00000000 00000000 00000000 00000000  ................
02-13 18:08:53.428: I/DEBUG(924):     49040ec4 00000000 4581be25 c4760772 2a2ba7e8  ....%..Er.v...+*
02-13 18:08:53.428: I/DEBUG(924):     49040ed4 4581be25 2a2bb778 00000078 4581be25  %..Ex.+*x...%..E
02-13 18:08:53.428: I/DEBUG(924): memory near sl:
02-13 18:08:53.428: I/DEBUG(924):     40076a2c 00000000 00000000 00000000 00000000  ................
02-13 18:08:53.428: I/DEBUG(924):     40076a3c 00000000 00000000 00000000 00000000  ................
02-13 18:08:53.428: I/DEBUG(924):     40076a4c c4760772 00000000 00000000 00000000  r.v.............
02-13 18:08:53.428: I/DEBUG(924):     40076a5c 00000000 00000000 00000000 00000000  ................
02-13 18:08:53.428: I/DEBUG(924):     40076a6c 00000000 00000000 00000000 00000000  ................
02-13 18:08:53.428: I/DEBUG(924): memory near ip:
02-13 18:08:53.428: I/DEBUG(924):     4673468c 45814d41 45814d8f 458a7b99 458a7c45  AM.E.M.E.{.EE|.E
02-13 18:08:53.428: I/DEBUG(924):     4673469c 458a6d8f 458a7081 458a6fc9 458a7145  .m.E.p.E.o.EEq.E
02-13 18:08:53.428: I/DEBUG(924):     467346ac 458a6edd 458a73e1 45830ba1 458a723d  .n.E.s.E...E=r.E
02-13 18:08:53.428: I/DEBUG(924):     467346bc 45814d4b 45814d9b 457fb2ad 45820c79  KM.E.M.E...Ey..E
02-13 18:08:53.428: I/DEBUG(924):     467346cc 45839615 458a6f4d 4087323d 45836865  ...EMo.E=2.@eh.E
02-13 18:08:53.437: I/DEBUG(924): memory near sp:
02-13 18:08:53.437: I/DEBUG(924):     49040978 2a131dd0 00000000 40076a4c 45852bc7  ...*....Lj.@.+.E
02-13 18:08:53.437: I/DEBUG(924):     49040988 00000000 2a2bcbe4 df0027ad 00000000  ......+*.'......
02-13 18:08:53.437: I/DEBUG(924):     49040998 2a247720 40076a4c 40076a4c 49040dd8   w$*Lj.@Lj.@...I
02-13 18:08:53.437: I/DEBUG(924):     490409a8 40076a4c 4581b1af 00001000 2a2d2828  Lj.@...E....((-*
02-13 18:08:53.437: I/DEBUG(924):     490409b8 00000000 2a2ebee0 00000000 4003b769  .......*....i..@
02-13 18:08:53.437: I/DEBUG(924): code around pc:
02-13 18:08:53.437: I/DEBUG(924):     458a6f04 f240490f 23032232 4479a801 ffa2f753  .I@.2".#..yDS...
02-13 18:08:53.437: I/DEBUG(924):     458a6f14 a802490c f7424479 a801f962 fd76f753  .I..yDB.b...S.v.
02-13 18:08:53.437: I/DEBUG(924):     458a6f24 68026920 47886c91 682b9829 d0014298   i.h.l.G).+h.B..
02-13 18:08:53.437: I/DEBUG(924):     458a6f34 eb92f740 bd30b02b 0009f86e 0009f866  @...+.0.n...f...
02-13 18:08:53.447: I/DEBUG(924):     458a6f44 000649bf 000649e6 4604b570 460e4817  .I...I..p..F.H.F
02-13 18:08:53.447: I/DEBUG(924): code around lr:
02-13 18:08:53.447: I/DEBUG(924):     4624619c c8030c08 0003e90c 9a009801 0f01f010  ................
02-13 18:08:53.447: I/DEBUG(924):     462461ac 0060ea4f 5819bf18 bf184418 4790588a  O.`....X.D...X.G
02-13 18:08:53.447: I/DEBUG(924):     462461bc 0000bd0e b5104b04 4604447b 60033308  .....K..{D.F.3.`
02-13 18:08:53.447: I/DEBUG(924):     462461cc ef1cf6bb bd104620 004c0248 4605b538  .... F..H.L.8..F
02-13 18:08:53.447: I/DEBUG(924):     462461dc b13c6804 f6bc1d20 b118ef82 68436820  .h<. ....... hCh
02-13 18:08:53.827: D/Zygote(36): Process 1594 terminated by signal (11)





понедельник, февраля 04, 2013

Android Query

Дали наводку на очень интересный проект - Android Query

Содержит разные вкусности вида

//fetch and set the image from internet, cache with file and memory 
aq.id(R.id.image1).image("http://www.vikispot.com/z/images/vikispot/android-w.png");