Android高德地图自定义Markers的例子

 更新时间:2016年9月20日 19:54  点击:1877
下文为各位重点介绍关于Android高德地图自定义Markers的例子,希望这篇文章能够让各位理解到Android高德地图自定义Markers的方法。

之前的博客里说了地图的嵌入和定位,今天就说说在地图上显示一些我们想要的。在地图中有自带的Markers(标记),但是它只显示一个椭圆的图标,一般是不符合我们的需求的,这样就要我们自己来自定义。首先标记有下面一些属性;

1.position(Required) 在地图上标记位置的经纬度值。参数不能为空。

2.title 当用户点击标记,在信息窗口上显示的字符串。

3.snippet 附加文本,显示在标题下方。

4.draggable 如果您允许用户可以自由移动标记,设置为“ true ”。默认情况下为“ false ”。

5.visible 设置“ false ”,标记不可见。默认情况下为“ true ”。

6.anchor图标摆放在地图上的基准点。默认情况下,锚点是从图片下沿的中间处。

7.perspective设置 true,标记有近大远小效果。默认情况下为 false。

8.可以通过Marker.setRotateAngle() 方法设置标记的旋转角度,从正北开始,逆时针计算。如设置旋转90度,Marker.setRotateAngle(90)

9.通过setFlat() 方法设置标志是否贴地显示

自定义图标通常由 BitmapDescriptor 设置。我们可以在类 BitmapDescriptorFactory 使用以下其中一种方法定义。

1.fromAsset(String assetName) 在 assets 目录中使用图像创建自定义标记。

2.fromBitmap (Bitmap image) 使用位图图像创建自定义标记。

3.fromFile (String path) 指定路径的文件创建自定义图标。

4.fromResource (int resourceId) 使用已经存在的资源创建自定义图标。

先看一下要实现的效果:

 

Screenshot_2015-09-15-10-21-10 地图自带标记                    {A755B3A7-DBB4-4D10-BE5F-D8E07493EEE1} 实现效果


实现思路是:自定义布局,获取数据填入相应位置,然后将view转成Bitmap,调用AMap.addMarker(markerOptions) 方法添加到地图上。

  1. 自定义布局并填充数据:

  2.  

for (int i = 0; i < positionEneityList.size(); i++) {

    if (positionEneityList.get(i).getType().equals("1")) {

       View view = View.inflate(getActivity(),R.layout.view_day, null);

       TextView tv_price = (TextView) view.findViewById(R.id.tv_price);

       TextView tv_price_status = (TextView) view.findViewById(R.id.tv_price_status);

       tv_price.setText(positionEneityList.get(i).getPrice());

       tv_price_status.setText("元/时");

       Bitmap bitmap = CommentActivity.convertViewToBitmap(view);

       drawMarkerOnMap(new LatLng(Double.parseDouble(positionEneityList.get(i).getLatitude())

, Double.parseDouble(positionEneityList.get(i).getLongitude())), bitmap, positionEneityList.get(i).getId());

    }

 }


2.转成Bitmap:

//view 转bitmap

public static Bitmap convertViewToBitmap(View view) {

    view.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));

    view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());

    view.buildDrawingCache();

    Bitmap bitmap = view.getDrawingCache();

    return bitmap;

}

3.添加到地图上:

/**

 * 在地图上画marker

 *

 * @param point      marker坐标点位置(example:LatLng point = new LatLng(39.963175,

 *                   116.400244); )

 * @param markerIcon 图标

 * @return Marker对象

 */

private Marker drawMarkerOnMap(LatLng point, Bitmap markerIcon, String id) {

    if (aMap != null && point != null) {

        Marker marker = aMap.addMarker(new MarkerOptions().anchor(0.5f, 1)

                .position(point)

                .title(id)

                .icon(BitmapDescriptorFactory.fromBitmap(markerIcon)));

 

        return marker;

    }

    return null;

 

}


这样就实现了上述效果。

Android Fragment里嵌入高德地图定位的例子是基于地图的,我们后面会介绍嵌入高德地图的方法,具体的操作如下所示。


在上一篇已经写了嵌入高德地图,这里来说一下怎么实现定位,并显示定位的图标。

public class FragmentMap extends Fragment implements LocationSource, AMapLocationListener{

       private static FragmentMap fragment = null;

       @ViewInject(R.id.map)

       private MapView mapView;

       private AMap aMap;

       private View mapLayout;

       private OnLocationChangedListener mListener;

       private LocationManagerProxy mAMapLocationManager;

 

       public static Fragment newInstance() {

          if (fragment == null) {

             synchronized (FragmentMap.class) {

                 if (fragment == null) {

                      fragment = new FragmentMap();

 

                 }

           }

        }

       return fragment;

    }

 

    public View onCreateView(LayoutInflater inflater, ViewGroup container,

          Bundle savedInstanceState) {

          if (mapLayout == null) {

          mapLayout = inflater.inflate(R.layout.fragment_map, null);

          ViewUtils.inject(this, mapLayout);

          mapView.onCreate(savedInstanceState);

 

         if (aMap == null) {

              aMap = mapView.getMap();

              aMap.setLocationSource(this);// 设置定位监听

              aMap.getUiSettings().setMyLocationButtonEnabled(true);// 设置默认定位按钮是否显示

              aMap.setMyLocationEnabled(true);// 设置为true表示显示定位层并可触发定位,false表示隐藏定位层并不可触发定位,默认是false

              // 自定义系统定位蓝点

              MyLocationStyle myLocationStyle = new MyLocationStyle();

              // 自定义定位蓝点图标

              myLocationStyle.myLocationIcon(BitmapDescriptorFactory.fromResource(R.mipmap.content_btn_location));

             // 将自定义的 myLocationStyle 对象添加到地图上

             aMap.setMyLocationStyle(myLocationStyle);

             // 构造 LocationManagerProxy 对象

            mAMapLocationManager = LocationManagerProxy.getInstance(getActivity());

          }

          } else {

                  if (mapLayout.getParent() != null) {

                        ((ViewGroup) mapLayout.getParent()).removeView(mapLayout);

                  }

           }

      return mapLayout;

     }

