android 横向动态列表,Android横向ListView

本文探讨了在Android开发中实现横向ListView的方法,包括动态添加布局和自定义AdapterView子类。通过示例代码展示了如何使用HorizontalListView,并提供了设置触摸事件、监听滚动状态等功能。
摘要由CSDN通过智能技术生成

在日常开发中经常会发现横向的ListView。下面讨论实现方案。

1.动态的添加布局。

RelativeLayout view = (RelativeLayout) LayoutInflater.from(this)

.inflate(R.layout.demo, null);

ListView.addView(view);

2.通过继承AdapterView(ListAdapter)自定义类实现

部分关键代码如下:

类名:HorizontalListView(这个类不是我实现的,我只是拿来用)

a3aed8fc8b9be7aef11d12c860f98eaf.png

d525723ee2ca3f200a419d3b52cbbfdc.png

布局代码

android:id="@+id/listview"

android:layout_width="wrap_content"

android:layout_height="240dp"

android:clipToPadding="true"

android:paddingLeft="12dp"

app:dividerWidth="35dp"

/>

继承自AdapterView(ListAdapter),用法和普通的ListView相似。

代码粘贴如下:

package com.homelink.newlink.view;

import android.annotation.SuppressLint;

import android.annotation.TargetApi;

import android.content.Context;

import android.content.res.TypedArray;

import android.database.DataSetObserver;

import android.graphics.Canvas;

import android.graphics.Rect;

import android.graphics.drawable.Drawable;

import android.os.Build;

import android.os.Bundle;

import android.os.Parcelable;

import android.support.v4.view.ViewCompat;

import android.support.v4.widget.EdgeEffectCompat;

import android.util.AttributeSet;

import android.view.GestureDetector;

import android.view.HapticFeedbackConstants;

import android.view.MotionEvent;

import android.view.View;

import android.view.ViewGroup;

import android.widget.AdapterView;

import android.widget.ListAdapter;

import android.widget.ListView;

import android.widget.ScrollView;

import android.widget.Scroller;

import com.homelink.newlink.R;

import com.lianjia.common.utils.device.DensityUtil;

import java.util.ArrayList;

import java.util.LinkedList;

import java.util.List;

import java.util.Queue;

/**

* Created by jou on 2017/1/4.

*/

