您好,登錄后才能下訂單哦!
功能要求是屏幕上固定顯示 3 個 Layout 項(圖片+文字),支持點擊切換到選擇的 Layout 項,并支持滑動切換到最近的 Layout 項。
最后的效果如下:
下面逐步上代碼:
布局文件 activity_main.xml 如下:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity"> <TextView android:text="" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <HorizontalScrollView android:id="@+id/hsv" android:layout_width="match_parent" android:layout_height="wrap_content" android:scrollbarStyle="outsideInset"> <cn.steven.hsvp_w_picpathswitch.HSVLayout android:id="@+id/avatar_layout" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </HorizontalScrollView> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/hsv" android:layout_marginTop="12dp" android:id="@+id/scrollx_tv"/> <Button android:onClick="onClickScrollX" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/scrollx_tv" android:layout_marginTop="12dp" android:text="滾動位置"/> </RelativeLayout>
上面的 HorizontalScrollView 中使用了自定義的 HSVLayout 布局,定義(HSVLayout.java)如下:
public class HSVLayout extends LinearLayout { private HSVAdapter adapter; private Context context; public HSVLayout(Context context, AttributeSet attrs) { super(context, attrs); this.context = context; } /** * 設置布局適配器 * * @param layoutWidthPerAvatar 指定了每一個 item 的占用寬度 * @param adapter 適配器 * @param notify 在點擊某一個 item 后的回調 */ public void setAdapter(int layoutWidthPerAvatar, HSVAdapter adapter, final INotifySelectItem notify) { this.adapter = adapter; for (int i = 0; i < adapter.getCount(); i++) { final Map<String, Object> map = adapter.getItem(i); View view = adapter.getView(i, null, null); // 為視圖設定點擊監聽器 final int finalI = i; view.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // 點擊選擇了某一個 Item 視圖 notify.select(finalI); } }); this.setOrientation(HORIZONTAL); // 設置固定顯示的每個 item 布局的寬度 this.addView(view, new LinearLayout.LayoutParams( layoutWidthPerAvatar, LayoutParams.WRAP_CONTENT)); } } }
HSVLayout 中的每一個 視圖 item 都是由 HSVAdapter 進行設置的,這個比較簡單,只控制了每一個 item 的展示,不影響整個水平滾動視圖:
public class HSVAdapter extends BaseAdapter { private static final String TAG = "HSV"; private List<Map<String,Object>> lstAvatars; private Context context; private int layoutWidthPerAvatar; public HSVAdapter(Context context, int layoutWidthPerAvatar){ this.context=context; this.lstAvatars =new ArrayList<Map<String,Object>>(); this.layoutWidthPerAvatar = layoutWidthPerAvatar; } @Override public int getCount() { return lstAvatars.size(); } @Override public Map<String,Object> getItem(int location) { return lstAvatars.get(location); } @Override public long getItemId(int arg0) { return arg0; } public void addObject(Map<String,Object> map){ lstAvatars.add(map); notifyDataSetChanged(); } @Override public View getView(int location, View arg1, ViewGroup arg2) { View view = LayoutInflater.from(context).inflate(R.layout.user_avatar,null); view.setLayoutParams(new ViewGroup.LayoutParams(layoutWidthPerAvatar, ViewGroup.LayoutParams.WRAP_CONTENT)); TextView tvIndex = (TextView) view.findViewById(R.id.index_tv); tvIndex.setText("index-" + String.valueOf(location)); return view; } }
其對應的布局文件 user_avatar.xml 如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center"> <ImageView android:layout_width="64dp" android:layout_height="64dp" android:src="@drawable/avatar"/> <TextView android:id="@+id/index_tv" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" /> </LinearLayout>
最后看一下主頁面 MainActivity:
public class MainActivity extends ActionBarActivity implements INotifySelectItem { private static final String TAG = "Main"; private HorizontalScrollView hsv; private HSVLayout layoutAvatar; private HSVAdapter adapterAvatar; private TextView tvScrollX; private int layoutWidthPerAvatar = 0; private Integer[] p_w_picpaths = { R.drawable.avatar, R.drawable.avatar, R.drawable.avatar, R.drawable.avatar, R.drawable.avatar, R.drawable.avatar, R.drawable.avatar, R.drawable.avatar, R.drawable.avatar }; // 記錄當前居中的頭像索引 private int currentIndex = 1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); int width = DisplayUtil.getScreenWidth(this); int layoutWidth = (int) (width - getResources().getDimension(R.dimen.activity_horizontal_margin) * 2); // 每一個頭像占用的寬度 layoutWidthPerAvatar = layoutWidth / 3; hsv = (HorizontalScrollView) findViewById(R.id.hsv); hsv.setOnTouchListener(new View.OnTouchListener() { private int lastScrollX = 0; private int TouchEventId = -9987832; Handler handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); if (msg.what == TouchEventId) { if (lastScrollX == hsv.getScrollX()) { // 停止滾動,計算合適的位置(采用四舍五入) int indexScrollTo = Math.round(lastScrollX/(layoutWidthPerAvatar*1.0f)); Log.d(TAG, "stop scroll - " + lastScrollX + "|" + layoutWidthPerAvatar + "|" + lastScrollX/(layoutWidthPerAvatar*1.0f) + "|" + indexScrollTo); if (indexScrollTo > 0) { hsv.smoothScrollTo(indexScrollTo*layoutWidthPerAvatar, 0); } else { hsv.smoothScrollTo(0, 0); } } else { handler.sendMessageDelayed( handler.obtainMessage(TouchEventId), 100); lastScrollX = hsv.getScrollX(); } } } }; @Override public boolean onTouch(View v, MotionEvent event) { Log.d(TAG, "touch event - action: " + event.getAction() + "|" + event.getX() + "|" + event.getY() + "|" + hsv.getScrollX() + "|" + hsv.getScrollY()); if (event.getAction() == MotionEvent.ACTION_UP) { handler.sendMessageDelayed(handler.obtainMessage(TouchEventId), 100); } return false; } }); layoutAvatar = (HSVLayout) findViewById(R.id.avatar_layout); adapterAvatar = new HSVAdapter(this, layoutWidthPerAvatar); for (int i = 0; i < p_w_picpaths.length; i++) { Map<String, Object> map = new HashMap<String, Object>(); map.put("p_w_picpath", p_w_picpaths[i]); map.put("index", (i+1)); adapterAvatar.addObject(map); } layoutAvatar.setAdapter(layoutWidthPerAvatar, adapterAvatar, this); tvScrollX = (TextView) findViewById(R.id.scrollx_tv); } @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_main, 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 select(int position) { Toast.makeText(this, "select " + String.valueOf(position), Toast.LENGTH_SHORT).show(); if (position > 0) { if (currentIndex != position) { hsv.smoothScrollTo((position-1)*layoutWidthPerAvatar, 0); currentIndex = position; } } } public void onClickScrollX(View view) { tvScrollX.setText("Scroll.x = " + String.valueOf(hsv.getScrollX())); } }
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。