我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Android 高仿微信朋友圈动态支持双击手势放大并滑动查看图片效果

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Android 高仿微信朋友圈动态支持双击手势放大并滑动查看图片效果

最近参与了开发一款旅行APP,其中包含实时聊天和动态评论功能,终于耗时几个月几个伙伴完成了,今天就小结一下至于实时聊天功能如果用户不多的情况可以scoket实现,如果用户万级就可以采用开源的smack + opnefile实现,也可以用mina开源+XMMP,至于怎么搭建和实现,估计目前github上一搜一大把,至于即时通讯怕误人子弟,暂且不做介绍,现就把实现的一个微信朋友圈的小功能介绍一下。

   先上效果图:

一拿到主流的UI需求,大致分析下,需要我ListView嵌套Gridview,而gridView的行数也和图片总数有关系,因此通过个数我们可以动态设置条目的宽高,而点击图片放大我们可一跳转到另一界面,图片左右滑动可以用viewpager实现,双击图片放大和手指缩放图片也可以用就监听手势进行不断放大,对于安卓事件不熟悉的朋友可以直接使用一个著名的photoVIew开源项目,支持手势缩放图片和滑动图片实现画廊功能,也很好的解决了内存溢出问题。

      一 配置ImageLoader       

       本项目中加载网络图片我就直接使用imageLoader,但建议还是去看下源码,因为开源项目本身自带缓存机制,有很好的缓存技巧,有很多东西值得我们借鉴。其不仅可以加载本地图片(文件path),也支持加载网络图片(url),并且自带防止内存溢出功能。


public class MyApplication extends Application { 
  @Override 
  public void onCreate() { 
    super.onCreate(); 
    DisplayImageOptions defaultOptions = new DisplayImageOptions 
        .Builder() 
        .showImageForEmptyUri(R.drawable.empty_photo)  
        .showImageOnFail(R.drawable.empty_photo)  
        .cacheInMemory(true) 
        .cacheOnDisc(true) 
        .build(); 
    ImageLoaderConfiguration config = new ImageLoaderConfiguration 
        .Builder(getApplicationContext()) 
        .defaultDisplayImageOptions(defaultOptions) 
        .discCacheSize(50 * 1024 * 1024)// 
        .discCacheFileCount(100)//缓存一百张图片 
        .writeDebugLogs() 
        .build(); 
    ImageLoader.getInstance().init(config); 
  } 
} 

 二 准备主界面和需要的基础类

  1  Listadapter


public class FridListAdapter extends BaseAdapter{ 
  private ArrayList<MyBean> mList; 
  private LayoutInflater mInflater; 
  private Context mContext; 
  public FridListAdapter(Context context,ArrayList<MyBean> list) { 
    mInflater = LayoutInflater.from(context); 
    mContext=context; 
    this.mList=list; 
  } 
  @Override 
  public int getCount() { 
    return mList==null?0:mList.size(); 
  } 
  @Override 
  public MyBean getItem(int position) { 
    return mList.get(position); 
  } 
  @Override 
  public long getItemId(int position) { 
    return getItem(position).id; 
  } 
  @Override 
  public View getView(int position, View convertView, ViewGroup parent) { 
    ViewHolder holder; 
    if (convertView == null) { 
      holder = new ViewHolder(); 
      convertView = mInflater.inflate(R.layout.list_item, null); 
      holder.avator=(ImageView)convertView.findViewById(R.id.avator); 
      holder.name=(TextView)convertView.findViewById(R.id.name); 
      holder.content = (TextView) convertView.findViewById(R.id.content); 
      holder.gridView=(NoScrollGridView)convertView.findViewById(R.id.gridView); 
      convertView.setTag(holder); 
    } else { 
      holder = (ViewHolder) convertView.getTag(); 
    } 
    final MyBean bean = getItem(position); 
    //加载网络图片 
    ImageLoader.getInstance().displayImage(bean.avator, holder.avator); 
    holder.name.setText(bean.name); 
    holder.content.setText(bean.content); 
    if(bean.urls!=null&&bean.urls.length>0){ 
      holder.gridView.setVisibility(View.VISIBLE); 
      holder.gridView.setAdapter(new DynamicGridAdapter(bean.urls, mContext)); 
      holder.gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() { 
        @Override 
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 
          imageBrower(position,bean.urls); 
        } 
      }); 
    }else{ 
      holder.gridView.setVisibility(View.GONE); 
    } 
    return convertView; 
  } 
  private void imageBrower(int position, String[] urls) { 
    Intent intent = new Intent(mContext, ImagePagerActivity.class); 
    // 图片url,为了演示这里使用常量,一般从数据库中或网络中获取 
    intent.putExtra(ImagePagerActivity.EXTRA_IMAGE_URLS, urls); 
    intent.putExtra(ImagePagerActivity.EXTRA_IMAGE_INDEX, position); 
    mContext.startActivity(intent); 
  } 
  // 优化listview 
  private static class ViewHolder { 
    public TextView name; 
    public ImageView avator; 
    TextView content; 
    NoScrollGridView gridView; 
  } 
}

  2  主界面

   实际项目中数据是数据是从服务器获取的,本次就只将图片从网络获取,


