Android 个人理财工具三:添加账单页面 上

ColaBox 登记收支记录终于进入了复杂阶段了。这个界面我也是查找了很多资料以及打开android的源代码看了后才完成了,现在想来Google的开源真是明智的啊。

从前面的登录页面跳转进入添加账单页面。这个页面主要是用来登记收支记录的。说白了就是往数据库录入明细。

表结构如下:

db.execSQL("CREATE TABLE bills ("
                 + "_ID INTEGER PRIMARY KEY," //id
                 + "fee integer,"                                     //费用
                 +"acctitemid integer,"                          //账目类型
                 + "userid integer,"                                //使用者
                 + "sdate TEXT,"                                 //日期
                 + "stime TEXT,"                                //时间
                 + "desc TEXT"                                  //备注
                 + ");");

可以看到主要是录入这些数据。首先是布置界面,我目前想到的用个tablelayout来布局。

最后布局就是如下图(图1)这样:

在这儿我首先需要设置账目,前面我们已经初始化过账目的数据。

账目应该是一个ExpandableListActivity 2层的结构。需要从数据库里面读取。我在账目后面放了一个editview 只读没有光标的,也就是在这儿不可录入,在该editview的onclick事件里面我们打开账目选择界面。如下图:

图2 账目选择:

在这个界面中点击子节点就返回前面界面,把选择的账目传递过去。在这有个问题,如果用户需要录入的账目没有怎么办?

所以我这没有用dialog方式而是用了ExpandableListActivity。在这个界面中如果长点某个子节点就弹出管理账目菜单,来维护账目,如下图所示:

图3 账目选择菜单:

图4 编辑账目:

上面这些流程说起来很简单,可是当我用andriod编写时,遇到了很多问题,不过一个个都被我解决了,这正是编程的快乐所在。

关于ExpandableListActivity 大家可以参考android 里面apidemos 里面ExpandableList1、ExpandableList2、ExpandableList3。

这里面对熟悉这个ui还是很有帮助的。在ExpandableList2 里面就是从数据库进行读取的例子。当然android里面那个我是没太看明白因为他引用了import android.provider.Contacts.People; 联系人部分的框架,而我目前对数据库的操作和他不一样,我都是直接sql访问。

但是你只要搞定2个cursor就ok了,Cursor groupCursor childCursor ,其他都由SimpleCursorTreeAdapter帮你实现了。

下面我们来看看如何使用SimpleCursorTreeAdapter。

Java代码

//首先要实现groupcursor就是父节点游标,这个其实就是我的acctitem表的
//select * from accitem where pid is null 的结果
Cursor groupCursor = billdb.getParentNode();
  // Cache the ID column index
mGroupIdColumnIndex = groupCursor.getColumnIndexOrThrow("_ID");
  // Set up our adapter
mAdapter = new MyExpandableListAdapter(groupCursor, this,  android.R.layout.simple_expandable_list_item_1,
 android.R.layout.simple_expandable_list_item_1,
  new String[] { "NAME" }, // Name for group layouts
  new int[] { android.R.id.text1 },
  new String[] { "NAME" }, //
  new int[] { android.R.id.text1 });
setListAdapter(mAdapter);
//然后我要实现childCursor
//其实就是select * from acctitem where id=pid 的结果
public class MyExpandableListAdapter extends SimpleCursorTreeAdapter {
public MyExpandableListAdapter(Cursor cursor, Context context,
    int groupLayout, int childLayout, String[] groupFrom,
    int[] groupTo, String[] childrenFrom, int[] childrenTo)
 {
   super(context, cursor, groupLayout, groupFrom, groupTo,
     childLayout, childrenFrom, childrenTo);
 }
protected Cursor getChildrenCursor(Cursor groupCursor) {
 String pid = groupCursor.getLong(mGroupIdColumnIndex) + "";
 // Log.v("cola","pid="+pid);
 return billdb.getChildenNode(pid);
 }
}
//我们看看Billdbhelper里面的cursor
 public Cursor getParentNode(){
  return db.query("acctitem", new String[]{"_id", "name" }, "pid is null", null, null, null, "pid,_id");  

 } 

 public Cursor getChildenNode(String pid){
  Log.v("cola","run getchildenNode");
  return db.query("acctitem", new String[]{"_id", "name" }, "pid="+pid, null, null, null, "_id");
 }
//只要这几步一个2级的tree list就可以出现了.

