Android - 移除视图时屏幕未更新
Android - Screen not updating when removing view
这是我第一个 Android 动手实践的应用程序。该应用程序的唯一目的是制作和存储列表。当我创建新列表并将其添加到屏幕时,我遇到了屏幕无法正确更新自身的问题。为了尽可能多地了解视图和布局,我忽略了所有主题。无论如何,我有一个带有自定义按钮的线性布局,它本质上是另一种线性布局。第一次启动时,该应用程序看起来像这样! (我需要 10 个代表 post 图片所以现在你明白了)
***************************************************
* 列表列表 | + | | * |*
*--------------------------------------------*
* *
* 开始制作清单 *
* + *
*--------------------------------------------*
* *
* *
单击“开始制作列表”并在出现的弹出窗口中输入字符串后,我遇到了第一个按钮被删除但屏幕重绘不正确的问题。
***************************************************
* 列表列表 | + | | * |*
*--------------------------------------------*
* 测试标签 *
*--------------------------------------------*
* + *
*--------------------------------------------*
以防万一您无法从我的 ascii 艺术中分辨出原始按钮的剩余部分。你不能点击它,所以它就像消失了一样,但我的加号图像和阴影背景仍然显示。
代码,或者至少我认为您需要看到的代码
@Override
public void onCreate(Bundle savedInstanceState)
{
try{
super.onCreate(savedInstanceState);
init();
/* Start DB Gather data */
listData = new ListDB(this); //extends SQLiteOpenHelper
Cursor listNames = listData.getListNames(0);
if (listNames.getCount() > 0)
{
/* Regular processing */
createStandardView(listNames);
}
else
{
/* No lists yet, special view for new users */
createNoListView();
}
/* Draw the view to the screen */
setContentView(screen);
}catch(Exception e)
{
TextView errMsg = new TextView(this);
String err = e.toString() + "\n";
StackTraceElement[] stack = e.getStackTrace();
for(int i = 0; i < stack.length; ++i)
{
err += stack[i].toString() + "\n";
}
errMsg.setText(err.subSequence(0, err.length()));
setContentView(errMsg);
}
}
问题有点出现在对 createNoListView() 的调用中,所以这是代码
/**
* Creates the initial view the user will see when they first install the app / have no lists yet. This layout could
* have been and should be in a seperate xml file like any other static android layout
*/
public void createNoListView()
{
/* Default Fresh Install add new list button view */
final WideButton btnAddNew = new WideButton(this, R.string.btnAddText, R.drawable.add_new);
btnAddNew.setId(1);
btnAddNew.setImageDimensions(35,35);
btnAddNew.setOnClickListener(new View.OnClickListener(){
public void onClick(View v){
actionBar.addNewList();
}
});
llMain.addView(btnAddNew);
}
WideButton class 是我制作的 udf class。它扩展了 LinearLayout 并包含一个 textview 和 imageview。 post 如果有人认为 class 有帮助,我会非常高兴。
所以这就是问题真正发生的地方。当用户点击时,我们进入 actionBar.addNewList()。仅供参考 ActionBar 是我自定义的 class,尽管 API 提供了类似的功能。 ActionBar 是当前正在执行的 class 的私有 class。操作栏实现 View.onCLickListener。这是 addNewList() 函数。 llMain 也是一个 linearLayout
/**
* Starts the process of creating a new list.
* */
public void addNewList()
{
LayoutInflater inflater = ((Activity)action_bar.getContext()).getLayoutInflater();
final View vwDiag = inflater.inflate(R.layout.add_list_diag, null);
AlertDialog.Builder alert = new AlertDialog.Builder(ListOfLists.this);
alert.setView(vwDiag).setPositiveButton(R.string.ok, new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface d, int id)
{
/* Add the list to the DB*/
EditText txtNameVal = (EditText) vwDiag.findViewById(R.id.txtNameVal);
String listName = txtNameVal.getText().toString();
//Display new item
if(listData.getListCount() == 0)
{
((LinearLayout)ListOfLists.this.llMain.findViewById(1)).removeAllViews();
//ListOfLists.this.llMain.removeViewAt(0);
//ListOfLists.this.llMain.refreshDrawableState();
ListOfLists.this.llMain.removeAllViews();
}
listData.createList(listName);
addListToView(listName, null, null);
}
}).setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener(){public void onClick(DialogInterface d, int id){
}}).create().show();
}
}
如您所见,我尝试了很多不同的方法。我尝试过的其他事情是。
//first attempt if I remember correctly
View btnAddNew = ListOfLists.this.llMain.findViewById(1);
ListOfLists.this.llMain.removeView(btnAddNew);
//Another one I'm sure I've done
View btnAddNew = ListOfLists.this.llMain.findViewById(1);
ListOfLists.this.llMain.removeView(btnAddNew);
ListOfLists.this.llMain.invalidate();
我还完成了我能想到的这些命令的所有组合,这些命令看起来至少有点合乎逻辑。如果您需要查看更多代码,请询问。我只是认为它可能不适合 post 到目前为止我的整个应用程序。
这不是填充数据屏幕的方式。我并不是要听起来不礼貌,但您的基本方法在这里是错误的。您基本上是在自己的 Activity
内部做所有事情——从与数据模型交互到直接操作视图层次结构。
那不是 Android 做事的方式。您需要的是一个 Adapter
-- 您的数据和使用它的视图之间的中间组件。
您需要(可选)从 ListActivity
扩展(它会附带自己的 ListView
)但绑定 ListAdapter
(很可能是 SimpleCursorAdapter
,因为您正在从数据库中获取数据)到您的 ListView
中,这些数据要么由您通过 布局 文件明确提供,要么使用 ListActivity
提供的默认文件当你从它 扩展 时。
只有 Adapter
会与您的数据模型交互 类。当基础数据 List
发生变化时,调用 Adapter#notifyDataSetChanged()
会自动为您刷新 ListView
。
看看上面的Android Developers' List View tutorial to get the hang of the basics. If you feel that the CursorAdapter
is a wee bit more complex for you right now, start with using an ArrayAdapter
first. Here's a good ListView example。
不要害怕看到这么多不同的 类 漂浮在周围。以后会更容易。
这是我第一个 Android 动手实践的应用程序。该应用程序的唯一目的是制作和存储列表。当我创建新列表并将其添加到屏幕时,我遇到了屏幕无法正确更新自身的问题。为了尽可能多地了解视图和布局,我忽略了所有主题。无论如何,我有一个带有自定义按钮的线性布局,它本质上是另一种线性布局。第一次启动时,该应用程序看起来像这样! (我需要 10 个代表 post 图片所以现在你明白了)
*************************************************** * 列表列表 | + | | * |* *--------------------------------------------* * * * 开始制作清单 * * + * *--------------------------------------------* * * * *
单击“开始制作列表”并在出现的弹出窗口中输入字符串后,我遇到了第一个按钮被删除但屏幕重绘不正确的问题。
*************************************************** * 列表列表 | + | | * |* *--------------------------------------------* * 测试标签 * *--------------------------------------------* * + * *--------------------------------------------*
以防万一您无法从我的 ascii 艺术中分辨出原始按钮的剩余部分。你不能点击它,所以它就像消失了一样,但我的加号图像和阴影背景仍然显示。
代码,或者至少我认为您需要看到的代码
@Override
public void onCreate(Bundle savedInstanceState)
{
try{
super.onCreate(savedInstanceState);
init();
/* Start DB Gather data */
listData = new ListDB(this); //extends SQLiteOpenHelper
Cursor listNames = listData.getListNames(0);
if (listNames.getCount() > 0)
{
/* Regular processing */
createStandardView(listNames);
}
else
{
/* No lists yet, special view for new users */
createNoListView();
}
/* Draw the view to the screen */
setContentView(screen);
}catch(Exception e)
{
TextView errMsg = new TextView(this);
String err = e.toString() + "\n";
StackTraceElement[] stack = e.getStackTrace();
for(int i = 0; i < stack.length; ++i)
{
err += stack[i].toString() + "\n";
}
errMsg.setText(err.subSequence(0, err.length()));
setContentView(errMsg);
}
}
问题有点出现在对 createNoListView() 的调用中,所以这是代码
/**
* Creates the initial view the user will see when they first install the app / have no lists yet. This layout could
* have been and should be in a seperate xml file like any other static android layout
*/
public void createNoListView()
{
/* Default Fresh Install add new list button view */
final WideButton btnAddNew = new WideButton(this, R.string.btnAddText, R.drawable.add_new);
btnAddNew.setId(1);
btnAddNew.setImageDimensions(35,35);
btnAddNew.setOnClickListener(new View.OnClickListener(){
public void onClick(View v){
actionBar.addNewList();
}
});
llMain.addView(btnAddNew);
}
WideButton class 是我制作的 udf class。它扩展了 LinearLayout 并包含一个 textview 和 imageview。 post 如果有人认为 class 有帮助,我会非常高兴。
所以这就是问题真正发生的地方。当用户点击时,我们进入 actionBar.addNewList()。仅供参考 ActionBar 是我自定义的 class,尽管 API 提供了类似的功能。 ActionBar 是当前正在执行的 class 的私有 class。操作栏实现 View.onCLickListener。这是 addNewList() 函数。 llMain 也是一个 linearLayout
/**
* Starts the process of creating a new list.
* */
public void addNewList()
{
LayoutInflater inflater = ((Activity)action_bar.getContext()).getLayoutInflater();
final View vwDiag = inflater.inflate(R.layout.add_list_diag, null);
AlertDialog.Builder alert = new AlertDialog.Builder(ListOfLists.this);
alert.setView(vwDiag).setPositiveButton(R.string.ok, new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface d, int id)
{
/* Add the list to the DB*/
EditText txtNameVal = (EditText) vwDiag.findViewById(R.id.txtNameVal);
String listName = txtNameVal.getText().toString();
//Display new item
if(listData.getListCount() == 0)
{
((LinearLayout)ListOfLists.this.llMain.findViewById(1)).removeAllViews();
//ListOfLists.this.llMain.removeViewAt(0);
//ListOfLists.this.llMain.refreshDrawableState();
ListOfLists.this.llMain.removeAllViews();
}
listData.createList(listName);
addListToView(listName, null, null);
}
}).setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener(){public void onClick(DialogInterface d, int id){
}}).create().show();
}
}
如您所见,我尝试了很多不同的方法。我尝试过的其他事情是。
//first attempt if I remember correctly
View btnAddNew = ListOfLists.this.llMain.findViewById(1);
ListOfLists.this.llMain.removeView(btnAddNew);
//Another one I'm sure I've done
View btnAddNew = ListOfLists.this.llMain.findViewById(1);
ListOfLists.this.llMain.removeView(btnAddNew);
ListOfLists.this.llMain.invalidate();
我还完成了我能想到的这些命令的所有组合,这些命令看起来至少有点合乎逻辑。如果您需要查看更多代码,请询问。我只是认为它可能不适合 post 到目前为止我的整个应用程序。
这不是填充数据屏幕的方式。我并不是要听起来不礼貌,但您的基本方法在这里是错误的。您基本上是在自己的 Activity
内部做所有事情——从与数据模型交互到直接操作视图层次结构。
那不是 Android 做事的方式。您需要的是一个 Adapter
-- 您的数据和使用它的视图之间的中间组件。
您需要(可选)从 ListActivity
扩展(它会附带自己的 ListView
)但绑定 ListAdapter
(很可能是 SimpleCursorAdapter
,因为您正在从数据库中获取数据)到您的 ListView
中,这些数据要么由您通过 布局 文件明确提供,要么使用 ListActivity
提供的默认文件当你从它 扩展 时。
只有 Adapter
会与您的数据模型交互 类。当基础数据 List
发生变化时,调用 Adapter#notifyDataSetChanged()
会自动为您刷新 ListView
。
看看上面的Android Developers' List View tutorial to get the hang of the basics. If you feel that the CursorAdapter
is a wee bit more complex for you right now, start with using an ArrayAdapter
first. Here's a good ListView example。
不要害怕看到这么多不同的 类 漂浮在周围。以后会更容易。