fix crash in KeyListAdapter by changing from different child layouts to one, which is changed on the fly in bindChildView()

This commit is contained in:
Dominik 2012-10-31 15:18:19 +01:00
parent 825ec676d0
commit 555381c4e2
6 changed files with 162 additions and 166 deletions

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
<!--
Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -14,67 +15,82 @@
limitations under the License.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:singleLine="true"
android:paddingLeft="10dip"
android:layout_marginRight="?android:attr/scrollbarSize"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:layout_width="fill_parent">
android:layout_marginRight="?android:attr/scrollbarSize"
android:orientation="vertical"
android:singleLine="true" >
<LinearLayout
android:layout_height="wrap_content"
android:id="@+id/keyLayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingRight="3dip">
android:paddingLeft="8dip"
android:paddingRight="3dip" >
<ImageView
android:id="@+id/ic_masterKey"
android:src="@drawable/key_small"
android:paddingRight="6dip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"/>
android:layout_gravity="center_vertical"
android:paddingRight="6dip"
android:src="@drawable/key_small" />
<TextView
android:id="@+id/keyId"
android:text="Key ID"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="5dip"
android:typeface="monospace"/>
android:text="Key ID"
android:textAppearance="?android:attr/textAppearanceMedium"
android:typeface="monospace" />
<TextView
android:id="@+id/keyDetails"
android:text="(RSA, 1024bit)"
android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
android:layout_height="wrap_content"
android:text="(RSA, 1024bit)"
android:textAppearance="?android:attr/textAppearanceSmall" />
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center_vertical"
android:gravity="right"
android:orientation="horizontal"
android:paddingBottom="2dip"
android:paddingTop="2dip"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center_vertical">
android:paddingTop="2dip" >
<ImageView
android:id="@+id/ic_encryptKey"
android:src="@drawable/encrypted_small"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
android:layout_height="wrap_content"
android:src="@drawable/encrypted_small" />
<ImageView
android:id="@+id/ic_signKey"
android:src="@drawable/signed_small"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
android:layout_height="wrap_content"
android:src="@drawable/signed_small" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/userIdLayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingLeft="36dip"
android:singleLine="true" >
<TextView
android:id="@+id/userId"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="3dip"
android:text="User ID"
android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout>
</LinearLayout>

View File

@ -1,72 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:singleLine="true"
android:paddingLeft="40dip"
android:layout_marginRight="?android:attr/scrollbarSize"
android:layout_height="?android:attr/listPreferredItemHeight"
android:layout_width="fill_parent">
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:orientation="horizontal"
android:paddingRight="3dip">
<TextView
android:id="@+id/keyId"
android:text="Key ID"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="5dip"
android:typeface="monospace"/>
<TextView
android:id="@+id/keyDetails"
android:text="(RSA, 1024bit)"
android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<LinearLayout
android:gravity="right"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:paddingBottom="2dip"
android:paddingTop="2dip"
android:layout_gravity="center_vertical">
<ImageView
android:id="@+id/ic_encryptKey"
android:src="@drawable/encrypted_small"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<ImageView
android:id="@+id/ic_signKey"
android:src="@drawable/signed_small"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>

View File

@ -1,33 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:paddingLeft="40dip"
android:layout_marginRight="?android:attr/scrollbarSize"
android:singleLine="true"
android:layout_width="fill_parent"
android:layout_height="?android:attr/listPreferredItemHeight">
<TextView
android:id="@+id/userId"
android:text="User ID"
android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="3dip"/>
</LinearLayout>

View File

@ -0,0 +1,88 @@
/*
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
* Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thialfihar.android.apg.ui;
import org.thialfihar.android.apg.Id;
import org.thialfihar.android.apg.R;
import org.thialfihar.android.apg.ui.widget.ExpandableListFragment;
import android.os.Bundle;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.View;
import android.widget.ExpandableListView;
import android.widget.ExpandableListView.ExpandableListContextMenuInfo;
public class KeyListFragment extends ExpandableListFragment {
protected KeyListActivity mKeyListActivity;
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mKeyListActivity = (KeyListActivity) getActivity();
// register long press context menu
registerForContextMenu(getListView());
// Give some text to display if there is no data. In a real
// application this would come from a resource.
setEmptyText(getString(R.string.listEmpty));
}
/**
* Context Menu on Long Click
*/
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
// TODO: better inflate menu from xml
// android.view.MenuInflater inflater = (android.view.MenuInflater) mActivity
// .getMenuInflater();
// menu.setHeaderTitle(R.string.checkbox_list_context_title);
// inflater.inflate(R.menu.checkbox_list_context, menu);
menu.add(0, Id.menu.export, 0, R.string.menu_exportKey);
menu.add(0, Id.menu.delete, 1, R.string.menu_deleteKey);
}
@Override
public boolean onContextItemSelected(android.view.MenuItem item) {
ExpandableListContextMenuInfo expInfo = (ExpandableListContextMenuInfo) item.getMenuInfo();
// expInfo.id would also return row id of childs, but we always want to get the row id of
// the group item, thus we are using the following way
int groupPosition = ExpandableListView.getPackedPositionGroup(expInfo.packedPosition);
long keyRingRowId = getExpandableListAdapter().getGroupId(groupPosition);
switch (item.getItemId()) {
case Id.menu.export:
mKeyListActivity.showExportKeysDialog(keyRingRowId);
return true;
case Id.menu.delete:
mKeyListActivity.showDeleteKeyDialog(keyRingRowId);
return true;
default:
return super.onContextItemSelected(item);
}
}
}

