常见的Android应用程序功能是在每个细节项上滑动以转到下一个项目或上一个项目。
数据库游标包含一个列表,这些项目显示在ListActivity的onCreate中:
if (cursor.moveToFirst()) {
listThings.setAdapter(new ResourceCursorAdapter(this, R.layout.my_simple_expandable_list_item_2, cursor) {
@Override
public void bindView(View view, Context context, Cursor cursor) {
TextView tvFirst = (TextView)view.findViewById(android.R.id.text1);
TextView tvSecond = (TextView)view.findViewById(android.R.id.text2);
tvFirst.setText(cursor.getString(1) + " - " + getPctString(cursor.getString(2)));
tvSecond.setText(cursor.getString(3));
}
});
} else {
....
工作正常。内置布局资源R.layout.my_simple_expandable_list_item_2
告诉适配器在单个文本视图中显示光标中的每个项目。点击后,我可以在后续活动中显示该项目的详细信息:
AdapterView.OnItemClickListener itemClickListener = new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> listView, View v, int position, long id) {
Intent intent = new Intent(ThingListActivity.this, ThingActivity.class);
intent.putExtra(FollowOnActivity.EXTRA_ID, (int) id);
startActivity(intent);
}
};
进入FollowOnActivity
后,我可以查找详细信息并填充视图。我也可以倾听并对滑动做出反应。
问题:我无权访问列表中的下一个和上一个项目。到目前为止,我还没有提出我认为的清洁解决方案。由于这是一个常见的要求,因此可能有一个很好的模式。我想知道那是什么。
我能够使screen slide example正常工作,但该示例中的列表固定为五个项目,这些项目是xml文件中的文本而不是数据库项目。我根据ThingSlideActivity
,ScreenSlidePagerActivity
根据ThingSlidePageAdapter
和ScreenSlidePageAdapter
根据ThingSlideFragment
创建ScreenSlidePageFragment
。但我不知道如何将其连接到我来自的列表视图。它可能有一个很大的列表,我试图不提取所有这些的详细信息。
我坐在列表视图中,其中已经填充了一个游标(此问题顶部的第一个代码块)。用户单击列表中的随机数并运行onListItemClick。如何启用左右滑动以查看上一个和下一个项目?
答案 0 :(得分:1)
您运行了一个查询,并为Cursor
获得了ListActivity
。您已将Cursor
附加到显示您的列表的CursorAdapter
。
如果用户选择第三项(第2项),则在OnItemClickListener
中,position
参数将为2。
那么如果你将位置(2)传递给你的后续活动,那么在那里运行相同的查询并从光标第2行开始呢?使用光标,您将知道上一个,下一个......您拥有列表中所有内容的数据!
显示大型详细信息视图并左右水平滑动的方法是使用名为ViewPager
的窗口小部件。 ViewPager
由PagerAdapter
驱动,ListAdapter
有一些相似之处但绝对不同于PagerAdapter
。
您要做的是创建一个Cursor
Cursor
,因此在创建页面时,您可以从ResourceCursorAdapter
向其提供数据。当请求适配器页面3时,您创建一个详细视图,从光标读取第三条记录并将该数据放在详细视图中。
真的那么简单。 bindView
正在审议这个问题。当要求适配器查看第三个项目时,将创建/回收视图,光标位于第三个记录上,最后调用PagerAdapter
方法将数据放入视图中。
这是public class CursorPagerAdapter extends PagerAdapter {
/** Note that this class does not handle closing the cursor. */
private Cursor mCursor;
public CursorPagerAdapter(Cursor mCursor) {
this.mCursor = mCursor;
}
@Override
public int getCount() {
return mCursor == null ? 0 : mCursor.getCount();
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
mCursor.moveToPosition(position);
String data1 = mCursor.getString(1);
String data2 = mCursor.getString(2);
String data3 = mCursor.getString(3);
View view = LayoutInflater.from(container.getContext()).inflate(R.layout.detail_view, container, false);
// TODO fill in the view with the cursor data
container.addView(view);
return view;
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
}
的粗略示例:
ViewPager
ViewPager
是一个棘手的小问题,但作为Android开发人员,您迟早会需要它,所以现在开始学习如何使用它们会很好。我建议您深入了解并查看您可以参与的任何ASP.NET 5 An error occurred while starting the application
教程。
答案 1 :(得分:0)
这是最终正常运作的。它使用developer.android.com/training中screen-slide example中的模式,但有一点不同:在ThingSlideActivity.getItem()
中,我使用ThingSlideFragment.onCreate(pos)
而不是ThingSlideFragment.newInstance(pos)
。另外,我添加了static Cursor getCursor()
,其中提供了首先填充Cursor
的原始ListActivity
。这允许我从列表中的位置转换为数据库键。如果这种模式有任何缺陷,请告知。
初始活动此活动包含数据库中的列表,并且光标处于打开状态,直到列表被销毁:
public class ThingListActivity extends ListActivity {
private SQLiteDatabase db;
private static Cursor cursor;
static Cursor getCursor() {
return cursor;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ListView listThings = getListView();
int position = getIntent().getIntExtra("POSITION", 0);
try {
SQLiteOpenHelper tableDatabaseHelper = new TableDatabaseHelper(this);
db = tableDatabaseHelper.getReadableDatabase();
cursor = db.query("TABLE", pullFields, selectionFields, selectionArgs, null, null, null); // you define your own query
if (cursor.moveToFirst()) {
listThings.setAdapter(new ResourceCursorAdapter(this, R.layout.my_simple_expandable_list_item_2, cursor) { //built-in layout
@Override
public void bindView(View view, Context context, Cursor cursor) {
TextView tvFirst = (TextView)view.findViewById(android.R.id.text1);
TextView tvSecond = (TextView)view.findViewById(android.R.id.text2);
tvFirst.setText(cursor.getString(1) + " - " + getPctString(cursor.getString(2)));
tvSecond.setText(cursor.getString(3));
}
});
} else {
Toast toast = Toast.makeText(this, "The list was empty.", Toast.LENGTH_SHORT);
toast.show();
}
} catch (SQLiteException e) {
Toast toast = Toast.makeText(this, "Database Unavailable", Toast.LENGTH_SHORT);
toast.show();
} finally {
//Not closing cursor. Will do in onDestroy()
}
}
@Override
public void onDestroy(){
super.onDestroy();
if (cursor != null) cursor.close();
if (db != null) db.close();
}
@Override
protected void onListItemClick(ListView listView, View view, int position, long id) {
Intent intent = new Intent(ThingListActivity.this, ThingSlideActivity.class);
intent.putExtra(ThingSlideActivity.EXTRA_POSITION, (int) position);
startActivity(intent);
}
}
后续FragmentActivity
。此活动有一个内部类ThingSlidePageAdapter
。请注意setCurrentItem
,它会将您置于列表中的正确位置。的:强>
public class ThingSlideActivity extends FragmentActivity{
public static final String EXTRA_POSITION = "extra_position";
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_screen_slide);
ViewPager mPager = (ViewPager)findViewById(R.id.pager);
PagerAdapter mPagerAdapter = new ThingSlidePageAdapter(getSupportFragmentManager());
mPager.setAdapter(mPagerAdapter);
mPager.setCurrentItem((Integer)getIntent().getExtras().get(EXTRA_POSITION));
}
private static class ThingSlidePageAdapter extends FragmentStatePagerAdapter {
int count;
public ThingSlidePageAdapter(FragmentManager fm){
super(fm);
this.count = ThingListActivity.getCursor().getCount();
}
@Override
public int getCount() {
return this.count;
}
@Override
public Fragment getItem(int position) {
return ThingSlideFragment.newInstance(position); // onCreate() doesn't work well.
}
}
}
** Fragment
我们正在翻阅。这是我们使用原始Cursor
中的ListView
来获取数据库密钥(_id
)的地方。然后执行一个新的查询,仅为一个项目提取详细信息。但在幕后,前一项和下一项也被拉了。
public class ThingSlideFragment extends Fragment {
private static final String ARG_POSITION = "position";
public static ThingSlideFragment create(int position) {
ThingSlideFragment fragment = new ThingSlideFragment();
Bundle args = new Bundle();
args.putInt(ARG_POSITION, position);
fragment.setArguments(args);
return fragment;
}
public static ThingSlideFragment newInstance(int position) {
ThingSlideFragment fragment = new ThingSlideFragment();
Bundle args = new Bundle();
args.putInt(ARG_POSITION, position);
fragment.setArguments(args);
return fragment;
}
public ThingSlideFragment() {
}
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.activity_thing, container, false);
TextView tv = (TextView)rootView.findViewById(R.id.thingname);
Cursor mCursor = ThingListActivity.getCursor();
if (mCursor != null) {
mCursor.moveToPosition(getArguments().getInt(ARG_POSITION));
int id = Integer.parseInt(mCursor.getString(0));
populateView(id, rootView);
}
return rootView;
}
private void populateView(int id, View rootView) {
Cursor cursor = null;
SQLiteDatabase db = null;
try {
SQLiteOpenHelper tableDatabaseHelper = new TableDatabaseHelper(this.getContext()) ;
db = tableDatabaseHelper.getReadableDatabase();
cursor = db.query("TABLE", new String[] {"NAME", "DESCRIPTION", "DETAIL1", "DETAIL2", "DETAIL3", "DETAIL4"}, "_id = ?", new String[] {Integer.toString(id)}, null, null, null);
//Move to first record in the cursor (should be just one since our query used database key "CREATE TABLE TABLE (_id INTEGER PRIMARY KEY AUTOINCREMENT, ...."
if (cursor.moveToFirst()) {
// Get thing details from the cursor
String nameText = cursor.getString(0);
String descriptionText = cursor.getString(1);
// ........ continue with other fields
// Populate TextView items
((TextView)rootView.findViewById(R.id.thingname)).setText(nameText);
((TextView)rootView.findViewById(R.id.description)).setText(descriptionText);
// ........ continue with other fields
}
} catch (SQLiteException e) {
Toast toast = Toast.makeText(this.getContext(), "Database unavailable. "+ e.getMessage(), Toast.LENGTH_LONG) ;
} finally {
try {cursor.close();} catch (Throwable t) {}
try {db.close();} catch (Throwable t) {}
}
}
}
并且,在这里的许多示例中,遗漏了支持xml文件的内容!
<!-- R.layout.activity_screen_slide.xml containing R.id.pager -->
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- R.layout.activity_thing.xml containing R.id.thingname and R.id.description -->
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:id="@+id/thingRelativeLayout"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context="com.someones.package.ThingActivity"
tools:showIn="@layout/activity_thing">
<TextView
android:id="@+id/thingname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:paddingTop="40dp"
android:textSize="40dp"
android:gravity="center"
tools:text="Name Of Thing"
/>
<TextView
android:id="@+id/description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:textSize="20dp"
android:layout_below="@id/thingname"
android:paddingTop="10dp"
tools:text="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris et magna ut erat elementum cursus in quis ipsum. Nam faucibus ultrices eros, vel tempor leo semper sit amet."
/>
</RelativeLayout>
</ScrollView>
我希望这对你有用,并希望很多人能够找到它并从中受益,因为我花了几天时间来解决这个问题,直到我让它满意为止。对于经验丰富的人来说,可能只是一个简单,但对于那些具有一定经验水平的人来说很有帮助。