上面其实才是刚开始,后面我们需要使用一个自定义的Dialog 类似于一个inputBox,因为我们新增账目是需要输入账目的名称。就是上面图4表现的。

虽然alertDialog提供了很多方法,可以选择list、treelist、radio,可惜就是不能录入text。

这里我参考了api demos 里面的 DateWidgets1.java 和源代码里面DatePickerDialog.java 。

我们可以从alertdialog 继承,然后添加一个Editview 最后把数据返回出来。只要把上面我说的2个java看清楚了后处理起来就简单了。

主要是一个回调函数的用法。下面看代码:

Java代码

//
public class Dialog_edit extends AlertDialog implements OnClickListener {
 private String text = "";
 private EditText edit;
 private OnDateSetListener mCallback; //定义回调函数
 private LinearLayout layout;
 public interface OnDateSetListener { //回调接口
  void onDateSet(String text);
 }
 protected Dialog_edit(Context context, String title, String value,
   OnDateSetListener Callback) {
  super(context);
  mCallback = Callback;
  TextView label = new TextView(context);
  label.setText("hint");
  // setView(label);
  edit = new EditText(context);
  edit.setText(value);
  layout = new LinearLayout(context);
  layout.setOrientation(LinearLayout.VERTICAL);
  // LinearLayout.LayoutParams param =
  // new LinearLayout.LayoutParams(100, 40);
  // layout.addView(label, param);
  LinearLayout.LayoutParams param2 = new LinearLayout.LayoutParams(200,
    50);
  layout.addView(edit, param2);
  //添加edit
  setView(layout);
  setTitle(title);
  setButton("确定", this);
  setButton2("取消", (OnClickListener) null);
 }
 public void onClick(DialogInterface dialog, int which) {
  // Log.v("cola","U click which="+which);
  text = edit.getText().toString();
  Log.v("cola", "U click text=" + text);
  if (mCallback != null)
   mCallback.onDateSet(text); //使用回调返回录入的数据
 }
}

这样我们就完成了自定义的dialog 我们可以使用它来新增和编辑账目。对于账目的增删改就是sql的事情了。

在这我又遇到一个问题就是我新增一个账目后如何来刷新界面,从而反映账目修改后的变化。

在这我开始以为只要使用getExpandableListView().invalidate(); 就可以了。

因为我之前在ExpandableList1.java例子里面,使用它可以刷新界面。

在那个例子里面我修改了数组后调用该方法,界面就刷新了,而在这SimpleCursorTreeAdapter就行不通了,我想

应该只要刷新cursor应该就可以了,后来找到了notifyDataSetChanged,呵呵,果然可以了。 这样账目的录入和管理就搞定了。

下面给出目前最新的代码。

首先是账目管理:

Java代码

package com.cola.ui;
import android.app.AlertDialog;
import android.app.ExpandableListActivity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.Contacts.People;
import android.util.Log;
import android.view.ContextMenu;
import android.view.MenuItem;
import android.view.View;
import android.view.ContextMenu.ContextMenuInfo;
import android.widget.ExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.SimpleCursorTreeAdapter;
import android.widget.TextView;
import android.widget.ExpandableListView.ExpandableListContextMenuInfo;
/**
 * Demonstrates expandable lists backed by Cursors
 */
public class Frm_Editacctitem extends ExpandableListActivity {
 private int mGroupIdColumnIndex;
 private String mPhoneNumberProjection[] = new String[] { People.Phones._ID,
   People.Phones.NUMBER };
 private ExpandableListAdapter mAdapter;
 BilldbHelper billdb;
 Dialog_edit newdialog; 