public class MainActivity extends ListActivity { 
  public static final String TAG = "MainActivity"; 
  private FridListAdapter mAdapter; 
  @Override 
  public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    new LoderDataTask().execute(); 
  } 
  class LoderDataTask extends AsyncTask<Void, Void, MessageModle> { 
    @Override 
    protected MessageModle doInBackground(Void... params) { 
      Gson gson = new Gson(); 
      MessageModle msg = gson.fromJson(getData(), MessageModle.class); 
      return msg; 
    } 
    @Override 
    protected void onPostExecute(MessageModle result) { 
      mAdapter = new FridListAdapter(MainActivity.this, result.list); 
      setListAdapter(mAdapter); 
    } 
  } 
  private String getData() { 
    // 模拟网络获取数据 
    String json = "{\"code\":200,\"msg\":\"ok\",list:[" 
        + "{\"id\":110,\"avator\":\"http://img0.bdstatic.com/img/image/shouye/leimu/mingxing.jpg\",\"name\":\"赵薇\",\"content\":\"今天不开心!\",\"urls\":[]}," 
        + "{\"id\":111,\"avator\":\"http://image.cnwest.com/attachement/jpg/site1/20110507/001372d8a36f0f2f4c953a.jpg\",\"name\":\"李晨\",\"content\":\"我们\"," 
        + " \"urls\":[\"http://guangdong.sinaimg.cn/2015/0530/U11307P693DT20150530094310.jpg\"]}," 
        + "{\"id\":114,\"avator\":\"http://img.hexun.com/2009-05-01/117287830.jpg\",\"name\":\"小马哥\",\"content\":\"今天淘宝了吗\",\"urls\":[" 
        + "\"http://g.hiphotos.bdimg.com/album/s%3D680%3Bq%3D90/sign=ccd33b46d53f8794d7ff4b26e2207fc9/0d338744ebf81a4c0f993437d62a6059242da6a1.jpg\"," 
        + "\"http://f.hiphotos.bdimg.com/album/s%3D680%3Bq%3D90/sign=6b62f61bac6eddc422e7b7f309e0c7c0/6159252dd42a2834510deef55ab5c9ea14cebfa1.jpg\"," 
        + "\"http://g.hiphotos.bdimg.com/album/s%3D680%3Bq%3D90/sign=e58fb67bc8ea15ce45eee301863b4bce/a5c27d1ed21b0ef4fd6140a0dcc451da80cb3e47.jpg\"," 
        + "\"http://c.hiphotos.bdimg.com/album/s%3D680%3Bq%3D90/sign=cdab1512d000baa1be2c44b3772bc82f/91529822720e0cf3855c96050b46f21fbf09aaa1.jpg\"]}," 
        + "{\"id\":112,\"avator\":\"http://img3.yxlady.com/yl/UploadFiles_5361/20150528/20150528050208705.jpg\",\"name\":\"邓超\",\"content\":\"奔跑吧兄弟! 欢迎收看!\",\"urls\":[\"http://upload.cbg.cn/2015/0305/1425518659246.jpg\"," 
        + "\"http://www.people.com.cn/mediafile/pic/20150619/30/4179219540177204330.jpg\"]}," 
        + "{\"id\":113,\"avator\":\"http://img4.imgtn.bdimg.com/it/u=945108765,1070109457&fm=21&gp=0.jpg\",\"name\":\"奥巴马\",\"content\":\"holle\",\"urls\":[\"http://f.hiphotos.bdimg.com/album/s%3D680%3Bq%3D90/sign=6b62f61bac6eddc422e7b7f309e0c7c0/6159252dd42a2834510deef55ab5c9ea14cebfa1.jpg\",\"http://g.hiphotos.bdimg.com/album/s%3D680%3Bq%3D90/sign=e58fb67bc8ea15ce45eee301863b4bce/a5c27d1ed21b0ef4fd6140a0dcc451da80cb3e47.jpg\",\"http://c.hiphotos.bdimg.com/album/s%3D680%3Bq%3D90/sign=cdab1512d000baa1be2c44b3772bc82f/91529822720e0cf3855c96050b46f21fbf09aaa1.jpg\"]}]}"; 
    return json; 
  } 

  3 GridView的Adapter

     因为Listview的条目中包含Gridview,在这里还需要为它创建atapter

    由于adapter没太多技术含量,因此重点部分列出,在这里我们需要判断下适配的数据眼总数,微信最大数是9张,显示一张的时候,图片比较大,两张的时候稍微减少,四张的时候两列两行和两张的大小一致,其他张数的时候都是三行三列的九宫格。