View File

@ -33,10 +33,6 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Messenger;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.View;
import android.widget.ExpandableListView;
public class KeyListSecretActivity extends KeyListActivity {
@ -49,8 +45,6 @@ public class KeyListSecretActivity extends KeyListActivity {
setContentView(R.layout.key_list_secret_activity);
mExportFilename = Constants.path.APP_DIR + "/secexport.asc";
// mList.setOnChildClickListener(this);
}
@Override
@ -76,14 +70,6 @@ public class KeyListSecretActivity extends KeyListActivity {
}
}
//
// public boolean onChildClick(ExpandableListView parent, View v, int groupPosition,
// int childPosition, long id) {
// mSelectedItem = groupPosition;
// checkPassPhraseAndEdit();
// return true;
// }
//
public void checkPassPhraseAndEdit(long keyId) {
String passPhrase = PassphraseCacheService.getCachedPassphrase(this, keyId);
if (passPhrase == null) {

View File

@ -36,6 +36,7 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.CursorTreeAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
public class KeyListAdapter extends CursorTreeAdapter {
@ -99,41 +100,37 @@ public class KeyListAdapter extends CursorTreeAdapter {
*/
@Override
public View newChildView(Context context, Cursor cursor, boolean isLastChild, ViewGroup parent) {
// first entry is fingerprint
if (cursor.getPosition() == 0) {
return mInflater.inflate(R.layout.key_list_child_item_user_id, null);
} else {
// differentiate between keys and userIds in MergeCursor
if (cursor.getColumnIndex(Keys.KEY_ID) != -1) {
// other layout for master key
int masterKeyIndex = cursor.getColumnIndex(Keys.IS_MASTER_KEY);
if (cursor.getInt(masterKeyIndex) == 1) {
return mInflater.inflate(R.layout.key_list_child_item_master_key, null);
} else {
return mInflater.inflate(R.layout.key_list_child_item_sub_key, null);
}
} else {
return mInflater.inflate(R.layout.key_list_child_item_user_id, null);
}
}
return mInflater.inflate(R.layout.key_list_child_item, null);
}
/**
* Bind TextViews from view of childs to query results
* Bind TextViews from view of childs based on query results
*/
@Override
protected void bindChildView(View view, Context context, Cursor cursor, boolean isLastChild) {
LinearLayout keyLayout = (LinearLayout) view.findViewById(R.id.keyLayout);
LinearLayout userIdLayout = (LinearLayout) view.findViewById(R.id.userIdLayout);
// first entry is fingerprint
if (cursor.getPosition() == 0) {
// show only userId layout
keyLayout.setVisibility(View.GONE);
userIdLayout.setVisibility(View.VISIBLE);
String fingerprint = PGPHelper.getFingerPrint(context,
cursor.getLong(cursor.getColumnIndex(Keys.KEY_ID)));
fingerprint = fingerprint.replace(" ", "\n");
TextView userId = (TextView) view.findViewById(R.id.userId);
if (userId == null) {
Log.d(Constants.TAG, "userId is null!");
}
userId.setText(context.getString(R.string.fingerprint) + ":\n" + fingerprint);
} else {
// differentiate between keys and userIds in MergeCursor
if (cursor.getColumnIndex(Keys.KEY_ID) != -1) {
keyLayout.setVisibility(View.VISIBLE);
userIdLayout.setVisibility(View.GONE);
String keyIdStr = PGPHelper.getSmallFingerPrint(cursor.getLong(cursor
.getColumnIndex(Keys.KEY_ID)));
@ -147,16 +144,30 @@ public class KeyListAdapter extends CursorTreeAdapter {
TextView keyDetails = (TextView) view.findViewById(R.id.keyDetails);
keyDetails.setText("(" + algorithmStr + ")");
ImageView masterKeyIcon = (ImageView) view.findViewById(R.id.ic_masterKey);
if (cursor.getInt(cursor.getColumnIndex(Keys.IS_MASTER_KEY)) != 1) {
masterKeyIcon.setVisibility(View.INVISIBLE);
} else {
masterKeyIcon.setVisibility(View.VISIBLE);
}
ImageView encryptIcon = (ImageView) view.findViewById(R.id.ic_encryptKey);
if (cursor.getInt(cursor.getColumnIndex(Keys.CAN_ENCRYPT)) != 1) {
encryptIcon.setVisibility(View.GONE);
} else {
encryptIcon.setVisibility(View.VISIBLE);
}
ImageView signIcon = (ImageView) view.findViewById(R.id.ic_signKey);
if (cursor.getInt(cursor.getColumnIndex(Keys.CAN_SIGN)) != 1) {
signIcon.setVisibility(View.GONE);
} else {
signIcon.setVisibility(View.VISIBLE);
}
} else {
keyLayout.setVisibility(View.GONE);
userIdLayout.setVisibility(View.VISIBLE);
String userIdStr = cursor.getString(cursor.getColumnIndex(UserIds.USER_ID));
TextView userId = (TextView) view.findViewById(R.id.userId);