 private ExpandableListContextMenuInfo info; 

 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setTitle("ColaBox-选择账目");
  billdb = new BilldbHelper(this);
  // Query for people
  Cursor groupCursor = billdb.getParentNode();
  // Cache the ID column index
  mGroupIdColumnIndex = groupCursor.getColumnIndexOrThrow("_ID");
  // Set up our adapter
  mAdapter = new MyExpandableListAdapter(groupCursor, this,
    android.R.layout.simple_expandable_list_item_1,
    android.R.layout.simple_expandable_list_item_1,
    new String[] { "NAME" }, // Name for group layouts
    new int[] { android.R.id.text1 }, new String[] { "NAME" }, //
    new int[] { android.R.id.text1 });
  setListAdapter(mAdapter);
  registerForContextMenu(getExpandableListView());
 } 

 @Override
 public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id)
 {
  Bundle bundle = new Bundle();
  bundle.putString("DataKey", ((TextView)v).getText().toString());//给bundle 写入数据
  Intent mIntent = new Intent();
  mIntent.putExtras(bundle);
  setResult(RESULT_OK, mIntent);
  billdb.close();
  finish();
  return true;
 }
 @Override
 public void onCreateContextMenu(ContextMenu menu, View v,
   ContextMenuInfo menuInfo) {
  super.onCreateOptionsMenu(menu);
  if (ExpandableListView
    .getPackedPositionType(((ExpandableListContextMenuInfo) menuInfo).packedPosition) == 1) {
   Log.v("cola", "run menu");
   menu.setHeaderTitle("菜单");
   menu.add(0, 1, 0, "新 增");
   menu.add(0, 2, 0, "删 除");
   menu.add(0, 3, 0, "编 辑");
  }
 }
 @Override
 public boolean onContextItemSelected(MenuItem item) {
  info = (ExpandableListContextMenuInfo) item.getMenuInfo();
  if (item.getItemId() == 1) {
   // Log.v("cola","id"+info.id);
   newdialog = new Dialog_edit(this, "请输入新增账目的名称", "",
     mDialogClick_new);
   newdialog.show();
  } else if (item.getItemId() == 2) {
   new AlertDialog.Builder(this).setTitle("提示").setMessage("确定要删除'"+((TextView)info.targetView).getText().toString()+"'这个账目吗?")
     .setIcon(R.drawable.quit).setPositiveButton("确定",
       new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog,
          int whichButton) {
         billdb.Acctitem_delitem((int)info.id);
         updatedisplay();
        }
       }).setNegativeButton("取消",
       new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog,
          int whichButton) {
         // 取消按钮事件
        }
       }).show();
  } else if (item.getItemId() == 3) {
   newdialog = new Dialog_edit(this, "请修改账目名称",
     ((TextView) info.targetView).getText().toString(),
     mDialogClick_edit);
   newdialog.show();
  }
  return false;
 }
 private Dialog_edit.OnDateSetListener mDialogClick_new = new Dialog_edit.OnDateSetListener() {
  public void onDateSet(String text) {
   Log.v("cola", "new acctitem");
   billdb.Acctitem_newitem(text,ExpandableListView.getPackedPositionGroup(info.packedPosition));
   updatedisplay();
  }
 }; 

 private Dialog_edit.OnDateSetListener mDialogClick_edit = new Dialog_edit.OnDateSetListener() {
  public void onDateSet(String text) {
   billdb.Acctitem_edititem(text,(int)info.id);
   updatedisplay();
  }
 };
 private void updatedisplay(){
  Log.v("cola", "update display");
  ((MyExpandableListAdapter)mAdapter).notifyDataSetChanged();
 } 

 public class MyExpandableListAdapter extends SimpleCursorTreeAdapter {
  public MyExpandableListAdapter(Cursor cursor, Context context,
    int groupLayout, int childLayout, String[] groupFrom,
    int[] groupTo, String[] childrenFrom, int[] childrenTo) {
   super(context, cursor, groupLayout, groupFrom, groupTo,
     childLayout, childrenFrom, childrenTo);
  }
  @Override
  protected Cursor getChildrenCursor(Cursor groupCursor) {
   String pid = groupCursor.getLong(mGroupIdColumnIndex) + "";
   // Log.v("cola","pid="+pid);
   return billdb.getChildenNode(pid);
  }
  @Override
  public long getGroupId(int groupPosition) {
   // Log.v("cola", "getGroupId " + groupPosition);
   Cursor groupCursor = (Cursor) getGroup(groupPosition);
   return groupCursor.getLong(mGroupIdColumnIndex);
  }
  @Override
  public long getChildId(int groupPosition, int childPosition) {
   // Log.v("cola", "getChildId " + groupPosition + "," +
   // childPosition);
   Cursor childCursor = (Cursor) getChild(groupPosition, childPosition);
   return childCursor.getLong(0);
  }
 }
}

自定义对话框:

Java代码