@Override 
  public View getView(int position, View convertView, ViewGroup parent) { 
    MyGridViewHolder viewHolder; 
    if (convertView == null) { 
      viewHolder = new MyGridViewHolder(); 
      convertView = mLayoutInflater.inflate(R.layout.gridview_item, 
          parent, false); 
      viewHolder.imageView = (ImageView) convertView 
          .findViewById(R.id.album_image); 
      convertView.setTag(viewHolder); 
    } else { 
      viewHolder = (MyGridViewHolder) convertView.getTag(); 
    } 
    String url = getItem(position); 
    if (getCount() == 1) { 
      viewHolder.imageView.setLayoutParams(new android.widget.AbsListView.LayoutParams(300, 250)); 
    } 
    if (getCount() == 2 ||getCount() == 4) { 
      viewHolder.imageView.setLayoutParams(new android.widget.AbsListView.LayoutParams(200, 200)); 
    } 
    ImageLoader.getInstance().displayImage(url, viewHolder.imageView); 
    return convertView; 
  } 

   4  新建用于支持九宫格自定义的Gridview


public class NoScrollGridView extends GridView { 
  public NoScrollGridView(Context context) { 
    super(context); 
  } 
  public NoScrollGridView(Context context, AttributeSet attrs) { 
    super(context, attrs); 
  } 
  @Override 
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
    int expandSpec = 0; 
    int size = getAdapter().getCount(); 
    if (size == 1) { 
      setNumColumns(1); 
    }  
    if ( size==2 || size == 4 ) { 
      setNumColumns(2); 
    } 
    else { 
      setNumColumns(3); 
    } 
    expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,MeasureSpec.AT_MOST); 
    super.onMeasure(widthMeasureSpec,expandSpec ); 
  } 
} 

三 点击图片后的基础类

   1 建立大图查看器viewpaer


public class ImagePagerActivity extends FragmentActivity { 
  private static final String STATE_POSITION = "STATE_POSITION"; 
  public static final String EXTRA_IMAGE_INDEX = "image_index"; 
  public static final String EXTRA_IMAGE_URLS = "image_urls"; 
  private HackyViewPager mPager; 
  private int pagerPosition; 
  private TextView indicator; 
  @Override 
  public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.image_detail_pager); 
    pagerPosition = getIntent().getIntExtra(EXTRA_IMAGE_INDEX, 0); 
    String[] urls = getIntent().getStringArrayExtra(EXTRA_IMAGE_URLS); 
    mPager = (HackyViewPager) findViewById(R.id.pager); 
    ImagePagerAdapter mAdapter = new ImagePagerAdapter( 
        getSupportFragmentManager(), urls); 
    mPager.setAdapter(mAdapter); 
    indicator = (TextView) findViewById(R.id.indicator); 
    CharSequence text = getString(R.string.viewpager_indicator, 1, mPager 
        .getAdapter().getCount()); 
    indicator.setText(text); 
    // 更新下标 
    mPager.setOnPageChangeListener(new OnPageChangeListener() { 
      @Override 
      public void onPageScrollStateChanged(int arg0) { 
      } 
      @Override 
      public void onPageScrolled(int arg0, float arg1, int arg2) { 
      } 
      @Override 
      public void onPageSelected(int arg0) { 
        CharSequence text = getString(R.string.viewpager_indicator, 
            arg0 + 1, mPager.getAdapter().getCount()); 
        indicator.setText(text); 
      } 
    }); 
    if (savedInstanceState != null) { 
      pagerPosition = savedInstanceState.getInt(STATE_POSITION); 
    } 
    mPager.setCurrentItem(pagerPosition); 
  } 
  @Override 
  public void onSaveInstanceState(Bundle outState) { 
    outState.putInt(STATE_POSITION, mPager.getCurrentItem()); 
  } 
  private class ImagePagerAdapter extends FragmentStatePagerAdapter { 
    public String[] fileList; 
    public ImagePagerAdapter(FragmentManager fm, String[] fileList) { 
      super(fm); 
      this.fileList = fileList; 
    } 
    @Override 
    public int getCount() { 
      return fileList == null ? 0 : fileList.length; 
    } 
    @Override 
    public Fragment getItem(int position) { 
      String url = fileList[position]; 
      return ImageDetailFragment.newInstance(url); 
    } 
  } 

