我最近才了解JAVA和Android编程,所以请耐心等待。
上下文:我使用一个XML布局制作了一个带标签的Activity(使用ViewPager和SectionsPagerAdapter)。为此,我使用了Android Studio中的标准Activity with Fragment。对于不同的页面(滑动),只有某些TextView的值不同。我使用onViewCreated覆盖设置了这个。这在初始化时工作正常,但现在我想在用户交互(onClick)上更新和隐藏TextViews。这需要跟踪PlaceholderFragment中的页面视图,我已经通过我在这个论坛上阅读的setTag和findViewWithTag方法来完成,即我做了这个覆盖:
在PlaceholderFragment中:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
//added to keep reference to View
int position = getArguments().getInt(ARG_SECTION_NUMBER);
rootView.setTag(position);
return rootView;
}
现在,当单击TextView textViewStart时,我尝试更新三个TextView,包括单击的TextView:
在主要课程中:
public void onClick (View clickview) {
Log.i("onClick called: ", Integer.toString(clickview.getId())); // this gives a valid number. probably different from TextView ID in mView defined below
// get the current View from the ViewPager, stored using setTag
final View mView = mViewPager.findViewWithTag(currentTab); //currentTab is a variable with the current selected Page in the ViewPager, made using an override in onTabSelected
//Need to findIDs (for current tab page in ViewPager)
final TextView tvStart = (TextView)mView.findViewById(R.id.textViewStart);
final TextView tvPause = (TextView)mView.findViewById(R.id.textViewPause);
final TextView tvStop = (TextView)mView.findViewById(R.id.textViewStop);
//TextView tvStart = (TextView)findViewById(R.id.textViewStart); // this refers to another tab ! clickview.findViewById ONLY works for the actual object clicked
switch (clickview.getId()) {
case R.id.textViewStart: // START
runOnUiThread(new Runnable() {
@Override
public void run() {
//update controls
tvStart.setClickable(false);
tvStart.setVisibility(View.INVISIBLE);
tvStart.setTextColor(Color.parseColor("#888888"));//#RRGGBB // = grey
tvPause.setClickable(true);
tvPause.setVisibility(View.VISIBLE);
tvStop.setClickable(true);
tvStop.setVisibility(View.VISIBLE);
//NOTE this invalidates the textViews, BUT does not redraw the View, which only happens after onClick thread is finished, so what to do??
}
});
// mViewPager.setCurrentItem(currentTab-1); //also does not update View
//start timer
timerStatus = 1;
startTimer(currentTab); //this is another method, which starts a timer in the same View, this updates a ProgressBar which works.
}
}
以防万一,TextViews在XML中定义如下:
fragment_main.xml:
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="@string/Start"
android:id="@+id/textViewStart"
android:textSize="30dp"
android:textColor="#fff"
android:onClick="onClick"
android:clickable="true"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="@string/Pause"
android:id="@+id/textViewPause"
android:textSize="30dp"
android:textColor="#fff"
android:onClick="onClick"
android:clickable="false"
android:layout_below="@+id/view"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:visibility="invisible" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="@string/Stop"
android:id="@+id/textViewStop"
android:textSize="30dp"
android:textColor="#fff"
android:onClick="onClick"
android:clickable="false"
android:layout_below="@+id/view"
android:layout_alignRight="@+id/tvTimerTotal"
android:layout_alignEnd="@+id/tvTimerTotal"
android:visibility="invisible" />
问题: 我根本无法让TextViews显示或消失,或者让它们(un)可点击。现在发生的是TextViewStart(tvStart)按预期变为灰色,但它不会被隐藏并且仍然可以点击(我可以启动另一个startTimer实例)。此外,其他TextViews tvPause和tvStop不会出现。计时器(以startTimer()(主类的方法)启动)可以正常工作,并使用相同的findViewWithTag方法更新同一页面上的ProgressBar。
所以奇怪的是,TextViews的ID必须正确,因为setText和setTextColor正在工作,但完全相同的对象上的setVisibililty和setClickable不起作用!
我首先尝试的是没有runOnUiThread,它的工作方式类似。我也尝试将所有内容放在synchronized Thread中,但也有类似的结果。我还尝试将startTimer放在tvStop.post() {...}中,但这甚至没有启动计时器..
我真的不知道了,我在这里忽略了什么?
修改
这是我的完整活动(至少是Framents设置的一部分):
public class SomeActivity extends ActionBarActivity implements ActionBar.TabListener {
/**
* The {@link android.support.v4.view.PagerAdapter} that will provide
* fragments for each of the sections. We use a
* {@link FragmentPagerAdapter} derivative, which will keep every
* loaded fragment in memory. If this becomes too memory intensive, it
* may be best to switch to a
* {@link android.support.v4.app.FragmentStatePagerAdapter}.
*/
SectionsPagerAdapter mSectionsPagerAdapter;
/**
* The {@link ViewPager} that will host the section contents.
*/
ViewPager mViewPager;
//Peter: need access to current tab throughout activity
int currentTab;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_whatever);
// Set up the action bar.
final ActionBar actionBar = getSupportActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Create the adapter that will return a fragment for each of the three
// primary sections of the activity.
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
// When swiping between different sections, select the corresponding
// tab. We can also use ActionBar.Tab#select() to do this if we have
// a reference to the Tab.
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
@Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position);
}
});
// For each of the sections in the app, add a tab to the action bar.
for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
// Create a tab with text corresponding to the page title defined by
// the adapter. Also specify this Activity object, which implements
// the TabListener interface, as the callback (listener) for when
// this tab is selected.
actionBar.addTab(
actionBar.newTab()
.setText(mSectionsPagerAdapter.getPageTitle(i))
.setTabListener(this));
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_whatever, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
// When the given tab is selected, switch to the corresponding page in
// the ViewPager.
mViewPager.setCurrentItem(tab.getPosition());
// store current position in global variable
currentTab = tab.getPosition()+1; // +1 (!)
Log.i("TEST onTabSelected currentTab", Integer.toString(currentTab));
}
@Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
@Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
/**
* A {@link FragmentPagerAdapter} that returns a fragment corresponding to
* one of the sections/tabs/pages.
*/
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
// getItem is called to instantiate the fragment for the given page.
// Return a PlaceholderFragment (defined as a static inner class below).
return PlaceholderFragment.newInstance(position + 1);
}
@Override
public int getCount() {
// Show 3 total pages.
// DEFAULT: return 3;
return getResources().getStringArray(R.array.whatever_sections).length;
}
@Override
//PETER: this is the names of the pages
public CharSequence getPageTitle(int position) {
Locale l = Locale.getDefault();
// DEFAULT OVERRIDE
String[] menuItems = getResources().getStringArray(R.array.whatever_sections);
return menuItems[position];
}
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
/**
* The fragment argument representing the section number for this
* fragment.
*/
private static final String ARG_SECTION_NUMBER = "section_number";
/**
* Returns a new instance of this fragment for the given section
* number.
*/
public static PlaceholderFragment newInstance(int sectionNumber) {
PlaceholderFragment fragment = new PlaceholderFragment();
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, sectionNumber);
fragment.setArguments(args);
return fragment;
}
public PlaceholderFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_whatever, container, false);
//Peter added to keep reference to View (THIS WORKS)
int position = getArguments().getInt(ARG_SECTION_NUMBER);
rootView.setTag(position);
//Log.i("TEST onCreateView ARGS position: ",Integer.toString(position));
return rootView;
}
//PETER: added, this is apparently the default for setup of the items View components
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
//default code:
super.onViewCreated(view, savedInstanceState);
TextView tvWork = (TextView)view.findViewById(R.id.tvWork);
TextView tvPause = (TextView)view.findViewById(R.id.tvPause);
tvWork.setText("0:10");
tvPause.setText("4:00"); // 4 minutes
}
答案 0 :(得分:0)
我发现了这个问题。这不是setVisibility或View中的错误,但是在switch case语句中初学者错误。我有其他情况(我的帖子中的代码中没有显示),例如停止和暂停实现,但没有放
break;
在此代码中:
public void onClick (View clickview) throws InterruptedException {
switch (clickview.getId()) {
case R.id.textViewStart: // START
tvStart.setVisibility(View.INVISIBLE);
case R.id.textViewStop: // STOP
tvStart.setVisibility(View.VISIBLE);
}
}
案例fall through,并立即再次将TextView设置为可见。在为每个案例添加“break”之后,它按预期工作:
public void onClick (View clickview) throws InterruptedException {
switch (clickview.getId()) {
case R.id.textViewStart: // START
tvStart.setVisibility(View.INVISIBLE);
break; //otherwise next cases will all be executed too!
case R.id.textViewStop: // STOP
tvStart.setVisibility(View.VISIBLE);
break;
}
}