




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
【移动应用开发技术】如何在android中使用水平循环滚动控件
这期内容当中在下将会给大家带来有关如何在android中使用水平循环滚动控件,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。具体内容如下CycleScrollView.javapackage
com.example.test;
import
android.content.Context;
import
android.graphics.Rect;
import
android.os.Handler;
import
android.util.AttributeSet;
import
android.view.GestureDetector;
import
android.view.GestureDetector.OnGestureListener;
import
android.view.MotionEvent;
import
android.view.View;
import
android.view.ViewGroup;
import
android.widget.Scroller;
@SuppressWarnings("deprecation")
public
class
CycleScrollView<T>
extends
ViewGroup
implements
OnGestureListener
{
static
final
String
TAG
=
"CycleScrollView";
Context
mContext;
/**
*
Scroll
velocity.
*/
public
static
final
long
SCROLL_VELOCITY
=
50;
/**
*
Scroll
offset.
*/
public
static
final
int
SCROLL_OFFSET
=
-1;
/**
*
Touch
delay.
*/
public
static
final
long
TOUCH_DELAYMILLIS
=
2000;
/**
*
Fling
duration.
*/
public
static
final
int
FLING_DURATION
=
2000;
/**
*
Filing
max
velocity
x.
*/
public
static
final
int
MAX_VELOCITY_X
=
1000;
private
GestureDetector
detector;
private
Handler
mHandler;
private
Scroller
mScroller;
/**
*
Callback
interface
adapter
and
OnItemClick.
*/
private
CycleScrollAdapter<T>
mAdapter;
private
OnItemClickListener
mOnItemClickListener;
/**
*
Scroll
index
*/
private
int
mPreIndex;
private
int
mCurrentIndex;
private
int
mNextIndex;
private
View
mCurrentView;
private
View
mPreView;
private
View
mNextView;
private
float
mLastMotionX;
//
The
reLayout
is
false
can
not
invoke
onLayout.
private
boolean
reLayout
=
false;
//
If
the
item
count
more
than
screen
that
can
scroll.
private
boolean
canScroll
=
false;
//
A
flag
for
switch
current
view.
private
boolean
mCurrentViewAtLeft
=
true;
//
Fling
distance.
private
int
mFlingX
=
0;
private
boolean
isMoveAction
=
false;
private
int
defaultItemY
=
10;
private
int
maxItemCount
=
7;
private
int
initItemX
=
20;
/**
*
The
screen
width.
*/
private
int
screenWidth;
/**
*
Item
view
height.
*/
private
int
itemHeight;
/**
*
Item
view
width.
*/
private
int
itemWidth;
/**
*
Item
view
layout
x.
*/
private
int
itemX
=
getInitItemX();
/**
*
Item
view
layout
y.
*/
private
int
itemY
=
defaultItemY;
//
Auto
scroll
view
task.
private
final
Runnable
mScrollTask
=
new
Runnable()
{
@Override
public
void
run()
{
if
(canScroll)
{
scrollView(SCROLL_OFFSET);
mHandler.postDelayed(this,
SCROLL_VELOCITY);//
Loop
self.
}
}
};
public
CycleScrollView(Context
context)
{
super(context);
onCreate(context);
}
public
CycleScrollView(Context
context,
AttributeSet
attrs)
{
super(context,
attrs);
onCreate(context);
}
public
CycleScrollView(Context
context,
AttributeSet
attrs,
int
defStyle)
{
super(context,
attrs,
defStyle);
onCreate(context);
}
private
void
onCreate(Context
context)
{
mContext
=
context;
detector
=
new
GestureDetector(this);
mHandler
=
new
Handler();
mScroller
=
new
Scroller(context);
}
/**
*
Create
scroll
index.
*/
public
void
createIndex()
{
if
(canScroll)
{
mPreIndex
=
maxItemCount
-
1;
mCurrentIndex
=
0;
mNextIndex
=
1;
mPreView
=
getChildAt(mPreIndex);
mCurrentView
=
getChildAt(mCurrentIndex);
mNextView
=
getChildAt(mNextIndex);
}
}
/**
*
Set
item
click
callback.
*
*
@param
onItemClickListener
*
The
callback
*/
public
void
setOnItemClickListener(OnItemClickListener
onItemClickListener)
{
mOnItemClickListener
=
onItemClickListener;
}
/**
*
Set
itemAdapter
for
addItem
and
bindItem.
*
*
@param
itemAdapter
*/
public
void
setAdapter(CycleScrollAdapter<T>
adapter)
{
mAdapter
=
adapter;
}
/**
*
Start
auto
scroll.
*/
public
void
startScroll()
{
if
(canScroll)
{
mHandler.post(mScrollTask);
}
}
/**
*
Stop
auto
scroll
and
filing
scroll
task.
*/
public
void
stopScroll()
{
mHandler.removeCallbacks(mScrollTask);
}
/**
*
Delay
start
auto
scroll
task.
*/
public
void
delayStartScroll()
{
if
(canScroll)
{
mHandler.postDelayed(mScrollTask,
TOUCH_DELAYMILLIS);
}
}
@Override
protected
void
onMeasure(int
widthMeasureSpec,
int
heightMeasureSpec)
{
super.onMeasure(widthMeasureSpec,
heightMeasureSpec);
int
count
=
this.getChildCount();
for
(int
i
=
0;
i
<
count;
i++)
{
View
child
=
this.getChildAt(i);
child.measure(widthMeasureSpec,
heightMeasureSpec);
}
}
@Override
protected
void
onLayout(boolean
changed,
int
l,
int
t,
int
r,
int
b)
{
/**
*
On
layout
set
the
child
view
layout
by
x
y
width
and
height.
*/
if
(reLayout)
{//
Run
one
times.
for
(int
i
=
0;
i
<
getChildCount();
i++)
{
View
child
=
this.getChildAt(i);
child.setVisibility(View.VISIBLE);
child.layout(itemX,
getItemY(),
itemX
+
getItemWidth(),
getItemY()
+
getItemHeight());
itemX
+=
getItemMargin();
}
reLayout
=
!reLayout;
}
}
/**
*
When
fling
view
run
the
fling
task
scroll
view.
*/
@Override
public
boolean
onFling(MotionEvent
e1,
MotionEvent
e2,
float
velocityX,
float
velocityY)
{
if
(e1
==
null
||
e2
==
null)
{
return
false;
}
//
When
deltaX
and
velocityX
not
good
return
false.
if
(Math.abs(velocityX)
<
MAX_VELOCITY_X)
{
return
false;
}
//
Get
the
delta
x.
float
deltaX
=
(e1.getX()
-
e2.getX());
/**
*
If
can
fling
stop
other
scroll
task
at
first
,
delay
the
task
after
*
fling.
*/
mHandler.removeCallbacks(mScrollTask);
if
(canScroll)
{
mHandler.postDelayed(mScrollTask,
TOUCH_DELAYMILLIS
+
FLING_DURATION
-
1000);
}
/**
*
The
flingX
is
fling
distance.
*/
mFlingX
=
(int)
deltaX;
//
Start
scroll
with
fling
x.
mScroller.startScroll(0,
0,
mFlingX,
0,
FLING_DURATION);
return
false;
}
@Override
public
void
computeScroll()
{
if
(canScroll
&&
mSputeScrollOffset())
{
/**
*
The
Scroller.getCurrX()
approach
mFlingX
,
the
deltaX
more
and
*
more
small.
*/
int
deltaX
=
mFlingX
-
mScroller.getCurrX();
scrollView(-deltaX
/
10);
postInvalidate();
}
}
/**
*
When
touch
event
is
move
scroll
child
view.
*/
@Override
public
boolean
onTouchEvent(MotionEvent
ev)
{
//
Get
event
x,y
at
parent
view.
final
float
x
=
ev.getX();
/**
*
Get
event
x,y
at
screen.
*/
final
int
rawX
=
(int)
ev.getRawX();
final
int
rawY
=
(int)
ev.getRawY();
switch
(ev.getAction())
{
case
MotionEvent.ACTION_DOWN:
//
Reset
isMoveAction.
isMoveAction
=
false;
//
Get
motionX.
mLastMotionX
=
x;
break;
case
MotionEvent.ACTION_MOVE:
//
When
action
move
set
isMoveAction
true.
isMoveAction
=
true;
//
Only
support
one
pointer.
if
(ev.getPointerCount()
==
1)
{
//
Compute
delta
X.
int
deltaX
=
0;
deltaX
=
(int)
(x
-
mLastMotionX);
mLastMotionX
=
x;
//
When
canScroll
is
true,
scrollView
width
deltaX.
if
(canScroll)
{
scrollView(deltaX);
}
}
break;
case
MotionEvent.ACTION_UP:
/**
*
If
not
move
find
click
item
and
invoke
click
event.
*/
if
(!isMoveAction)
{
View
view
=
getClickItem(rawX,
rawY);
if
(view
!=
null)
{
mOnItemClickListener.onItemClick(Integer.valueOf(view
.getTag().toString()));
}
}
break;
}
return
this.detector.onTouchEvent(ev);
}
/**
*
Get
click
item
view
by
rawX
and
rawY.
*
@param
rawX
the
x
at
screen.
*
@param
rawY
the
y
at
screen.
*
@return
the
click
item
view.
*/
private
View
getClickItem(final
int
rawX,
final
int
rawY)
{
for
(int
i
=
0;
i
<
getChildCount();
i++)
{
View
child
=
getChildAt(i);
//
Get
item
view
rect.
Rect
rect
=
new
Rect();
child.getGlobalVisibleRect(rect);
//
If
click
point
on
the
item
view,
invoke
the
click
event.
if
(rect.contains(rawX,
rawY))
{
return
child;
}
}
return
null;
}
/**
*
Scroll
view
by
delta
x.
*
*
@param
deltaX
*
The
scroll
distance.
*/
private
void
scrollView(int
deltaX)
{
//
Move
child
view
by
deltaX.
moveChildView(deltaX);
//
After
move
change
index.
if
(deltaX
<
0)
{//
move
left
//
If
current
at
right
switch
current
view
to
left.
switchCurrentViewToLeft();
//
change
previous
current
next
index.
moveToNext();
}
else
{//
move
right
//
If
current
at
left
switch
current
view
to
right.
switchCurrentViewToRight();
//
change
previous
current
next
index.
moveToPre();
}
invalidate();
}
/**
*
Move
view
by
delta
x.
*
*
@param
deltaX
*
The
move
distance.
*/
private
void
moveChildView(int
deltaX)
{
for
(int
i
=
0;
i
<
getChildCount();
i++)
{
View
child
=
getChildAt(i);
child.layout(child.getLeft()
+
deltaX,
child.getTop(),
child.getRight()
+
deltaX,
child.getBottom());
}
}
/**
*
Current
event
is
move
to
left,
if
current
view
at
right
switch
current
*
view
to
left.
*/
private
void
switchCurrentViewToLeft()
{
if
(!mCurrentViewAtLeft)
{
mPreIndex
=
mCurrentIndex;
mCurrentIndex
=
mNextIndex;
mNextIndex++;
if
(mNextIndex
>
maxItemCount
-
1)
{
mNextIndex
=
0;
}
mCurrentView
=
getChildAt(mCurrentIndex);
mPreView
=
getChildAt(mPreIndex);
mNextView
=
getChildAt(mNextIndex);
mCurrentViewAtLeft
=
!mCurrentViewAtLeft;
}
}
/**
*
Current
event
is
move
to
right,
if
current
view
at
left
switch
current
*
view
to
right.
*/
private
void
switchCurrentViewToRight()
{
if
(mCurrentViewAtLeft)
{
mNextIndex
=
mCurrentIndex;
mCurrentIndex
=
mPreIndex;
mPreIndex--;
if
(mPreIndex
<
0)
{
mPreIndex
=
maxItemCount
-
1;
}
mCurrentView
=
getChildAt(mCurrentIndex);
mPreView
=
getChildAt(mPreIndex);
mNextView
=
getChildAt(mNextIndex);
mCurrentViewAtLeft
=
!mCurrentViewAtLeft;
}
}
/**
*
Current
event
is
move
to
left,if
current
view
move
out
of
screen
move
the
*
current
view
to
right
and
reBind
the
item
change
index.
*/
private
void
moveToNext()
{
if
(mCurrentView.getRight()
<
0)
{
mCurrentView.layout(mPreView.getLeft()
+
getItemMargin(),
getItemY(),
mPreView.getLeft()
+
getItemMargin()
+
getItemWidth(),
getItemY()
+
getItemHeight());
if
(mCurrentView.getTag()
!=
null)
{
int
listIndex
=
(Integer)
mCurrentView.getTag();
int
index
=
(listIndex
+
maxItemCount)
%
mAdapter.getCount();
mAdapter.bindView(mCurrentView,
mAdapter.get(index));
mCurrentView.setTag(index);
}
mPreIndex
=
mCurrentIndex;
mCurrentIndex
=
mNextIndex;
mNextIndex++;
if
(mNextIndex
>
maxItemCount
-
1)
{
mNextIndex
=
0;
}
mCurrentView
=
getChildAt(mCurrentIndex);
mPreView
=
getChildAt(mPreIndex);
mNextView
=
getChildAt(mNextIndex);
moveToNext();
}
}
/**
*
Current
event
is
move
to
right,if
current
view
move
out
of
screen
move
*
the
current
view
to
left
and
reBind
the
item
change
index.
*/
private
void
moveToPre()
{
if
(mCurrentView.getLeft()
>
getScreenWidth())
{
mCurrentView.layout(mNextView.getLeft()
-
getItemMargin(),
getItemY(),
mNextView.getLeft()
-
getItemMargin()
+
getItemWidth(),
getItemY()
+
getItemHeight());
if
(mCurrentView.getTag()
!=
null)
{
int
listIndex
=
(Integer)
mCurrentView.getTag();
int
index
=
(listIndex
-
maxItemCount
+
mAdapter.getCount())
%
mAdapter.getCount();
mAdapter.bindView(mCurrentView,
mAdapter.get(index));
mCurrentView.setTag(index);
}
mNextIndex
=
mCurrentIndex;
mCurrentIndex
=
mPreIndex;
mPreIndex--;
if
(mPreIndex
<
0)
{
mPreIndex
=
maxItemCount
-
1;
}
mCurrentView
=
getChildAt(mCurrentIndex);
mPreView
=
getChildAt(mPreIndex);
mNextView
=
getChildAt(mNextIndex);
moveToPre();
}
}
@Override
public
boolean
onDown(MotionEvent
e)
{
return
true;
}
@Override
public
void
onShowPress(MotionEvent
e)
{
}
@Override
public
boolean
onSingleTapUp(MotionEvent
e)
{
return
false;
}
@Override
public
boolean
onScroll(MotionEvent
e1,
MotionEvent
e2,
float
distanceX,
float
distanceY)
{
return
false;
}
@Override
public
void
onLongPress(MotionEvent
e)
{
}
public
int
getMaxItemCount()
{
return
maxItemCount;
}
public
void
setMaxItemCount(int
maxItemCount)
{
this.maxItemCount
=
maxItemCount;
}
public
void
setReLayout(boolean
reLayout)
{
this.reLayout
=
reLayout;
}
public
void
setCanScroll(boolean
canScroll)
{
this.canScroll
=
canScroll;
}
public
int
getItemX()
{
return
itemX;
}
public
void
setItemX(int
itemX)
{
this.itemX
=
itemX;
}
public
int
getItemY()
{
return
itemY;
}
public
void
setItemY(int
itemY)
{
this.itemY
=
itemY;
}
public
int
getItemWidth()
{
return
itemWidth;
}
public
void
setItemWidth(int
itemWidth)
{
this.itemWidth
=
itemWidth;
}
public
int
getItemHeight()
{
return
itemHeight;
}
public
void
setItemHeight(int
itemHeight)
{
this.itemHeight
=
itemHeight;
}
public
int
getItemMargin()
{
return
(screenWidth
-
itemWidth
*
(maxItemCount
-
1)
-
initItemX
*
2)/(maxItemCount
-
2)
+
itemWidth;
}
public
int
getScreenWidth()
{
return
screenWidth;
}
public
void
setScreenWidth(int
screenWidth)
{
this.screenWidth
=
screenWidth;
}
public
int
getInitItemX()
{
return
initItemX;
}
public
void
setInitItemX(int
initItemX)
{
this.initItemX
=
initItemX;
}
/**
*
The
interface
for
item
click
callback.
*/
interface
OnItemClickListener
{
public
boolean
onItemClick(int
position);
}
}CycleScrollAdapter.javapackage
com.example.test;
import
java.util.List;
import
android.app.Activity;
import
android.content.Context;
import
android.util.DisplayMetrics;
import
android.view.View;
public
abstract
class
CycleScrollAdapter<T>
{
private
List<T>
list;
private
CycleScrollView<T>
mCycleScrollView;
Context
mContext;
/**
*
Initial
CycleScrollAdapter
bind
list
to
view.
*
*
@param
list
*
The
list
data.
*
@param
cycleScrollView
*
The
CycleScrollView.
*
@param
context
*
The
Context.
*/
public
CycleScrollAdapter(List<T>
list,
CycleScrollView<T>
cycleScrollView,
Context
context)
{
this.list
=
list;
mContext
=
context;
mCycleScrollView
=
cycleScrollView;
mCycleScrollView.setAdapter(this);
GetScreenWidthPixels();
initView(list);
}
/**
*
Get
screen
width
pixels.
*/
private
void
GetScreenWidthPixels()
{
DisplayMetrics
dm
=
new
DisplayMetrics();
Activity
a
=
(Activity)
mContext;
a.getWindowManager().getDefaultDisplay().getMetrics(dm);
mCycleScrollView.setScreenWidth(dm.widthPixels);
}
/**
*
Bind
list
to
view.
*
*
@param
list
*
The
list
data.
*/
protected
void
initView(List<T>
list)
{
if
(list
==
null
||
list.size()
==
0)
{
return;
}
//
Clear
all
view
from
ViewGroup
at
first.
mCycleScrollView.removeAllViewsInLayout();
//
Loop
list.
for
(int
i
=
0;
i
<
list.size();
i++)
{
/**
*
If
list
size
more
than
MaxItemCount
break
the
loop,
only
create
*
view
count
is
MaxItemCount.
*/
if
(i
==
mCycleScrollView.getMaxItemCount())
{
break;
}
/**
*
If
list
size
less
than
MaxItemCount
at
the
last
loop
reLayout
*
otherwise
at
the
MaxItemCount
index
reLayout.
*/
if
(i
==
list.size()
-
1
||
i
==
mCycleScrollView.getMaxItemCount()
-
1)
{
mCycleScrollView.setItemX(mCycleScrollView.getInitItemX());
mCycleScrollView.setReLayout(true);
}
add(list.get(i),
i);
}
/**
*
If
list
count
more
than
MaxItemCount
the
view
can
scroll
otherwise
*
can
not
scroll.
*/
if
(list.size()
>=
mCycleScrollView.getMaxItemCount())
{
mCycleScrollView.setCanScroll(true);
}
else
{
mCycleScrollView.setCanScroll(false);
}
/**
*
If
list
count
more
than
MaxItemCount
reBuild
index.
*/
mCycleScrollView.createIndex();
}
/**
*
Get
list
size.
*
*
@return
The
list
size.
*/
public
int
getCount()
{
return
list.size();
}
/**
*
Returns
the
element
at
the
specified
location
in
this
*
*
@param
index
*
the
index
of
the
element
to
return.
*
@return
the
element
at
the
specified
location.
*/
public
T
get(int
index)
{
return
list.get(index);
}
/**
*
Adds
the
specified
object
at
the
end
of
this
and
refresh
view.
*
*
@param
t
*
the
object
to
add.
*/
public
void
addItem(T
t)
{
list.add(t);
initView(list);
}
/**
*
Removes
the
first
occurrence
of
the
specified
object
from
this
and
*
refresh
view.
*
*
@param
t
*
the
object
to
remove.
*/
public
void
removeItem(T
t)
{
list.remove(t);
initView(list);
}
/**
*
Add
the
specified
view
to
the
index.
*
*
@param
t
*
The
data
to
add.
*
@param
index
*
the
index.
*/
private
void
add(T
t,
int
index)
{
View
view
=
getView(t);
ComputeItemSize(view);
mCycleScrollView.addView(view);
view.setTag(index);
}
/**
*
If
item
size
is
null
compute
item
size.
*
*
@param
view
*
the
item
view.
*/
private
void
ComputeItemSize(View
view)
{
if
(mCycleScrollView.getItemWidth()
==
0
||
mCycleScrollView.getItemHeight()
==
0)
{
int
w
=
View.MeasureSpec.makeMeasureSpec(0,
View.MeasureSpec.UNSPECIFIED);
int
h
=
View.MeasureSpec.makeMeasureSpec(0,
View.MeasureSpec.UNSPECIFIED);
view.measure(w,
h);
int
height
=
view.getMeasuredHeight();
int
width
=
view.getMeasuredWidth();
mCycleScrollView.setItemHeight(height);
mCycleScrollView.setItemWidth(width);
}
}
/**
*
Get
item
view.
*
*
@param
t
*
the
data
need
bind
to
view.
*
@return
the
view.
*/
public
abstract
View
getView(T
t);
/**
*
Bind
the
item
to
view.
*
*
@param
child
*
the
item
view
need
bind.
*
@param
t
*
the
item.
*/
public
abstract
void
bindView(View
child,
T
t);
}以上两个是核心类,下面是测试代码。实现CycleScrollAdapterAppCycleScrollAdapter.java绑定视图和应用数据package
com.example.test;
import
java.util.List;
import
android.content.Context;
import
android.content.pm.PackageInfo;
import
android.view.View;
import
android.widget.ImageView;
import
android.widget.TextView;
public
class
AppCycleScrollAdapter
extends
CycleScrollAdapter<PackageInfo>
{
public
AppCycleScrollAdapter(List<PackageInfo>
list,
CycleScrollView<PackageInfo>
cycleScrollView,
Context
context)
{
super(list,
cycleScrollView,
context);
}
@Override
protected
void
initView(List<PackageInfo>
list)
{
super.initView(list);
}
@Override
public
void
bindView(View
child,
PackageInfo
pi)
{
ImageView
image
=
(ImageView)
child.findViewById(R.id.item_image);
TextView
text
=
(TextView)
child.findViewById(R.id.item_text);
image.setImageDrawable(pi.applicationInfo.loadIcon(mContext
.getPackageManager()));
text.setText(pi.applicationInfo.loadLabel(mContext.getPackageManager()));
}
@Override
public
View
getView(PackageInfo
pi)
{
View
view
=
View.inflate(mContext,
R.layout.view_item,
null);
//
inflate
APP
icon
view
ImageView
image
=
(ImageView)
view.findViewById(R.id.item_image);
//
inflate
APP
name
view
TextView
text
=
(TextView)
view.findViewById(R.id.item_text);
image.setImageDrawable(pi.applicationInfo.loadIcon(mContext
.getPackageManager()));
text.setText(pi.applicationInfo.loadLabel(mContext.getPackageManager()));
ret
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 农业土地综合利用合作框架合同
- 石化炼厂安全生产事故防范措施
- 农民家庭农场资产管理合作协议
- 超表面光电器件-洞察及研究
- 管道清洗有限空间作业安全防范措施
- 多渠道销售自动化营销平台
- 金属间化合物性能研究-洞察及研究
- 餐饮房屋租赁合同协议书
- 餐饮租赁合同协议书范本
- 物流运输木方模板买卖合同范文
- 2025年法治素养考试试题及答案
- 2025年一次性社保赔偿协议模板
- 园区安全培训
- 《中医经络学说》课件
- 港股基础知识入门培训
- 2 我是什么 第二课时(说课稿)-2024-2025学年统编版语文二年级上册
- 保证金合同模板
- 2025年山西航空产业集团有限公司招聘笔试参考题库含答案解析
- 2025年临床医师定期考核必考复习题库及答案(900题)
- 新能源汽车技术测试题(附答案)
- T-CISA 323-2023 极寒环境用结构钢板
评论
0/150
提交评论