package com.cola.ui;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.util.Log;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
public class Dialog_edit extends AlertDialog implements OnClickListener {
 private String text = "";
 private EditText edit;
 private OnDateSetListener mCallback;
 private LinearLayout layout;
 public interface OnDateSetListener {
  void onDateSet(String text);
 }
 protected Dialog_edit(Context context, String title, String value,
   OnDateSetListener Callback) {
  super(context);
  mCallback = Callback;
  TextView label = new TextView(context);
  label.setText("hint");
  // setView(label);
  edit = new EditText(context);
  edit.setText(value);
  layout = new LinearLayout(context);
  layout.setOrientation(LinearLayout.VERTICAL);
  // LinearLayout.LayoutParams param =
  // new LinearLayout.LayoutParams(100, 40);
  // layout.addView(label, param);
  LinearLayout.LayoutParams param2 = new LinearLayout.LayoutParams(200,
    50);
  layout.addView(edit, param2);
  setView(layout);
  setTitle(title);
  setButton("确定", this);
  setButton2("取消", (OnClickListener) null);
 }
 public void onClick(DialogInterface dialog, int which) {
  // Log.v("cola","U click which="+which);
  text = edit.getText().toString();
  Log.v("cola", "U click text=" + text);
  if (mCallback != null)
   mCallback.onDateSet(text);
 }
}

数据库管理代码:

Java代码

package com.cola.ui;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
/**
 * Provides access to a database of notes. Each note has a title, the note
 * itself, a creation date and a modified data.
 */
public class BilldbHelper {
 private static final String TAG = "Cola_BilldbHelper";
 private static final String DATABASE_NAME = "cola.db"; 

 SQLiteDatabase db;
 Context context; 

 BilldbHelper(Context _context) {
  context=_context;
  db=context.openOrCreateDatabase(DATABASE_NAME, 0, null);
  Log.v(TAG,"db path="+db.getPath());
 } 

 public void CreateTable_acctitem() {
  try{
   db.execSQL("CREATE TABLE acctitem ("
     + "_ID INTEGER PRIMARY KEY,"
     + "PID integer,"
     + "NAME TEXT"
     + ");");
   Log.v("cola","Create Table acctitem ok");
  }catch(Exception e){
   Log.v("cola","Create Table acctitem err,table exists.");
  }
 } 

 public void CreateTable_bills() {
  try{
   db.execSQL("CREATE TABLE bills ("
     + "_ID INTEGER PRIMARY KEY,"
     +" acctitemid integer,"
     + "fee integer,"
     + "userid integer,"
     + "sdate TEXT,"
     + "stime TEXT,"
     + "desc TEXT"
     + ");"); 

   Log.v("cola","Create Table acctitem ok");
  }catch(Exception e){
   Log.v("cola","Create Table acctitem err,table exists.");
  }
 } 

 public void CreateTable_colaconfig() {
  try{
   db.execSQL("CREATE TABLE colaconfig ("
     + "_ID INTEGER PRIMARY KEY,"
     + "NAME TEXT"
     + ");");
   Log.v("cola","Create Table colaconfig ok");
  }catch(Exception e){
   Log.v("cola","Create Table acctitem err,table exists.");
  }
 } 

 public void InitAcctitem() {
  try{
   //s.getBytes(encoding);
   db.execSQL("insert into acctitem values (1,null,'收入')");
   db.execSQL("insert into acctitem values (2,1,'工资')");
   db.execSQL("insert into acctitem values (9998,1,'其他')");
   db.execSQL("insert into acctitem values (0,null,'支出')");
   db.execSQL("insert into acctitem values (3,0,'生活用品')");
   db.execSQL("insert into acctitem values (4,0,'水电煤气费')");
   db.execSQL("insert into acctitem values (5,0,'汽油费')");
   db.execSQL("insert into acctitem values (9999,0,'其他')"); 

   //db.execSQL("insert into bills values(100,135,10000,'','','备注')");
   Log.v("cola","insert into ok");
  }catch(Exception e)
  {
   Log.v("cola","init acctitem e="+e.getMessage());
  } 

 }
 public void Acctitem_newitem(String text,int type){ 

  Cursor c =db.query("acctitem", new String[]{"max(_id)+1"}, "_id is not null and _id<9998", null, null, null, null);
  c.moveToFirst();
  int maxid=c.getInt(0);
  String sql="insert into acctitem values ("+maxid+","+type+",'"+text+"')";
  db.execSQL(sql);
  Log.v("cola","newitem ok text="+text+" id="+type+" sql="+sql); 

 } 

 public void Acctitem_edititem(String text,int id){
  db.execSQL("update acctitem set name='"+text+"' where _id="+id);
  Log.v("cola","edititem ok text="+text+" id="+id);
 } 

 public void Acctitem_delitem(int id){ 

  db.execSQL("delete from acctitem where _id="+id);
  Log.v("cola","delitem ok id="+id);
 } 

 public void QueryTable_acctitem(){ 

 } 