2 查看大图界面


public class ImageDetailFragment extends Fragment { 
  private String mImageUrl; 
  private ImageView mImageView; 
  private ProgressBar progressBar; 
  private PhotoViewAttacher mAttacher; 
  public static ImageDetailFragment newInstance(String imageUrl) { 
    final ImageDetailFragment f = new ImageDetailFragment(); 
    final Bundle args = new Bundle(); 
    args.putString("url", imageUrl); 
    f.setArguments(args); 
    return f; 
  } 
  @Override 
  public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    mImageUrl = getArguments() != null ? getArguments().getString("url") : null; 
  } 
  @Override 
  public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
    final View v = inflater.inflate(R.layout.image_detail_fragment, container, false); 
    mImageView = (ImageView) v.findViewById(R.id.image); 
    mAttacher = new PhotoViewAttacher(mImageView); 
    mAttacher.setOnPhotoTapListener(new OnPhotoTapListener() { 
      @Override 
      public void onPhotoTap(View arg0, float arg1, float arg2) { 
        getActivity().finish(); 
      } 
    }); 
    progressBar = (ProgressBar) v.findViewById(R.id.loading); 
    return v; 
  } 
  @Override 
  public void onActivityCreated(Bundle savedInstanceState) { 
    super.onActivityCreated(savedInstanceState); 
    ImageLoader.getInstance().displayImage(mImageUrl, mImageView, new SimpleImageLoadingListener() { 
      @Override 
      public void onLoadingStarted(String imageUri, View view) { 
        progressBar.setVisibility(View.VISIBLE); 
      } 
      @Override 
      public void onLoadingFailed(String imageUri, View view, FailReason failReason) { 
        String message = null; 
        switch (failReason.getType()) { 
        case IO_ERROR: 
          message = "下载错误"; 
          break; 
        case DECODING_ERROR: 
          message = "图片无法显示"; 
          break; 
        case NETWORK_DENIED: 
          message = "网络有问题,无法下载"; 
          break; 
        case OUT_OF_MEMORY: 
          message = "图片太大无法显示"; 
          break; 
        case UNKNOWN: 
          message = "未知的错误"; 
          break; 
        } 
        Toast.makeText(getActivity(), message, Toast.LENGTH_SHORT).show(); 
        progressBar.setVisibility(View.GONE); 
      } 
      @Override 
      public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) { 
        progressBar.setVisibility(View.GONE); 
        mAttacher.update(); 
      } 
    }); 
  } 

     四  界面的头像圆形

      圆形头像用主流的circleimageview.jar的框架,但是有兴趣的朋友也可以自定义Imagview采用重写onDrawI()画圆形的方式将bitmap画上去,由于此demo整体功能较复杂,因此使用第三方的东西,ListView条目布局如下:


 <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:padding="6dp" > 
  <de.hdodenhof.circleimageview.CircleImageView 
    android:id="@+id/avator" 
    android:layout_width="48dp" 
    android:layout_height="48dp" 
    android:class="lazy" data-src="@drawable/empty_photo" /> 
  <TextView 
    android:id="@+id/name" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:layout_marginLeft="10dp" 
    android:layout_toRightOf="@id/avator" 
    android:textColor="#576B95" 
    android:textSize="16sp" 
    android:text="name" /> 
  <TextView 
    android:id="@+id/content" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:layout_below="@+id/name" 
    android:layout_marginLeft="10dp" 
    android:textSize="12sp" 
    android:layout_toRightOf="@id/avator" 
    android:text="content" /> 
  <com.loveplusplus.demo.image.NoScrollGridView 
    android:id="@+id/gridView" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:paddingTop="5dp" 
    android:layout_below="@id/content" 
    android:layout_marginLeft="10dp" 
    android:layout_toRightOf="@id/avator" 
    android:horizontalSpacing="1dp" 
    android:numColumns="3" 
    android:visibility="gone" 
    android:verticalSpacing="1dp" /> 
</RelativeLayout> 

   接下来我们还需要将主流的photoView.jar加入到工程中,

   总结一下实现以上功能我们使用了第三的imagloader,支持手势缩放的PhotoView,圆形图像的circleimageView,熟悉安卓view绘制机制加载过程,事件传递和分发的朋友是不需要第三方开源项目的支持的,但是对于入门不久的同学,学会怎样使用开源框架就可以,但是想要提高开源项目的的核心还是需要了解的,欢迎阅读

  运行效果图:

 

  有兴趣的朋友建议阅读下:

     安卓事件机制(一)和上篇关于View的博文。谢谢交流和分享。