   @Override

   public void onAttach(Activity activity) {

       super.onAttach(activity);

    }

 

   @Override

   public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

    }

 

  @Override

  public void onResume() {

      super.onResume();

      mapView.onResume();

   }

 

/**

* 方法必须重写

* map的生命周期方法

*/

  @Override

  public void onPause() {

       super.onPause();

       mapView.onPause();

       deactivate();

  }

 

/**

* 方法必须重写

* map的生命周期方法

*/

 @Override

 public void onSaveInstanceState(Bundle outState) {

      super.onSaveInstanceState(outState);

      mapView.onSaveInstanceState(outState);

 }

 

/**

* 方法必须重写

* map的生命周期方法

*/

 @Override

  public void onDestroy() {

     super.onDestroy();

     mapView.onDestroy();

  }

 

 @Override

 public void onLocationChanged(AMapLocation aMapLocation) {

      if (mListener != null &amp;amp;&amp;amp; aMapLocation != null) {

          if (aMapLocation.getAMapException().getErrorCode() == 0) {

               mListener.onLocationChanged(aMapLocation);// 显示系统小蓝点

 

              //获取位置信息

             geoLat = aMapLocation.getLatitude();

             geoLng = aMapLocation.getLongitude();

             aMap.moveCamera(CameraUpdateFactory.zoomTo(14));

 

          }

 

    }

 }

 

@Override

public void onLocationChanged(Location location) {

 

}

 

@Override

public void onStatusChanged(String provider, int status, Bundle extras) {

 

}

 

@Override

public void onProviderEnabled(String provider) {

 

}

 

@Override

public void onProviderDisabled(String provider) {

 

}

 

//激活定位

@Override

public void activate(OnLocationChangedListener listener) {

        mListener = listener;

        if (mAMapLocationManager == null) {

             mAMapLocationManager = LocationManagerProxy.getInstance(getActivity());

         //此方法为每隔固定时间会发起一次定位请求,为了减少电量消耗或网络流量消耗,

         //注意设置合适的定位时间的间隔,并且在合适时间调用removeUpdates()方法来取消定位请求

         //在定位结束后,在合适的生命周期调用destroy()方法

         //其中如果间隔时间为-1,则定位只定一次

          mAMapLocationManager.requestLocationData(LocationProviderProxy.AMapNetwork, 60 * 1000, 10, this);

        }

  }

 

//停止定位

@Override

public void deactivate() {

      mListener = null;

      if (mAMapLocationManager != null) {

           mAMapLocationManager.removeUpdates(this);

           mAMapLocationManager.destroy();

       }

     mAMapLocationManager = null;

    }

}

本文章来为各位介绍一篇关于Android开发之高德地图聚合Markers的例子,希望例子能够对各位朋友有用。

上一篇说了在地图上实现了自定义Markers,但是markers太多在地图上显示的就会密密麻麻,重叠覆盖,这里就介绍一下markers的聚合。先看一下封装好的聚合类。

 

public class MarkerClusterYellow {
    private Activity activity;
    private MarkerOptions options;
    private ArrayList<MarkerOptions>includeMarkers;
    private LatLngBounds bounds;// 创建区域
 
/**
*
* @param activity
* @param firstMarkers
* @param projection
* @param gridSize
* 区域大小参数
*/
   public MarkerClusterYellow(Activity activity, MarkerOptions firstMarkers,
         Projection projection, int gridSize) {
         options = new MarkerOptions();
         this.activity = activity;
         Point point = projection.toScreenLocation(firstMarkers.getPosition());
         Point southwestPoint = new Point(point.x - gridSize, point.y + gridSize);
         Point northeastPoint = new Point(point.x + gridSize, point.y - gridSize);
         bounds = new LatLngBounds(
         projection.fromScreenLocation(southwestPoint),
         projection.fromScreenLocation(northeastPoint));
         options.anchor(0.5f, 0.5f).title(firstMarkers.getTitle())
         .position(firstMarkers.getPosition())
         .icon(firstMarkers.getIcon())
         .snippet(firstMarkers.getSnippet());
         includeMarkers = new ArrayList<MarkerOptions>();
         includeMarkers.add(firstMarkers);
     }
 
/**
* 添加marker
*/
  public void addMarker(MarkerOptions markerOptions) {
      includeMarkers.add(markerOptions);// 添加到列表中
  }
 
/**
* 设置聚合点的中心位置以及图标
*/
public void setpositionAndIcon(String text) {
    String id="";
    int size = includeMarkers.size();
    if (size == 1) {
         return;
     }
   double lat = 0.0;
   double lng = 0.0;
   String snippet = "";
   for (MarkerOptions op : includeMarkers) {
       lat += op.getPosition().latitude;
       lng += op.getPosition().longitude;
       snippet += op.getTitle() + "\n";
       id=id+op.getTitle()+",";
    }
   options.position(new LatLng(lat / size, lng / size));// 设置中心位置为聚集点的平均距离
   options.title(id);
   options.snippet(snippet);
   int iconType = size / 2;
 
   switch (iconType) {
 
          default:
               options.icon(BitmapDescriptorFactory
               .fromBitmap(getViewBitmap(getView(size,text,
               R.mipmap.content_icon_positions_yellow))));
          break;
         }
    }
 