 public void FirstStart(){
  try{
   String col[] = {"type", "name" };
   Cursor c =db.query("sqlite_master", col, "name='colaconfig'", null, null, null, null);
   int n=c.getCount();
   if (c.getCount()==0){
    CreateTable_acctitem();
    CreateTable_colaconfig();
    CreateTable_bills();
    InitAcctitem();
   }
   //getTree();
   Log.v("cola","c.getCount="+n+""); 

  }catch(Exception e){
   Log.v("cola","e="+e.getMessage());
  } 

 } 

 public void close(){
  db.close();
 } 

 public Cursor getParentNode(){
  return db.query("acctitem", new String[]{"_id", "name" }, "pid is null", null, null, null, "pid,_id");   

 } 

 public Cursor getChildenNode(String pid){
  Log.v("cola","run getchildenNode");
  return db.query("acctitem", new String[]{"_id", "name" }, "pid="+pid, null, null, null, "_id");
 } 

}

系列文章:

Android 个人理财工具六:显示账单明细 下

Android 个人理财工具五:显示账单明细 上

Android 个人理财工具四:添加账单页面 下

Android 个人理财工具三:添加账单页面 上

Android 个人理财工具二:使用SQLite实现启动时初始化数据

Android 个人理财工具一:项目概述与启动界面的实现

以上就Android 开发个人理财工具 添加账单页面的讲解,后续继续更新相应文章,谢谢大家对本站的支持!

(0)