demo源码下载地址:https://github.com/Tamicer/CHatMomentDemo

以上所述是小编给大家介绍的Android 高仿微信朋友圈动态支持双击手势放大并滑动查看图片效果,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对编程网网站的支持!

您可能感兴趣的文章:Android实现Banner界面广告图片循环轮播(包括实现手动滑动循环)Android开发之使用ViewPager实现图片左右滑动切换效果Android实现图片自动轮播并且支持手势左右无限滑动Android实现手势滑动多点触摸放大缩小图片效果Android手势滑动实现ImageView缩放图片大小解决Android快速滑动时图片一闪一闪问题Android中RecyclerView 滑动时图片加载的优化Android 使用ViewPager实现图片左右循环滑动自动播放Android 利用ViewPager实现图片可以左右循环滑动效果附代码下载Android利用ViewPager实现带小圆球的图片滑动


免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Android 高仿微信朋友圈动态支持双击手势放大并滑动查看图片效果

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Android 高仿微信朋友圈动态支持双击手势放大并滑动查看图片效果

最近参与了开发一款旅行APP,其中包含实时聊天和动态评论功能,终于耗时几个月几个伙伴完成了,今天就小结一下至于实时聊天功能如果用户不多的情况可以scoket实现,如果用户万级就可以采用开源的smack + opnefile实现,也可以用mi
2022-06-06

编程热搜

  • Android:VolumeShaper
    VolumeShaper(支持版本改一下,minsdkversion:26,android8.0(api26)进一步学习对声音的编辑,可以让音频的声音有变化的播放 VolumeShaper.Configuration的三个参数 durati
    Android:VolumeShaper
  • Android崩溃异常捕获方法
    开发中最让人头疼的是应用突然爆炸,然后跳回到桌面。而且我们常常不知道这种状况会何时出现,在应用调试阶段还好,还可以通过调试工具的日志查看错误出现在哪里。但平时使用的时候给你闹崩溃,那你就欲哭无泪了。 那么今天主要讲一下如何去捕捉系统出现的U
    Android崩溃异常捕获方法
  • android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
    系统的设置–>电池–>使用情况中,统计的能耗的使用情况也是以power_profile.xml的value作为基础参数的1、我的手机中power_profile.xml的内容: HTC t328w代码如下:
    android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
  • Android SQLite数据库基本操作方法
    程序的最主要的功能在于对数据进行操作,通过对数据进行操作来实现某个功能。而数据库就是很重要的一个方面的,Android中内置了小巧轻便,功能却很强的一个数据库–SQLite数据库。那么就来看一下在Android程序中怎么去操作SQLite数
    Android SQLite数据库基本操作方法
  • ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
    工作的时候为了方便直接打开编辑文件,一些常用的软件或者文件我们会放在桌面,但是在ubuntu20.04下直接直接拖拽文件到桌面根本没有效果,在进入桌面后发现软件列表中的软件只能收藏到面板,无法复制到桌面使用,不知道为什么会这样,似乎并不是很
    ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
  • android获取当前手机号示例程序
    代码如下: public String getLocalNumber() { TelephonyManager tManager =
    android获取当前手机号示例程序
  • Android音视频开发(三)TextureView
    简介 TextureView与SurfaceView类似,可用于显示视频或OpenGL场景。 与SurfaceView的区别 SurfaceView不能使用变换和缩放等操作,不能叠加(Overlay)两个SurfaceView。 Textu
    Android音视频开发(三)TextureView
  • android获取屏幕高度和宽度的实现方法
    本文实例讲述了android获取屏幕高度和宽度的实现方法。分享给大家供大家参考。具体分析如下: 我们需要获取Android手机或Pad的屏幕的物理尺寸,以便于界面的设计或是其他功能的实现。下面就介绍讲一讲如何获取屏幕的物理尺寸 下面的代码即
    android获取屏幕高度和宽度的实现方法
  • Android自定义popupwindow实例代码
    先来看看效果图:一、布局
  • Android第一次实验
    一、实验原理 1.1实验目标 编程实现用户名与密码的存储与调用。 1.2实验要求 设计用户登录界面、登录成功界面、用户注册界面,用户注册时,将其用户名、密码保存到SharedPreference中,登录时输入用户名、密码,读取SharedP
    Android第一次实验

目录