   public LatLngBounds getBounds() {
       return bounds;
   }
 
   public MarkerOptions getOptions() {
        return options;
   }
 
   public void setOptions(MarkerOptions options) {
          this.options = options;
   }
 
   public View getView(int carNum,String text,int resourceId) {
        View view = activity.getLayoutInflater().inflate(R.layout.my_car_cluster_view, null);
        TextView carNumTextView = (TextView) view.findViewById(R.id.my_car_num);
        TextView tv_price = (TextView) view.findViewById(R.id.tv_price);
        TextView tv_price_status = (TextView) view.findViewById(R.id.tv_price_status);
        tv_price.setText(text);
        tv_price_status.setText("元/天");
        tv_price.setTextColor(Color.parseColor("#FFBB18"));
        tv_price_status.setTextColor(Color.parseColor("#FFBB18"));
        LinearLayout myCarLayout = (LinearLayout) view.findViewById(R.id.my_car_bg);
        myCarLayout.setBackgroundResource(resourceId);
        carNumTextView.setText(String.valueOf(carNum));
        return view;
   }
 
/**
* 把一个view转化成bitmap对象
*/
public static Bitmap getViewBitmap(View view) {view.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
         MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
        view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
        view.buildDrawingCache();
        Bitmap bitmap = view.getDrawingCache();
        return bitmap;
     }
}

在前一篇博客的基础上我们进行聚合,只需要做以下操作:

public class FragmentMap extends Fragment implements LocationSource, AMapLocationListener,OnCameraChangeListener {

     private static FragmentMap fragment = null;

     @ViewInject(R.id.map)

     private MapView mapView;

     private AMap aMap;

     private View mapLayout;

     private OnLocationChangedListener mListener;

     private LocationManagerProxy mAMapLocationManager;

     private List<PositionEneity> positionEneityList = new ArrayList<PositionEneity>();

     private ArrayList<MarkerOptions> markerOptionsListYellow = new ArrayList<MarkerOptions>();// 所有的marker

     private ArrayList<MarkerOptions> markerOptionsListInViewYellow= new ArrayList<MarkerOptions>();// 视野内的marker

     String yellow="";

     private int height;// 屏幕高度(px)

     private int width;// 屏幕宽度(px)

     private int gridSize = 50;// marker点区域大小

 

    Handler handler = new Handler() {

      @Override

      public void handleMessage(android.os.Message msg) {

          super.handleMessage(msg);

          if (msg.what == 0) {

              resetMarks();// 更新markers

           }

      }

 };

 

   public static Fragment newInstance() {

        if (fragment == null) {

            synchronized (FragmentMap.class) {

               if (fragment == null) {

                  fragment = new FragmentMap();

 

             }

        }

     }

       return fragment;

 }

 

public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {

      if (mapLayout == null) {

         mapLayout = inflater.inflate(R.layout.fragment_map, null);

         ViewUtils.inject(this, mapLayout);

         mapView.onCreate(savedInstanceState);

         DisplayMetrics dm = new DisplayMetrics();

         getActivity().getWindowManager().getDefaultDisplay().getMetrics(dm);

         width = dm.widthPixels;

         height = dm.heightPixels;

              if (aMap == null) {

                  aMap = mapView.getMap();

                  aMap.setLocationSource(this);// 设置定位监听

                  aMap.getUiSettings().setMyLocationButtonEnabled(true);// 设置默认定位按钮是否显示

                  aMap.setMyLocationEnabled(true);// 设置为true表示显示定位层并可触发定位,false表示隐藏定位层并不可触发定位,默认是false

 

             }

         } else {

               if (mapLayout.getParent() != null) {

                  ((ViewGroup) mapLayout.getParent()).removeView(mapLayout);

                }

          }

 

         aMap.setOnCameraChangeListener(this);

      return mapLayout;

}

 /**

 * 获取视野内的marker 根据聚合算法合成自定义的marker 显示视野内的marker

 */

<strong> private void resetMarks() {

 // 开始刷新界面

     Projection projection = aMap.getProjection();

     Point p = null;

     markerOptionsListInViewYellow.clear();

 // 获取在当前视野内的marker;提高效率

     for (MarkerOptions mp : markerOptionsListYellow) {

     p = projection.toScreenLocation(mp.getPosition());

     if (p.x &lt; 0 || p.y &lt; 0 || p.x &gt; width || p.y &gt; height) {

 // 不添加到计算的列表中

      } else {

         markerOptionsListInViewYellow.add(mp);

      }

 }

 

 // 自定义的聚合类MarkerCluster

   ArrayList&lt;MarkerClusterYellow&gt; clustersMarkeryellow = new ArrayList&lt;MarkerClusterYellow&gt;();

   for (MarkerOptions mp : markerOptionsListInViewYellow) {

          if (clustersMarkeryellow.size() == 0) {

              clustersMarkeryellow.add(new MarkerClusterYellow(getActivity(), mp,

                projection, gridSize));//gridSize 根据自己需求调整

          } else {

               boolean isIn = false;

               for (MarkerClusterYellow cluster : clustersMarkeryellow) {

               if (cluster.getBounds().contains(mp.getPosition())) {

                   cluster.addMarker(mp);

                   isIn = true;

                   break;

                 }

          }

      if (!isIn) {

            clustersMarkeryellow.add(new MarkerClusterYellow(getActivity(), mp, projection, gridSize));

                 }

         }

 }

 

 // 先清除地图上所有覆盖物

     aMap.clear();

     for (MarkerClusterYellow markerClusterYellow : clustersMarkeryellow) {

            markerClusterYellow.setpositionAndIcon(yellow);// 设置聚合点的位置和icon

            aMap.addMarker(markerClusterYellow.getOptions());// 重新添加

          }

  

 }

