标签:
先来张效果图吧~
先说下思路吧: 这是个商品详情页,然后商品页面里面使用layoutInflater获取出要弹出框框的view,当然了,这里面参数的加载数据也就写在这个popwindow里面啦。
开始贴代码了
商品弹出框布局:(下面的购物车和购买偷懒直接设定了宽度)
activity_product_attribute.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="5dp" android:orientation="vertical" android:background="#FFFAF0" > <!-- android:background="#ffffff" --> <!-- 这里的linearLayout加android:background=""这个属性要谨慎,如果加了后,popwindow是不能半透明了的 --> <!-- <ScrollView android:id="@+id/MySearchScroll" android:layout_width="match_parent" android:layout_height="wrap_content" > --> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:layout_marginTop="20dp"> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginLeft="10dp" android:gravity="left" android:text="主要颜色" /> <LinearLayout android:id="@+id/linear_prodetailcolor" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:layout_gravity="left" android:layout_marginTop="10dp" > <com.shop.eshopservice.xListView.HorizontialListView android:id="@+id/ColorListView" android:layout_width="match_parent" android:layout_height="43dp" /> </LinearLayout> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:layout_marginTop="15dp" android:layout_marginBottom="20dp" > <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginLeft="10dp" android:gravity="left" android:text="尺码" /> <LinearLayout android:id="@+id/linear_prodetailsize" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:layout_gravity="left" android:layout_marginTop="10dp" > <com.shop.eshopservice.xListView.HorizontialListView android:id="@+id/SizeListView" android:layout_width="match_parent" android:layout_height="43dp" android:layout_gravity="left"/> </LinearLayout> </LinearLayout> <View android:layout_width="fill_parent" android:layout_height="1px" android:background="?android:attr/listDivider" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <TextView android:id="@+id/pro_gouwuche" android:layout_width="185dp" android:layout_height="50dp" android:background="#FF8C00" android:gravity="center" android:clickable="true" android:text="加入购物车" android:textColor="#ffffff" /> <TextView android:id="@+id/pro_tobuy" android:layout_width="185dp" android:layout_height="50dp" android:background="#FF0000" android:gravity="center" android:clickable="true" android:text="立即购买" android:textColor="#ffffff"/> </LinearLayout> </LinearLayout> <!-- <Button android:id="@+id/first" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="5dp" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:layout_marginTop="5dp" android:text="第一个按钮" /> <Button android:id="@+id/second" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="5dp" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:text="第二个按钮" /> <Button android:id="@+id/third" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="5dp" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:text="第三个按钮" /> --> <!-- </ScrollView> --> </LinearLayout>
然后在商品详情页,也就是第一张图,点击购买或加入购物车的时候,调用弹出框的方法,这里我起名叫showProductAttribute(); 来贴上
private EShopOpenHelper eshop; private ColorAdapter cAdapter; private SizeAdapter sAdapter; private List<mColor> colorsList = new ArrayList<mColor>(); private List<Size> sizeList = new ArrayList<Size>(); private HorizontialListView horCorList; private HorizontialListView horSizeList; private PopupWindow window; private String sizeName = ""; private String colorName = ""; //这两列的请求数据库填充数据我放在oncreate()方法里面了,为了写帖子方便就单独拿出来了。 colorsList = eshop.selColorByProId(info.getId()); sizeList = eshop.selSizeByProId(info.getId()); protected void showProductAttribute() { // 利用layoutInflater获得View LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); View view = inflater.inflate(R.layout.activity_product_attribute, null); horCorList = (HorizontialListView) view.findViewById(R.id.ColorListView); // 横向的ListView horSizeList = (HorizontialListView) view.findViewById(R.id.SizeListView); TextView gouwuche = (TextView) view.findViewById(R.id.pro_gouwuche); // 加入购物车 TextView tobuy = (TextView) view.findViewById(R.id.pro_tobuy); // 立即购买 // 下面是两种方法得到宽度和高度 getWindow().getDecorView().getWidth() window = new PopupWindow(view, WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.WRAP_CONTENT); // 设置popWindow弹出窗体可点击,这句话必须添加,并且是true window.setFocusable(true); // 必须要给调用这个方法,否则点击popWindow以外部分,popWindow不会消失 // window.setBackgroundDrawable(new BitmapDrawable()); // 实例化一个ColorDrawable颜色为半透明 ColorDrawable dw = new ColorDrawable(0xb0000000); window.setBackgroundDrawable(dw); // 在参照的View控件下方显示 // window.showAsDropDown(MainActivity.this.findViewById(R.id.start)); // 设置popWindow的显示和消失动画 window.setAnimationStyle(R.style.mypopwindow_anim_style); // 在底部显示 window.showAtLocation(GoodsDetailActivity.this.findViewById(R.id.Product_attribute_more), Gravity.BOTTOM, 0,0); cAdapter = new ColorAdapter(colorsList, getApplicationContext()); sAdapter = new SizeAdapter(sizeList, getApplicationContext()); horCorList.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { mColor cor = (mColor) parent.getAdapter().getItem(position);//颜色的实体类 colorName = cor.getColorName(); cAdapter.setSelectedPosition(position); cAdapter.notifyDataSetChanged(); // ToastUtils.ToastMessage(getApplicationContext(), "" + // cor.getColorName()); } }); horSizeList.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Size size = (Size) parent.getAdapter().getItem(position);//尺寸的实体类 sizeName = size.getSizeName(); sAdapter.setSelectedPosition(position); sAdapter.notifyDataSetChanged(); // ToastUtils.ToastMessage(getApplicationContext(), "" + // size.getSizeName()); } }); horCorList.setAdapter(cAdapter); horSizeList.setAdapter(sAdapter); // popWindow消失监听方法 window.setOnDismissListener(new OnDismissListener() { @Override public void onDismiss() { Toast.makeText(getApplicationContext(), "popWindow消失", 0); System.out.println("popWindow消失"); } }); } /** 消除弹窗 */ public void dissmiss() { window.dismiss(); }
这里还有里面的HorizontialListView类,这个是横向的ListView
HorizontialListView.java
/* * HorizontalListView.java v1.5 * * * The MIT License * Copyright (c) 2011 Paul Soucy (paul@dev-smart.com) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * */ package com.shop.eshopservice.xListView; import java.util.LinkedList; import java.util.Queue; import android.content.Context; import android.database.DataSetObserver; import android.graphics.Rect; import android.util.AttributeSet; import android.view.GestureDetector; import android.view.GestureDetector.OnGestureListener; import android.view.MotionEvent; import android.view.View; import android.widget.AdapterView; import android.widget.ListAdapter; import android.widget.Scroller; public class HorizontialListView extends AdapterView<ListAdapter> { public boolean mAlwaysOverrideTouch = true; protected ListAdapter mAdapter; private int mLeftViewIndex = -1; private int mRightViewIndex = 0; protected int mCurrentX; protected int mNextX; private int mMaxX = Integer.MAX_VALUE; private int mDisplayOffset = 0; protected Scroller mScroller; private GestureDetector mGesture; private Queue<View> mRemovedViewQueue = new LinkedList<View>(); private OnItemSelectedListener mOnItemSelected; private OnItemClickListener mOnItemClicked; private OnItemLongClickListener mOnItemLongClicked; private boolean mDataChanged = false; public HorizontialListView(Context context, AttributeSet attrs) { super(context, attrs); initView(); } private synchronized void initView() { mLeftViewIndex = -1; mRightViewIndex = 0; mDisplayOffset = 0; mCurrentX = 0; mNextX = 0; mMaxX = Integer.MAX_VALUE; mScroller = new Scroller(getContext()); mGesture = new GestureDetector(getContext(), mOnGesture); } @Override public void setOnItemSelectedListener(AdapterView.OnItemSelectedListener listener) { mOnItemSelected = listener; } @Override public void setOnItemLongClickListener(AdapterView.OnItemLongClickListener listener) { mOnItemLongClicked = listener; } @Override public void setOnItemClickListener(AdapterView.OnItemClickListener listener){ mOnItemClicked = listener; } private DataSetObserver mDataObserver = new DataSetObserver() { @Override public void onChanged() { synchronized(HorizontialListView.this){ mDataChanged = true; } invalidate(); requestLayout(); } @Override public void onInvalidated() { reset(); invalidate(); requestLayout(); } }; @Override public ListAdapter getAdapter() { return mAdapter; } @Override public View getSelectedView() { //TODO: implement return null; } @Override public void setAdapter(ListAdapter adapter) { if(mAdapter != null) { mAdapter.unregisterDataSetObserver(mDataObserver); } mAdapter = adapter; mAdapter.registerDataSetObserver(mDataObserver); reset(); } private synchronized void reset(){ initView(); removeAllViewsInLayout(); requestLayout(); } @Override public void setSelection(int position) { //TODO: implement } private void addAndMeasureChild(final View child, int viewPos) { LayoutParams params = child.getLayoutParams(); if(params == null) { params = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); } addViewInLayout(child, viewPos, params, true); child.measure(MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(getHeight(), MeasureSpec.AT_MOST)); } @Override protected synchronized void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); if(mAdapter == null){ return; } if(mDataChanged){ int oldCurrentX = mCurrentX; initView(); removeAllViewsInLayout(); mNextX = oldCurrentX; mDataChanged = false; } if(mScroller.computeScrollOffset()){ int scrollx = mScroller.getCurrX(); mNextX = scrollx; } if(mNextX < 0){ mNextX = 0; mScroller.forceFinished(true); } if(mNextX > mMaxX) { mNextX = mMaxX; mScroller.forceFinished(true); } int dx = mCurrentX - mNextX; removeNonVisibleItems(dx); fillList(dx); positionItems(dx); mCurrentX = mNextX; if(!mScroller.isFinished()){ post(new Runnable(){ @Override public void run() { requestLayout(); } }); } } private void fillList(final int dx) { int edge = 0; View child = getChildAt(getChildCount()-1); if(child != null) { edge = child.getRight(); } fillListRight(edge, dx); edge = 0; child = getChildAt(0); if(child != null) { edge = child.getLeft(); } fillListLeft(edge, dx); } private void fillListRight(int rightEdge, final int dx) { while(rightEdge + dx < getWidth() && mRightViewIndex < mAdapter.getCount()) { View child = mAdapter.getView(mRightViewIndex, mRemovedViewQueue.poll(), this); addAndMeasureChild(child, -1); rightEdge += child.getMeasuredWidth(); if(mRightViewIndex == mAdapter.getCount()-1){ mMaxX = mCurrentX + rightEdge - getWidth(); } mRightViewIndex++; } } private void fillListLeft(int leftEdge, final int dx) { while(leftEdge + dx > 0 && mLeftViewIndex >= 0) { View child = mAdapter.getView(mLeftViewIndex, mRemovedViewQueue.poll(), this); addAndMeasureChild(child, 0); leftEdge -= child.getMeasuredWidth(); mLeftViewIndex--; mDisplayOffset -= child.getMeasuredWidth(); } } private void removeNonVisibleItems(final int dx) { View child = getChildAt(0); while(child != null && child.getRight() + dx <= 0) { mDisplayOffset += child.getMeasuredWidth(); mRemovedViewQueue.offer(child); removeViewInLayout(child); mLeftViewIndex++; child = getChildAt(0); } child = getChildAt(getChildCount()-1); while(child != null && child.getLeft() + dx >= getWidth()) { mRemovedViewQueue.offer(child); removeViewInLayout(child); mRightViewIndex--; child = getChildAt(getChildCount()-1); } } private void positionItems(final int dx) { if(getChildCount() > 0){ mDisplayOffset += dx; int left = mDisplayOffset; for(int i=0;i<getChildCount();i++){ View child = getChildAt(i); int childWidth = child.getMeasuredWidth(); child.layout(left, 0, left + childWidth, child.getMeasuredHeight()); left += childWidth; } } } public synchronized void scrollTo(int x) { mScroller.startScroll(mNextX, 0, x - mNextX, 0); requestLayout(); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { boolean handled = mGesture.onTouchEvent(ev); return handled; } protected boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { synchronized(HorizontialListView.this){ mScroller.fling(mNextX, 0, (int)-velocityX, 0, 0, mMaxX, 0, 0); } requestLayout(); return true; } protected boolean onDown(MotionEvent e) { mScroller.forceFinished(true); return true; } private OnGestureListener mOnGesture = new GestureDetector.SimpleOnGestureListener() { @Override public boolean onDown(MotionEvent e) { return HorizontialListView.this.onDown(e); } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { return HorizontialListView.this.onFling(e1, e2, velocityX, velocityY); } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { synchronized(HorizontialListView.this){ mNextX += (int)distanceX; } requestLayout(); return true; } @Override public boolean onSingleTapConfirmed(MotionEvent e) { Rect viewRect = new Rect(); for(int i=0;i<getChildCount();i++){ View child = getChildAt(i); int left = child.getLeft(); int right = child.getRight(); int top = child.getTop(); int bottom = child.getBottom(); viewRect.set(left, top, right, bottom); if(viewRect.contains((int)e.getX(), (int)e.getY())){ if(mOnItemClicked != null){ mOnItemClicked.onItemClick(HorizontialListView.this, child, mLeftViewIndex + 1 + i, mAdapter.getItemId( mLeftViewIndex + 1 + i )); } if(mOnItemSelected != null){ mOnItemSelected.onItemSelected(HorizontialListView.this, child, mLeftViewIndex + 1 + i, mAdapter.getItemId( mLeftViewIndex + 1 + i )); } break; } } return true; } @Override public void onLongPress(MotionEvent e) { int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { View child = getChildAt(i); if (isEventWithinView(e, child)) { if (mOnItemLongClicked != null) { mOnItemLongClicked.onItemLongClick(HorizontialListView.this, child, mLeftViewIndex + 1 + i, mAdapter.getItemId(mLeftViewIndex + 1 + i)); } break; } } } private boolean isEventWithinView(MotionEvent e, View child) { Rect viewRect = new Rect(); int[] childPosition = new int[2]; child.getLocationOnScreen(childPosition); int left = childPosition[0]; int right = left + child.getWidth(); int top = childPosition[1]; int bottom = top + child.getHeight(); viewRect.set(left, top, right, bottom); return viewRect.contains((int) e.getRawX(), (int) e.getRawY()); } }; }
相信大家也看到了填充颜色和尺寸数据的适配器了ColorAdapter和SizeAdapter,这两个适配器getView里面共用了一个布局item_attribute.xml
代码如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:id = "@+id/linear_productAttr" android:background="#FFFAF0" android:orientation="horizontal" > <TextView android:id="@+id/ProductAttrTextView" android:layout_width="40dp" android:layout_height="35dp" android:layout_marginBottom="5dp" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:layout_marginTop="5dp" android:clickable="true" android:gravity="center" android:background="@drawable/textview_border" android:textColor="#4F4F4F" /> </LinearLayout>
ColorAdapter.java文件
/** * 商品属性的适配器 * */ public class ColorAdapter extends BaseAdapter { private List<mColor> colorList; private Context ctx; private int selectedPosition = -1;// 选中的位置 public ColorAdapter(List<mColor> attr, Context ctx) { this.colorList = attr; this.ctx = ctx; } public void setList(List<mColor> proList){ this.colorList = proList; } @Override public int getCount() { return colorList.size(); } @Override public Object getItem(int arg0) { return colorList.get(arg0); } @Override public long getItemId(int arg0) { return arg0; } public void setSelectedPosition(int position){ selectedPosition = position; } @Override public View getView(final int position, View arg1, ViewGroup arg2) { final Holder hold; if (arg1 == null) { hold = new Holder(); arg1 = View.inflate(ctx, R.layout.item_attribute, null); hold.mTitle = (TextView) arg1.findViewById(R.id.ProductAttrTextView); //产品标题 hold.mTitle.setClickable(true); arg1.setTag(hold); } else { hold = (Holder) arg1.getTag(); } hold.mTitle.setText(ToDBC(colorList.get(position).getColorName())); if(selectedPosition == position){ hold.mTitle.setBackgroundColor(Color.rgb(255, 130, 71)); hold.mTitle.setTextColor(Color.rgb(255, 255, 255)); }else{ hold.mTitle.setBackgroundResource(R.drawable.textview_border); hold.mTitle.setTextColor(Color.rgb(0, 0, 0)); } return arg1; } /** * TextView自动换行 * @param input * @return */ public static String ToDBC(String input) { char[] c = input.toCharArray(); for (int i = 0; i< c.length; i++) { if (c[i] == 12288) { c[i] = (char) 32; continue; }if (c[i]> 65280&& c[i]< 65375) c[i] = (char) (c[i] - 65248); } return new String(c); } static class Holder { TextView mTitle; } }
然后SizeAdapter.java文件
/** * 商品尺寸的适配器 * */ public class SizeAdapter extends BaseAdapter { private List<Size> sizeList; private Context ctx; private int selectedPosition = -1;// 选中的位置 public SizeAdapter(List<Size> attr, Context ctx) { this.sizeList = attr; this.ctx = ctx; } public void setList(List<Size> proList){ this.sizeList = proList; } @Override public int getCount() { return sizeList.size(); } @Override public Object getItem(int arg0) { return sizeList.get(arg0); } @Override public long getItemId(int arg0) { return arg0; } public void setSelectedPosition(int position){ selectedPosition = position; } @Override public View getView(final int position, View convertView, ViewGroup parent) { final Holder hold; if (convertView == null) { hold = new Holder(); convertView = View.inflate(ctx, R.layout.item_attribute, null); hold.mTitle = (TextView) convertView.findViewById(R.id.ProductAttrTextView); //产品标题 hold.mTitle.setClickable(true); convertView.setTag(hold); } else { hold = (Holder) convertView.getTag(); } hold.mTitle.setText(ToDBC(sizeList.get(position).getSizeName())); if(selectedPosition == position){ hold.mTitle.setBackgroundColor(Color.rgb(255, 130, 71)); hold.mTitle.setTextColor(Color.rgb(255, 255, 255)); }else{ hold.mTitle.setBackgroundResource(R.drawable.textview_border); hold.mTitle.setTextColor(Color.rgb(0, 0, 0)); } return convertView; } /** * TextView自动换行 * @param input * @return */ public static String ToDBC(String input) { char[] c = input.toCharArray(); for (int i = 0; i< c.length; i++) { if (c[i] == 12288) { c[i] = (char) 32; continue; }if (c[i]> 65280&& c[i]< 65375) c[i] = (char) (c[i] - 65248); } return new String(c); } static class Holder { TextView mTitle; } }
好了,这整一个流程就下来了。。。
代码虽有些啰嗦,但功能也算实现了。。
PopupWindow弹出产品属性+横向ListView HorizontialList实现产品属性
标签:
原文地址:http://my.oschina.net/u/2008084/blog/491184