编辑/注意: 我真的需要回答这个问题,而且我想留下" stock"谷歌Android API。我已经为此创造了+100的赏金,但如果我在接下来的几天内使用股票API得到一个简单的解决方案,我将再增加+100,使其价值200点。
我尝试使用Android CalendarView控件。我在NestedScrollView中使用按钮和CalendarView制作了一个小应用程序。我做了按钮,它的边距非常大,所以我可以验证滚动工作。在运行Android 6.01的三星Galaxy S5上运行正常。但是在运行4.2.2的三星S Duo(这是我的预定目标)上,没有办法提前一个月(通知本月没有箭头)
这是来自运行Android 6.01的Samsung S5的屏幕截图
这是三星的Duo运行4.2.2
content_main.xml如下所示。 。 。
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!-- This linear layout is because the scrollview can have only 1 direct child -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/recordEnd"
android:layout_width="200dp"
android:layout_height="100dp"
android:layout_marginTop="100dp"
android:layout_marginBottom="100dp"
android:gravity="center"
android:text="Record End"/>
<CalendarView
android:id="@+id/thecalendar"
android:layout_width="240dp"
android:layout_height="300dp"
android:minDate="01/01/2016"
android:maxDate="11/30/2016"/>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
...在Android Studio中,设计视图会显示箭头。我不知道如何调试它。
答案 0 :(得分:10)
快速查看CalendarView
代码,看起来日历外观是从系统推断的,我无法找到改变它的方法。您可以在下方找到如何根据mode
选择日历视图:
final TypedArray a = context.obtainStyledAttributes(
attrs, R.styleable.CalendarView, defStyleAttr, defStyleRes);
final int mode = a.getInt(R.styleable.CalendarView_calendarViewMode, MODE_HOLO);
a.recycle();
switch (mode) {
case MODE_HOLO:
mDelegate = new CalendarViewLegacyDelegate(
this, context, attrs, defStyleAttr, defStyleRes);
break;
case MODE_MATERIAL:
mDelegate = new CalendarViewMaterialDelegate(
this, context, attrs, defStyleAttr, defStyleRes);
break;
default:
throw new IllegalArgumentException("invalid calendarViewMode attribute");
}
修改强>:
经过一段时间花在这个问题上我有更好的解释:
预览显示带箭头的视图,因为您尚未设置正确的API版本。如果您查看下面的图像,您会发现在Lollipop之前的版本中,按钮丢失了,在它之后,一切都很好而且很好。要更改API版本,只需单击红色突出显示的按钮,然后选择所需的API级别,即可在不同平台上准确预览xml。
为什么以前版本的Material Design中缺少箭头?
在这里,我无法找到谷歌某人给出的答案,但我相信这与屏幕分辨率有某种关系(在较旧的设备上,你没有足够的空间来显示{{ 1}}就像在较新的Android版本中一样,这就是他们选择CalendarView
的原因,因为它只能显示几行并且仍然完全正常运行,而使用ListView
显示则会裁剪一些最后一行)。
正如我在原帖中所说,ViewPager
的风格是根据Material Design(Android 5.0+)的可用性选择的。
旧版本(在下面找到)有一个CalendarView
,并且缺少下一个/上一个按钮。由于日历是使用ListView
显示的,因此ListView
的父视图为CalendarView
,因此您无法滚动到下个月。要解决此问题,您可以找到一些解释和解决方案here。
Scroll
Material Design版本将<TextView android:id="@+android:id/month_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:paddingTop="10dip"
android:paddingBottom="10dip"
style="@android:style/TextAppearance.Medium" />
<!-- This is the header representing the days of the week -->
<LinearLayout android:id="@+android:id/day_names"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="6dip"
android:layout_marginEnd="2dip"
android:layout_marginStart="2dip"
android:gravity="center" >
<TextView android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:visibility="gone" />
<TextView android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center" />
<TextView android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center" />
<TextView android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center" />
<TextView android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center" />
<TextView android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center" />
<TextView android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center" />
<TextView android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center" />
</LinearLayout>
<ImageView android:layout_width="match_parent"
android:layout_height="1dip"
android:scaleType="fitXY"
android:gravity="fill_horizontal"
android:src="?android:attr/dividerHorizontal" />
<ListView android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:drawSelectorOnTop="false"
android:cacheColorHint="@android:color/transparent"
android:fastScrollEnabled="false"
android:overScrollMode="never" />
替换为ListView
,并添加prev和next按钮。
ViewPager
目前,由于<android.widget.DayPickerViewPager
android:id="@+id/day_picker_view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ImageButton
android:id="@+id/prev"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="48dp"
android:minHeight="48dp"
android:src="@drawable/ic_chevron_start"
android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/date_picker_prev_month_button"
android:visibility="invisible" />
<ImageButton
android:id="@+id/next"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="48dp"
android:minHeight="48dp"
android:src="@drawable/ic_chevron_end"
android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/date_picker_next_month_button"
android:visibility="invisible" />
属性已从公共API中删除,因此无法找到CalendarView
样式的方法。
android.R.styleable类及其字段已从公共API中删除,以更好地确保应用程序的向前兼容性。
话虽如此,您可以保留旧版Android版本的旧样式,因为您无法对其进行更改,但请注意,stylable
不应位于ListView
或者尝试找到一个稳定且更符合您需求的存储库。
编辑II:
Scroll
没有被破坏,它在所有Android版本上都能很好地运行,即使它可能会让人觉得由于使用CalendarView
的实现而导致其行为被破坏。现在,&#39;让我们深入研究一下这个问题,以便每个人都能理解发生了什么:
问题没有。 1:在ListView
中使用ListView
一般来说,使用嵌套的元素是一种不好的做法,因为它们无法正确处理滚动操作。
问题没有。 2:使用ScrollView
并不能解决问题
从Android 5.0开始,Google添加了支持库以支持嵌套滚动,但NestedScrollView
除非实现ListView
,否则将无法处理滚动。为此,将NestedScrollingChild
类子类化并实现接口方法,并从每个方法调用NestedScrollingChildHelper中的相应方法。完成此步骤后,您可以在ListView
中使用ListView
,但不能使用NestedScrollView
(请参阅问题编号3)
问题没有。 3:您无法从CalendarView
更改列表
真正的问题是CalendarView
没有任何方法可以让您使用自己编写的自定义列表更改默认列表。假设你有这样一个方法,你可以通过用自定义的方法替换默认列表来使CalendarView
工作,滚动就可以完美地工作,但不幸的是你不能。
要解决问题,您有两个选择:
- 重新设计您的视图,使CalendarView
不在其名称中包含CalendarView
的类中
- 使用Pravin Divraniya的答案,这将使您的日历工作完美,但请记住,嵌套的卷轴很糟糕(特别是在屏幕较小的旧Android设备上)
答案 1 :(得分:8)
Iulian Popescu的一个很好而深刻的解释,我只是想简化它。首先,我想澄清一些事情。
CalenderView
小部件的确切外观和交互模型可能因操作系统版本和主题(例如Holo与Material)而异。android.widget.CalendarView
类Android的代码,您可以看到CalendarViewLegacyDelegate
类负责在HOLO
主题和CalendarViewMaterialDelegate
类的情况下呈现CalenderView负责在MATERIAL
主题的情况下渲染CalenderView。我再次发布该代码仅供参考。public CalendarView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); final TypedArray a = context.obtainStyledAttributes( attrs, R.styleable.CalendarView, defStyleAttr, defStyleRes); final int mode = a.getInt(R.styleable.CalendarView_calendarViewMode, MODE_HOLO); a.recycle(); switch (mode) { case MODE_HOLO: mDelegate = new CalendarViewLegacyDelegate( this, context, attrs, defStyleAttr, defStyleRes); break; case MODE_MATERIAL: mDelegate = new CalendarViewMaterialDelegate( this, context, attrs, defStyleAttr, defStyleRes); break; default: throw new IllegalArgumentException("invalid calendarViewMode attribute"); } }
CalendarViewMaterialDelegate
(android.widget.CalendarViewMaterialDelegate)类中,我们可以看到DayPickerView
(android.widget.DayPickerView)类用作渲染我们在Material中可以看到的日历视图的容器theme.In DayPickerView
class ViewPager
用于在一个页面中显示一个月。对于下一个和上一个,还有两个ImageButton
。由于有两个按钮可以更改月份,因此不会产生任何问题,并且可以在MATERIAL
主题中正常工作。private final ViewPager mViewPager; private final ImageButton mPrevButton; private final ImageButton mNextButton;
CalendarViewLegacyDelegate
(android.widget.CalendarViewLegacyDelegate)类中看到的,ListView
用于显示CalenderView
中的周列表(垂直滚动)。上一页和下一页没有任何ImageButton,因为它会垂直滚动。/** * The adapter for the weeks list. */ private WeeksAdapter mAdapter; /** * The weeks list. */ private ListView mListView;
根据此Android版开发人员网站的link,我们绝不应将ScrollView
与ListView
一起使用,因为ListView
负责自己的垂直滚动。因此,HOLO
主题CalenderView
在ScrollView
内使用时会出现意外行为。
<强>解决方案: - 强>
您可以使用以下给定的自定义滚动视图类而不是NestedScrollView
类。在CalenderView
主题的情况下,它会使HOLO
垂直滚动平滑。
public class VerticalScrollView extends ScrollView{
public VerticalScrollView(Context context) {
super(context);
}
public VerticalScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public VerticalScrollView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
final int action = ev.getAction();
switch (action)
{
case MotionEvent.ACTION_DOWN:
super.onTouchEvent(ev);
break;
case MotionEvent.ACTION_MOVE:
return false; // redirect MotionEvents to ourself
case MotionEvent.ACTION_CANCEL:
super.onTouchEvent(ev);
break;
case MotionEvent.ACTION_UP:
return false;
default:
break;
}
return false;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
super.onTouchEvent(ev);
return true;
}
}
我希望这会清除你的疑虑。