 private void initview() {

 for (int i = 0; i < positionEneityList.size(); i++) {

       if (positionEneityList.get(i).getType().equals("2")) {

             yellow=positionEneityList.get(i).getPrice();

             View view01 = View.inflate(getActivity(),R.layout.view_everyday, null);

             TextView tv_price = (TextView) view01.findViewById(R.id.tv_price);

             TextView tv_price_status = (TextView) view01.findViewById(R.id.tv_price_status);

             tv_price.setText(positionEneityList.get(i).getPrice());

             tv_price_status.setText("元/天");

             Bitmap bitmap = CommentActivity.convertViewToBitmap(view01);

           <strong>  markerOptionsListYellow.add(new MarkerOptions() .position(new LatLng(Double.parseDouble(positionEneityList.get(i).getLatitude())

 , Double.parseDouble(positionEneityList.get(i).getLongitude()))).icon(BitmapDescriptorFactory.fromBitmap(bitmap))

 .title(positionEneityList.get(i).getId()));

           }

       }

 }

 

 

 @Override

 public void onCameraChange(CameraPosition cameraPosition) {

 

 }

 

 @Override

 public void onCameraChangeFinish(CameraPosition cameraPosition) {

 

      handler.sendEmptyMessage(0);// 更新界面marker

 }

}


定位和地图显示部分请参考之前的博客:

本文章为各位介绍一篇关于Android开发之百分比布局库的例子,希望这个例子能够为各位同学带来有效的帮助。


为了解决android手机适配问题,我们经常想如果可以按照百分比的方式进行界面布局,这样适配各种屏幕就简单多了吧!现在谷歌正式提供百分比布局支持库(android-support-percent-lib)。

这个库提供了:

两种布局供大家使用: PercentRelativeLayout、PercentFrameLayout,通过名字就可以看出,这是继承自FrameLayout和RelativeLayout两个容器类;

支持的属性有:

layout_widthPercent、layout_heightPercent、

layout_marginPercent、layout_marginLeftPercent、

layout_marginTopPercent、layout_marginRightPercent、

layout_marginBottomPercent、layout_marginStartPercent、layout_marginEndPercent。

可以看到支持宽高,以及margin。

也就是说,大家只要在开发过程中使用PercentRelativeLayout、PercentFrameLayout替换FrameLayout、RelativeLayout即可。

使用:

关于使用,其实及其简单,并且github上也有例子,android-percent-support-lib-sample。

使用Android studio在build.gradle添加以下信息就可以获取支持库,当然了,如果你没有下载到该支持库会提示你下载。

{5330C3E9-D43A-40E0-A247-83C217BE9A84}

PercentRelativeLayout使用小例子:

布局文件如下:

 <android.support.percent.PercentRelativeLayout

    xmlns:android="
http://schemas.android.com/apk/res/android
"

    xmlns:app="
http://schemas.android.com/apk/res-auto
"

    android:layout_width="match_parent"

    android:layout_height="match_parent">

 

    <TextView

        android:id="@+id/row_one_item_one"

        android:layout_width="0dp"

        android:layout_height="0dp"

        android:layout_alignParentTop="true"

        android:background="#7700ff00"

        android:text="w:70%,h:20%"

        android:gravity="center"

        app:layout_heightPercent="20%"

        app:layout_widthPercent="70%"/>

 

    <TextView

        android:id="@+id/row_one_item_two"

        android:layout_width="0dp"

        android:layout_height="0dp"

        android:layout_toRightOf="@+id/row_one_item_one"

        android:background="#396190"

        android:text="w:30%,h:20%"

        app:layout_heightPercent="20%"

        android:gravity="center"

        app:layout_widthPercent="30%"/>

 

 

    <ImageView

        android:id="@+id/row_two_item_one"

        android:layout_width="match_parent"

        android:layout_height="0dp"

        android:scaleType="centerCrop"

        android:layout_below="@+id/row_one_item_one"

        android:background="#d89695"

        app:layout_heightPercent="70%"/>

 

    <TextView

        android:layout_width="0dp"

        android:layout_height="0dp"

        android:layout_below="@id/row_two_item_one"

        android:background="#770000ff"

        android:gravity="center"

        android:text="width:100%,height:10%"

        app:layout_heightPercent="10%"

        app:layout_widthPercent="100%"/>

 

</android.support.percent.PercentRelativeLayout

效果图如下

 

Screenshot_2015-09-16-12-02-58

 

因为没有LinearLayout我们可以自己来自定义。刚好在网上看到有自定义好的PercentLinearlayout,分享给大家

public class PercentLinearlayout extends LinearLayout{

    private PercentLayoutHelper mPercentLayoutHelper;

 

    public PercentLinearlayout(Context context, AttributeSet attrs)

    {

        super(context, attrs);

 

        mPercentLayoutHelper = new PercentLayoutHelper(this);

    }

 

 