相关推荐

  • Android 应用中插入广告的实例

    想必大家都知道,国内的Android应用基本都是免费的,那么开发者如何获得收入呢?应用中插入广告是一个比较常用的盈利手段.本文就讲解如何在Android应用中插入广告. 国内的广告平台有很多,用户数量比较多的有万普,有米,多普.下面就不一一介绍了,免得说我打广告.本文以万普为例.   1.首先去万普官网下载sdk,把sdk里面的jar包导入到项目的lib目录下.        2.修改AndroidManifest.xml文件. 确保应用具有以下几项权限: XML/HTML代码 <uses-pe

  • Android 个人理财工具一:项目概述与启动界面的实现

    从本文开始为大家制作一个Android个人理财工具,并把整个开发过程记录下来,与大家分享.   项目总体介绍 此Android个人理财工具的主要功能是,可以录入日常生活中的各类收入和支出明细,并且可以在每月底能够统计每月各类情况.给出收支关系饼图,月份之间的柱状图等报告. 下图是程序的流程图: 程序可能涉及到的技术: 1.多个视图的切换,参数的传递,intent的使用. 2.Grid 明细的体现. 3.sqlite数据的操作. 4.自绘view 来表现统计图. 先写这些.        启动界面

  • Android 个人理财工具六:显示账单明细 下

    上一节的显示账单明细 上中,账单明细的显示已经基本实现,本文主要整理下代码,实现此窗口的查询和删除功能:按下Menu菜单时弹出选择月份的窗口,可选择明细的月份:在ListView上长按可弹出确认删除的对话框,以完成删除. 下面上图: 这里面有个OnItemLongClickListener 事件,这个事件的用法如下: 首先activity 里面implements OnItemLongClickListener,然后如下面的代码所写: Java代码 // 这里listview 添加侦听事件 lv

  • Android 个人理财工具四:添加账单页面 下

    本文考虑把账单界面整理下,实现如下图中的功能.做之前感觉应该不难,但实际做时发现排列界面布局甚至比编写程序代码还要复杂.网上搜索发现,关于这种布局的资料能用的很少,Google Demo中用的最多的就是Listview了,但本实例的界面似乎要复杂一些. spinner和cursor如何配合使用成了完成此实例过程中的难点,本来应该很简单,但却把我郁闷坏了. 先给大家贴上最终的效果图片: 界面的xml: XML/HTML代码 <?xml version="1.0" encoding=

  • Android 音乐播放器的开发实例详解

    本文将引导大家做一个音乐播放器,在做这个Android开发实例的过程中,能够帮助大家进一步熟悉和掌握学过的ListView和其他一些组件.为了有更好的学习效果,其中很多功能我们手动实现,例如音乐播放的快进快退等. 先欣赏下本实例完成后运行的界面效果: 首先我们建立项目,我使用的SDK是Android2.2的,然后在XML中进行布局. 上方是一个ListView用来显示我们的音乐列表,中间是一个SeekBar可以拖动当前音乐的播放进度,之所以用SeekBar而不用ProgressBar是因为我们需

  • Android 个人理财工具五:显示账单明细 上

    前面我们已经将每个月的收支明细存入到SQLite的数据表中,本文将实现从SQLite的数据表中取出这些数据显示为账单明细界面. 下图是最终的效果图: 在设计该界面时我考虑过好几个方案.本来准备使用一个gridview,因为觉得名字很像我需要的东西.可是后来查了一些资料,并且做了点实验,发现和我想象的有些差距.于是采用了目前这种方式.使用Listview. 这个界面布局实际上很简单,就是上面一个表头(Linearlayout),中间一个Listview,下面是一个脚注(Linearlayout).

  • Android开发之ListView、GridView 详解及示例代码

    ListView与GridView是Android开发中的常用控件,它们和Adapter配合使用能够实现很多界面效果.下面分别以实例说明ListView.GridView的用法.        1.ListView的Android开发实例 ListView 是android开发中最常用的控件之一,一般构成列表包括三个元素,ListView:用来展示列表的视图.Adapter:数据与视图连接的桥梁.Data:具体的数据包括字符串 .图片或者控件. 适配器一般有以下几种类型: ArrayAdapte

  • Android 个人理财工具二:使用SQLite实现启动时初始化数据

       关于SQLite sqlite是嵌入式SQL数据库引擎SQLite(SQLite Embeddable SQL Database Engine)的一个扩展.SQLite是一个实现嵌入式SQL数据库引擎小型C语言库(C library),实现了独立的,可嵌入的,零配置的SQL数据库引擎.特性包括:事务操作是原子,一致,孤立,并且持久的,即使在系统崩溃和电源故障之后. 零配置--不需要安装和管理. 实现了绝大多数SQL92标准. 我在多年前就关注sqlite的发展,非常看好sqlite的前景,

  • Android 个人理财工具三:添加账单页面 上

    ColaBox 登记收支记录终于进入了复杂阶段了.这个界面我也是查找了很多资料以及打开android的源代码看了后才完成了,现在想来Google的开源真是明智的啊. 从前面的登录页面跳转进入添加账单页面.这个页面主要是用来登记收支记录的.说白了就是往数据库录入明细. 表结构如下: db.execSQL("CREATE TABLE bills ("                  + "_ID INTEGER PRIMARY KEY," //id          

  • Android 使用版本控制工具时添加忽略文件的方式(详解)

    Android Studio 配合SVN时,添加忽略文件相对简单,首先打开项目的Settings选项,切换到Version Control下的Ignored Files目录,如下图: ignore1.png 点击右上角绿色加号,出现如下对话框: ignore2.png 其中 Ignore specified file选项是忽略指定的文件 Ignore all files under选项是忽略指定文件夹下的文件 Ignore all files matching选项是忽略匹配指定格式的文件 一般需

  • 在PHP站点的页面上添加Facebook评论插件的实例教程

    首先,需要在facebook创建一个APP,创建方法见https://developers.facebook.com/,APP有一项是填写Domain的,这里填写你website的Domain.(APP是绑定domain的,不能乱填) 然后就可以使用facebook comments plugins. 使用facebook comments plugins,可以在页面中插入facebook comments. 生成code方法:https://developers.facebook.com/do

  • Android 中使用 ViewPager实现屏幕页面切换和页面轮播效果

    之前关于如何实现屏幕页面切换,写过一篇博文<Android中使用ViewFlipper实现屏幕切换>,相比ViewFlipper,ViewPager更适用复杂的视图切换,而且Viewpager有自己的adapter,这也让其适应复杂对象,实现数据的动态加载. ViewPager是谷歌官方给我们提供的一个兼容低版本安卓设备的软件包,里面包囊了只有在安卓3.0以上可以使用的api.而viewpager就是其中之一,利用它,我们可以做很多事情,从最简单的导航,到页面菜单等等. 下面我们就展示下Vie

  • SpringBoot定制三种错误页面及错误数据方法示例

    目录 定制错误页面 自定义 error.html 自定义动态错误页面 自定义静态错误页面 定制错误数据 1. 自定义异常处理类 2. 自定义错误属性处理工具 我们知道 Spring Boot 已经提供了一套默认的异常处理机制,但是 Spring Boot 提供的默认异常处理机制却并不一定适合我们实际的业务场景,因此,我们通常会根据自身的需要对 Spring Boot 全局异常进行统一定制,例如定制错误页面,定制错误数据等. 定制错误页面 我们可以通过以下 3 种方式定制 Spring Boot

随机推荐