public class HorizontalListView extends AdapterView {

/**

* Defines where to insert items into the ViewGroup, as defined in {@code ViewGroup

* #addViewInLayout(View, int, LayoutParams, boolean)}

*/

private static final int INSERT_AT_END_OF_LIST = -1;

private static final int INSERT_AT_START_OF_LIST = 0;

/** The velocity to use for overscroll absorption */

private static final float FLING_DEFAULT_ABSORB_VELOCITY = 30f;

/** The friction amount to use for the fling tracker */

private static final float FLING_FRICTION = 0.009f;

/**

* Used for tracking the state data necessary to restore the HorizontalListView to its previous

* state after a rotation occurs

*/

private static final String BUNDLE_ID_CURRENT_X = "BUNDLE_ID_CURRENT_X";

/**

* The bundle id of the parents state. Used to restore the parent's state after a rotation

* occurs

*/

private static final String BUNDLE_ID_PARENT_STATE = "BUNDLE_ID_PARENT_STATE";

/** Tracks ongoing flings */

protected Scroller mFlingTracker = new Scroller(getContext());

/** Gesture listener to receive callbacks when gestures are detected */

private final GestureListener mGestureListener = new GestureListener();

/** Used for detecting gestures within this view so they can be handled */

private GestureDetector mGestureDetector;

/** This tracks the starting layout position of the leftmost view */

private int mDisplayOffset;

/** Holds a reference to the adapter bound to this view */

protected ListAdapter mAdapter;

/** Holds a cache of recycled views to be reused as needed */

private List> mRemovedViewsCache = new ArrayList>();

/** Flag used to mark when the adapters data has changed, so the view can be relaid out */

private boolean mDataChanged = false;

/** Temporary rectangle to be used for measurements */

private Rect mRect = new Rect();

/** Tracks the currently touched view, used to delegate touches to the view being touched */

private View mViewBeingTouched = null;

/** The width of the divider that will be used between list items */

private int mDividerWidth = 0;

/** The drawable that will be used as the list divider */

private Drawable mDivider = null;

/** The x position of the currently rendered view */

protected int mCurrentX;

/** The x position of the next to be rendered view */

protected int mNextX;

/** Used to hold the scroll position to restore to post rotate */

private Integer mRestoreX = null;

/**

* Tracks the maximum possible X position, stays at max value until last item is laid out and it

* can be determined

*/

private int mMaxX = Integer.MAX_VALUE;

/** The adapter index of the leftmost view currently visible */

private int mLeftViewAdapterIndex;

/** The adapter index of the rightmost view currently visible */

private int mRightViewAdapterIndex;

/** This tracks the currently selected accessibility item */

private int mCurrentlySelectedAdapterIndex;

/**

* Callback interface to notify listener that the user has scrolled this view to the point that

* it is low on data.

*/

private RunningOutOfDataListener mRunningOutOfDataListener = null;

/**

* This tracks the user value set of how many items from the end will be considered running out

* of data.

*/

private int mRunningOutOfDataThreshold = 0;

/**

* Tracks if we have told the listener that we are running low on data. We only want to tell

* them once.

*/

private boolean mHasNotifiedRunningLowOnData = false;

/**

* Callback interface to be invoked when the scroll state has changed.

*/

private OnScrollStateChangedListener mOnScrollStateChangedListener = null;

/**

* Represents the current scroll state of this view. Needed so we can detect when the state

* changes so scroll listener can be notified.

*/

private OnScrollStateChangedListener.ScrollState mCurrentScrollState =

OnScrollStateChangedListener.ScrollState.SCROLL_STATE_IDLE;

/**

* Tracks the state of the left edge glow.

*/

private EdgeEffectCompat mEdgeGlowLeft;

/**

* Tracks the state of the right edge glow.

*/

private EdgeEffectCompat mEdgeGlowRight;

/** The height measure spec for this view, used to help size children views */

private int mHeightMeasureSpec;

/** Used to track if a view touch should be blocked because it stopped a fling */

private boolean mBlockTouchAction = false;

/**

* Used to track if the parent vertically scrollable view has been told to

* DisallowInterceptTouchEvent

*/

private boolean mIsParentVerticiallyScrollableViewDisallowingInterceptTouchEvent = false;

/**

* The listener that receives notifications when this view is clicked.

*/

private OnClickListener mOnClickListener;

/**

* Recode the position of press and loose

*/

private MotionEvent mPressEvent;

private MotionEvent mLooseEvent;

/**

* MaoDian mode

*/

private boolean mIsAnchorEnable;

/**

* Filing mode

*/

private boolean mIsFilingEnable = true;

public HorizontalListView(Context context, AttributeSet attrs) {

super(context, attrs);

mEdgeGlowLeft = new EdgeEffectCompat(context);

mEdgeGlowRight = new EdgeEffectCompat(context);

mGestureDetector = new GestureDetector(context, mGestureListener);

bindGestureDetector();

initView();

retrieveXmlConfiguration(context, attrs);

setWillNotDraw(false);

// If the OS version is high enough then set the friction on the fling tracker */

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {

HoneycombPlus.setFriction(mFlingTracker, FLING_FRICTION);

}

}

/** Registers the gesture detector to receive gesture notifications for this view */

private void bindGestureDetector() {

// Generic touch listener that can be applied to any view that needs to process gestures

final OnTouchListener gestureListenerHandler = new OnTouchListener() {

@Override public boolean onTouch(final View v, final MotionEvent event) {

// Delegate the touch event to our gesture detector

return mGestureDetector.onTouchEvent(event);

}

};

setOnTouchListener(gestureListenerHandler);

}

/**

* When this HorizontalListView is embedded within a vertical scrolling view it is important to

* disable the parent view from interacting with

* any touch events while the user is scrolling within this HorizontalListView. This will start

* at this view and go up the view tree looking

* for a vertical scrolling view. If one is found it will enable or disable parent touch

* interception.

*

* @param disallowIntercept If true the parent will be prevented from intercepting child touch

* events

*/

private void requestParentListViewToNotInterceptTouchEvents(Boolean disallowIntercept) {

// Prevent calling this more than once needlessly

if (mIsParentVerticiallyScrollableViewDisallowingInterceptTouchEvent != disallowIntercept) {

View view = this;

while (view.getParent() instanceof View) {

// If the parent is a ListView or ScrollView then disallow intercepting of touch events

if (view.getParent() instanceof ListView || view.getParent() instanceof ScrollView) {

view.getParent().requestDisallowInterceptTouchEvent(disallowIntercept);

mIsParentVerticiallyScrollableViewDisallowingInterceptTouchEvent = disallowIntercept;

return;

}

view = (View) view.getParent(

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值