    @Override

    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)

    {

        mPercentLayoutHelper.adjustChildren(widthMeasureSpec, heightMeasureSpec);

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        if (mPercentLayoutHelper.handleMeasuredStateTooSmall())

        {

            super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        }

    }

 

    @Override

    protected void onLayout(boolean changed, int l, int t, int r, int b)

    {

        super.onLayout(changed, l, t, r, b);

        mPercentLayoutHelper.restoreOriginalParams();

    }

 

    @Override

    public LayoutParams generateLayoutParams(AttributeSet attrs)

    {

        return new LayoutParams(getContext(), attrs);

    }

 

 

    public static class LayoutParams extends LinearLayout.LayoutParams

            implements PercentLayoutHelper.PercentLayoutParams

    {

        private PercentLayoutHelper.PercentLayoutInfo mPercentLayoutInfo;

 

        public LayoutParams(Context c, AttributeSet attrs)

        {

            super(c, attrs);

            mPercentLayoutInfo = PercentLayoutHelper.getPercentLayoutInfo(c, attrs);

        }

 

        @Override

        public PercentLayoutHelper.PercentLayoutInfo getPercentLayoutInfo()

        {

            return mPercentLayoutInfo;

        }

 

        @Override

        protected void setBaseAttributes(TypedArray a, int widthAttr, int heightAttr)

        {

            PercentLayoutHelper.fetchWidthAndHeight(this, a, widthAttr, heightAttr);

        }

 

        public LayoutParams(int width, int height) {

            super(width, height);

        }

 

 

        public LayoutParams(ViewGroup.LayoutParams source) {

            super(source);

        }

 

        public LayoutParams(MarginLayoutParams source) {

            super(source);

        }

 

    }

 

 

}


使用效果如下:

 

Screenshot_2015-09-16-12-10-06

本文主要 介绍Android 开发中的两个UI控件RecyclerView,CardView,及这两个控件的导入导出功能。

先上效果图:


原理图:


这是RecycleView的工作原理:
1.LayoutManager用来处理RecycleView的“列表”样式,Support包默认包含了:LinearLayoutManager  横向或纵向的滚动列表、
GridLayoutManager  网格列表、StaggeredGridLayoutManager  交错的网格列表。
2.Adapter负责处理RecycleView的数据和样式
3.在传统的ListView中有一种常见的写法是使用ViewHolder来缓存数据集,在新版的RecycleView内置了ViewHolder这一模块,所以在Adapter内部新建内部类ViewHolder。
4.RecycleView 和listView的一个区别就是本身不处理点击事件,点击事件应该绑在ViewHolder里面,可以直接写也可以通过接口绑在Adapter里面来实现。

 
首先添加数据集:

package com.lfk.drawapictiure.Info;
/**
 * Created by liufengkai on 15/9/13.
 */
public class MenuInfo {
    private String paint_name;
    private String paint_time;
    private String paint_root;
    private String paint_img_root;
    public MenuInfo(String paint_name, String paint_time,
                    String paint_root, String paint_img_root) {
        this.paint_name = paint_name;
        this.paint_time = paint_time;
        this.paint_root = paint_root;
        this.paint_img_root = paint_img_root;
    }
    public String getPaint_name() {
        return paint_name;
    }
    public String getPaint_time() {
        return paint_time;
    }
    public String getPaint_root() {
        return paint_root;
    }
    public String getPaint_img_root() {
        return paint_img_root;
    }
}

 
实现继承自RecycleView的Adapter中间要包裹自己实现的ViewHolder,onCreateviewHolder函数和onBindViewHolder实现了ListView里面getView的工作,分别为找到控件和控件赋值,

实现点击的接口,设置接口并且绑在ViewHolder的itemView里面即根视图中。

public class MainLayoutAdapter extends RecyclerView.Adapter<MainLayoutAdapter.MainViewHolder> {
    private LayoutInflater inflater;
    private ArrayList<MenuInfo> userList;
    private Context context;
    private MainItemClickListener itemClickListener;
    public MainLayoutAdapter(ArrayList<MenuInfo> userList, Context context) {
        this.userList = userList;
        this.context = context;
        this.inflater = LayoutInflater.from(context);
    }
    public void setItemClickListener(MainItemClickListener itemClickListener) {
        this.itemClickListener = itemClickListener;
    }
  //onCreateviewHolder函数和onBindViewHolder实现了ListView里面getView的工作,分别为找到控件和控件赋值
    @Override
    public MainLayoutAdapter.MainViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View wrapper = inflater.inflate(R.layout.draw_item, parent, false);
        return new MainViewHolder(
                wrapper,
                (TextView)wrapper.findViewById(R.id.paint_name),
                (TextView)wrapper.findViewById(R.id.paint_time),
                (TextView)wrapper.findViewById(R.id.paint_root),
                (ImageView)wrapper.findViewById(R.id.paint_img));
    }
    @Override
    public void onBindViewHolder(MainViewHolder holder, int position) {
        MenuInfo menuInfo = userList.get(position);
        holder.paint_img.setImageURI(Uri.parse(menuInfo.getPaint_img_root()));
        holder.paint_name.setText(menuInfo.getPaint_name());
        holder.paint_time.setText(menuInfo.getPaint_time());
        holder.paint_root.setText(menuInfo.getPaint_root());
    }
    @Override
    public int getItemCount() {
        return userList.size();
    }
    public class MainViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener,View.OnLongClickListener{
        private TextView paint_name;
        private TextView paint_time;
        private TextView paint_root;
        private ImageView paint_img;
        public MainViewHolder(View itemView, TextView paint_name,
                          TextView paint_time, TextView paint_root,
                          ImageView paint_img) {
            super(itemView);
            itemView.setOnClickListener(this);
            this.paint_name = paint_name;
            this.paint_time = paint_time;
            this.paint_root = paint_root;
            this.paint_img = paint_img;
        }
        @Override
        public void onClick(View view) {
            MenuInfo menuInfo = userList.get(getAdapterPosition());
            itemClickListener.onItemClick(view,menuInfo.getPaint_name(),menuInfo.getPaint_root());
        }
        @Override
        public boolean onLongClick(View view) {
            return false;
        }
    }
}


Activity中的使用:

package com.lfk.drawapictiure.Fragment;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.lfk.drawapictiure.Adapter.MainLayoutAdapter;
import com.lfk.drawapictiure.Info.MenuInfo;
import com.lfk.drawapictiure.InterFace.MainItemClickListener;
import com.lfk.drawapictiure.MainActivity;
import com.lfk.drawapictiure.R;
import java.util.ArrayList;
public class PaintFragment extends android.support.v4.app.Fragment {
    private RecyclerView mRecyclerView;
    private MainLayoutAdapter mAdapter;
    private RecyclerView.LayoutManager mLayoutManager;
    private String path = Environment.getExternalStorageDirectory().getPath() + "/DrawAPicture";
    public static PaintFragment newInstance() {
        return new PaintFragment();
    }
    public PaintFragment() {
        // Required empty public constructor
    }
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View wrapper = inflater.inflate(R.layout.fragment_paint, container, false);
        mRecyclerView = (RecyclerView)wrapper.findViewById(R.id.paint_recycle_view);
        mLayoutManager = new LinearLayoutManager(getActivity());
        mRecyclerView.setLayoutManager(mLayoutManager); //绑上列表管理器
        ArrayList<MenuInfo> arrayList = new ArrayList<>();
        arrayList.add(new MenuInfo("刘丰恺","09-13 05:28",path+"/"+"12138.lfk",path+"/"+"6826.jpg"));
        arrayList.add(new MenuInfo("刘丰恺","09-13 05:28",path+"/"+"12138.lfk",path+"/"+"6826.jpg"));
        arrayList.add(new MenuInfo("刘丰恺","09-13 05:28",path+"/"+"12138.lfk",path+"/"+"6826.jpg"));
        arrayList.add(new MenuInfo("刘丰恺","09-13 05:28",path+"/"+"12138.lfk",path+"/"+"6826.jpg"));
        mAdapter = new MainLayoutAdapter(arrayList, getActivity());
      // 设置点击事件
        mAdapter.setItemClickListener(new MainItemClickListener() {
            @Override
            public void onItemClick(View view, String name, String path) {
                Intent intent = new Intent(getActivity(), MainActivity.class);
                intent.setData(Uri.parse(path));
                startActivity(intent);
            }
        });
      //绑定数据集
        mRecyclerView.setAdapter(mAdapter);
        return wrapper;
    }
}


其中的子布局使用了CardView:

我设置的东西只有:

card_view:cardCornerRadius="4dp"  //设定圆角半径
card_view:cardElevation="8dp"//设定阴影
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:background="@drawable/list_item_selector"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    card_view:cardCornerRadius="4dp"
    card_view:
    android:layout_margin="@dimen/card_margin">
    <RelativeLayout
        android:layout_marginTop="16dp"
        android:layout_marginLeft="16dp"
        android:layout_marginRight="16dp"
        android:layout_marginBottom="16dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <ImageView
            android:maxHeight="100dp"
            android:layout_marginTop="8dp"
            android:layout_below="@+id/line_view"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/paint_img"
            android:src="@mipmap/ic_launcher" />
        <TextView
            android:id="@+id/paint_name"
            android:textColor="#000"
            android:textSize="18sp"
            android:text="项目名"
            android:layout_alignParentRight="true"
            android:singleLine="true"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
        <TextView
            android:id="@+id/paint_time"
            android:text="项目时间"
            android:textColor="@color/black"
            android:textSize="18sp"
            android:singleLine="true"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
        <View
            android:id="@+id/line_view"
            android:background="@color/gray"
            android:layout_below="@+id/paint_time"
            android:layout_width="match_parent"
            android:layout_height="1dp"/>
        <TextView
            android:id="@+id/paint_root"
            android:visibility="invisible"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    </RelativeLayout>
</android.support.v7.widget.CardView>




Android L——RecyclerView,CardView导入和使用

这篇文章是ANDROID L——Material Design详解(UI控件)的一个补充或者说是应用实例,如果有时间建议大家稍微浏览一下上篇文章。

本文主要介绍Android L新增加的两个UI控件RecyclerView,CardView的导入和使用。
RecyclerView是ListView的升级版
CardView则是Google提供的一个卡片式视图组件


本例就是使用RecyclerView来展示多个CardView的一个小例子,先看下效果图:



导入RecyclerView,CardView


由于RecyclerView,CardView是放在support library v7包中,所以我们想要使用就必须要导包。

下面就介绍下在Eclipse和Android Studio中是如何导入这两个包的。


Eclipse:




第一步:通过SDK manager下载/更新Android Support Libraries(5.0版本最新为21)



第二步:导入CardView和RecyclerView项目(都在support v7中)

1.在Eclipse中点击Import,导入Android项目

2.导入CardView和RecycleView,路径为your sdk path\extras\android\support\v7\cardview(RecycleView则为相同目录下的recyclerview)

3.导入时记得将工程copy到本地并建议重命名,这样方便以后管理例如:



第三步:设置Library

1..将两个工程设置为Library
2..在主工程中引入这两个Library例如:



通过这三步就可以将这两个包导入进来了。



Android Studio

Android Stuido相对于Eclipse简单的多:

第一步:

首先要确保已经将Android Support Libraries升级到最新.


第二步:

打开项目中的build.gradle文件,在dependencies中添加如下代码。

dependencies {
    compile 'com.android.support:recyclerview-v7:21.+'
    compile 'com.android.support:cardview-v7:21.+'
}


第三步:

重新Build一下工程。

Build完成后就会发现这两个包就已经导入进来了



代码介绍:

主题:

首先这个黑色基调的主题是使用了Material.Dark.ActionBar样式。


设置方法:修改values-v21文件夹下styles.xml文件:

<resources>
    <style name="AppTheme" parent="android:ThemeOverlay.Material.Dark.ActionBar">
    </style>
</resources>


布局文件:

recycler_view.xml(RecyclerView布局文件):

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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"
    tools:context=".MyActivity">
    <android.support.v7.widget.RecyclerView
        android:id="@+id/list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MyActivity" />
</FrameLayout>


FrameLayout里包含了RecyclerView控件


card_view.xml(CardView布局文件):

<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="5dp"
    android:orientation="horizontal"
    card_view:cardBackgroundColor="@color/cardview_dark_background"
    card_view:cardCornerRadius="5dp" >
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:padding="5dp" >
        <ImageView
            android:id="@+id/pic"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_centerInParent="true"
            android:scaleType="centerCrop" />
        <TextView
            android:clickable="true"
            android:id="@+id/name"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginBottom="10dp"
            android:layout_marginRight="10dp"
            android:gravity="right|bottom"
            android:textColor="@android:color/white"
            android:textSize="24sp" />
    </RelativeLayout>
</android.support.v7.widget.CardView>


CardView视图中包含了一个ImageView和一个TextView分别显示图片和文字信息


唯一需要介绍的就是在布局文件中使用了,如下两个属性:

 card_view:cardBackgroundColor="@color/cardview_dark_background"
    card_view:cardCornerRadius="5dp"

他俩的作用分别是设置CardView的背景颜色和外围的圆角大小(注意要使用card_view命名空间)


代码:

Actor类(封装数据的Model类):

public class Actor
{
    String name;
    String picName;
    public Actor(String name, String picName)
    {
        this.name = name;
        this.picName = picName;
    }
    public int getImageResourceId( Context context )
    {
        try
        {
            return context.getResources().getIdentifier(this.picName, "drawable", context.getPackageName());
        }
        catch (Exception e)
        {
            e.printStackTrace();
            return -1;
        }
    }
}


封装了演员的名字和图片名,getImageResourceId()方法的作用就是根据图片命找到系统资源

MyActivity(程序主控制Activity)

public class MyActivity
    extends Activity
{
    private RecyclerView mRecyclerView;
    private MyAdapter myAdapter;
    private List<Actor> actors = new ArrayList<Actor>();
    private String[] names = { "朱茵", "张柏芝", "张敏", "巩俐", "黄圣依", "赵薇", "莫文蔚", "如花" };
    private String[] pics = { "p1", "p2", "p3", "p4", "p5", "p6", "p7", "p8" };
    @Override
    protected void onCreate( Bundle savedInstanceState )
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.recycler_view);
        actors.add(new Actor("朱茵", "p1"));
        getActionBar().setTitle("那些年我们追的星女郎");
        // 拿到RecyclerView
        mRecyclerView = (RecyclerView) findViewById(R.id.list);
        // 设置LinearLayoutManager
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
        // 设置ItemAnimator
        mRecyclerView.setItemAnimator(new DefaultItemAnimator());
        // 设置固定大小
        mRecyclerView.setHasFixedSize(true);
        // 初始化自定义的适配器
        myAdapter = new MyAdapter(this, actors);
        // 为mRecyclerView设置适配器
        mRecyclerView.setAdapter(myAdapter);
    }
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu, menu);
        return true;
    }
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch(item.getItemId()) {
            // 当点击actionbar上的添加按钮时,向adapter中添加一个新数据并通知刷新
            case R.id.action_add:
                if (myAdapter.getItemCount() != names.length) {
                    actors.add(new Actor(names[myAdapter.getItemCount()], pics[myAdapter.getItemCount()]));
                    mRecyclerView.scrollToPosition(myAdapter.getItemCount() - 1);
                    myAdapter.notifyDataSetChanged();
                }
                return true;
            // 当点击actionbar上的删除按钮时,向adapter中移除最后一个数据并通知刷新
            case R.id.action_remove:
                if (myAdapter.getItemCount() != 0) {
                    actors.remove(myAdapter.getItemCount()-1);
                    mRecyclerView.scrollToPosition(myAdapter.getItemCount() - 1);
                    myAdapter.notifyDataSetChanged();
                }
                return true;
        }
        return super.onOptionsItemSelected(item);
    }
}



MyAdapter(自定义适配器类)

public class MyAdapter
    extends RecyclerView.Adapter<MyAdapter.ViewHolder>
{
    private List<Actor> actors;
    private Context mContext;
    public MyAdapter( Context context , List<Actor> actors)
    {
        this.mContext = context;
        this.actors = actors;
    }
    @Override
    public ViewHolder onCreateViewHolder( ViewGroup viewGroup, int i )
    {
        // 给ViewHolder设置布局文件
        View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.card_view, viewGroup, false);
        return new ViewHolder(v);
    }
    @Override
    public void onBindViewHolder( ViewHolder viewHolder, int i )
    {
        // 给ViewHolder设置元素
        Actor p = actors.get(i);
        viewHolder.mTextView.setText(p.name);
        viewHolder.mImageView.setImageDrawable(mContext.getDrawable(p.getImageResourceId(mContext)));
    }
    @Override
    public int getItemCount()
    {
        // 返回数据总数
        return actors == null ? 0 : actors.size();
    }
    // 重写的自定义ViewHolder
    public static class ViewHolder
        extends RecyclerView.ViewHolder
    {
        public TextView mTextView;
        public ImageView mImageView;
        public ViewHolder( View v )
        {
            super(v);
            mTextView = (TextView) v.findViewById(R.id.name);
            mImageView = (ImageView) v.findViewById(R.id.pic);
        }
    }
}


所有代码介绍完毕了,可以总结为以下两点:

RecyclerView:

理解为之前的ListView,不过需要设置LinearLayoutManager(目前资料不多我也有点迷糊以后再补充)和ItemAnimator(为每个条目设置操作动画)两个新属性

RecyclerView.Adapter:

理解为默认自带和基于ViewHolder的新的适配器,只不过回调方法稍有不同,但本质都是一样的。

[!--infotagslink--]

相关文章

  • Android子控件超出父控件的范围显示出来方法

    下面我们来看一篇关于Android子控件超出父控件的范围显示出来方法,希望这篇文章能够帮助到各位朋友,有碰到此问题的朋友可以进来看看哦。 <RelativeLayout xmlns:an...2016-10-02
  • C#创建自定义控件及添加自定义属性和事件使用实例详解

    这篇文章主要给大家介绍了关于C#创建自定义控件及添加自定义属性和事件使用的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用C#具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧...2020-06-25
  • JS实现自定义简单网页软键盘效果代码

    本文实例讲述了JS实现自定义简单网页软键盘效果。分享给大家供大家参考,具体如下:这是一款自定义的简单点的网页软键盘,没有使用任何控件,仅是为了练习JavaScript编写水平,安全性方面没有过多考虑,有顾虑的可以不用,目的是学...2015-11-08
  • JS中引用百度地图并将百度地图的logo和信息去掉

    采用CSS覆盖的方法就可以了,但是官方是不允许这么做的...2013-10-13
  • Android开发中findViewById()函数用法与简化

    findViewById方法在android开发中是获取页面控件的值了,有没有发现我们一个页面控件多了会反复研究写findViewById呢,下面我们一起来看它的简化方法。 Android中Fin...2016-09-20
  • Android模拟器上模拟来电和短信配置

    如果我们的项目需要做来电及短信的功能,那么我们就得在Android模拟器开发这些功能,本来就来告诉我们如何在Android模拟器上模拟来电及来短信的功能。 在Android模拟...2016-09-20
  • 夜神android模拟器设置代理的方法

    夜神android模拟器如何设置代理呢?对于这个问题其实操作起来是非常的简单,下面小编来为各位详细介绍夜神android模拟器设置代理的方法,希望例子能够帮助到各位。 app...2016-09-20
  • android自定义动态设置Button样式【很常用】

    为了增强android应用的用户体验,我们可以在一些Button按钮上自定义动态的设置一些样式,比如交互时改变字体、颜色、背景图等。 今天来看一个通过重写Button来动态实...2016-09-20
  • Android WebView加载html5页面实例教程

    如果我们要在Android应用APP中加载html5页面,我们可以使用WebView,本文我们分享两个WebView加载html5页面实例应用。 实例一:WebView加载html5实现炫酷引导页面大多...2016-09-20
  • 深入理解Android中View和ViewGroup

    深入理解Android中View和ViewGroup从组成架构上看,似乎ViewGroup在View之上,View需要继承ViewGroup,但实际上不是这样的。View是基类,ViewGroup是它的子类。本教程我们深...2016-09-20
  • openlayers6之地图覆盖物overlay详解

    overlay就是在地图上以另外一种形式浮现在地图上,常见的地图覆盖物为这三种类型,如:popup 弹窗、label标注信息、text文本信息等,接下来跟随小编看下openlayers6之地图覆盖物overlay详解,一起看看吧...2021-09-15
  • Android自定义WebView网络视频播放控件例子

    下面我们来看一篇关于Android自定义WebView网络视频播放控件开发例子,这个文章写得非常的不错下面给各位共享一下吧。 因为业务需要,以下代码均以Youtube网站在线视...2016-10-02
  • 自定义jquery模态窗口插件无法在顶层窗口显示问题

    自定义一个jquery模态窗口插件,将它集成到现有平台框架中时,它只能在mainFrame窗口中显示,无法在顶层窗口显示. 解决这个问题的办法: 通过以下代码就可能实现在顶层窗口弹窗 复制代码 代码如下: $(window.top.documen...2014-05-31
  • Android用MemoryFile文件类读写进行性能优化

    java开发的Android应用,性能一直是一个大问题,,或许是Java语言本身比较消耗内存。本文我们来谈谈Android 性能优化之MemoryFile文件读写。 Android匿名共享内存对外A...2016-09-20
  • 自定义feignClient的常见坑及解决

    这篇文章主要介绍了自定义feignClient的常见坑及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-10-20
  • Android设置TextView竖着显示实例

    TextView默认是横着显示了,今天我们一起来看看Android设置TextView竖着显示如何来实现吧,今天我们就一起来看看操作细节,具体的如下所示。 在开发Android程序的时候,...2016-10-02
  • pytorch 自定义卷积核进行卷积操作方式

    今天小编就为大家分享一篇pytorch 自定义卷积核进行卷积操作方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-05-06
  • android.os.BinderProxy cannot be cast to com解决办法

    本文章来给大家介绍关于android.os.BinderProxy cannot be cast to com解决办法,希望此文章对各位有帮助呀。 Android在绑定服务的时候出现java.lang.ClassCastExc...2016-09-20
  • Android 实现钉钉自动打卡功能

    这篇文章主要介绍了Android 实现钉钉自动打卡功能的步骤,帮助大家更好的理解和学习使用Android,感兴趣的朋友可以了解下...2021-03-15
  • 如何根据百度地图计算出两地之间的驾驶距离(两种语言js和C#)

    以下是使用js代码实现百度地图计算两地距离,代码如下所示:<script src="js/jquery-1.9.0.js" type="text/javascript" language="javascript"></script><script language="javascript" type="text/javascript" src="js/...2015-10-30